Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 劫持DOM操作_Javascript_Dom_Audio - Fatal编程技术网

Javascript 劫持DOM操作

Javascript 劫持DOM操作,javascript,dom,audio,Javascript,Dom,Audio,我有个问题。我试图在音频元素发生变化时立即获取其源,而不使其连接到服务器。让我详细说明一下:服务器只允许一个请求(随机生成的内容url),我正在尝试获取该请求,显然我不希望音频元素使用新源重新加载。我目前使用的是一个变异观察者,但没有幸超过onclick的速度(是的,为了不让任何人直接获取源代码,涉及到复杂的js)。代码如下: document.getElementsByTagName('audio')[0].setAttribute("autoplay", false); //not sure

我有个问题。我试图在音频元素发生变化时立即获取其源,而不使其连接到服务器。让我详细说明一下:服务器只允许一个请求(随机生成的内容url),我正在尝试获取该请求,显然我不希望音频元素使用新源重新加载。我目前使用的是一个变异观察者,但没有幸超过
onclick
的速度(是的,为了不让任何人直接获取源代码,涉及到复杂的js)。代码如下:

document.getElementsByTagName('audio')[0].setAttribute("autoplay", false);
//not sure if ^^ makes a difference
audioObserver = new MutationObserver(function (mutations) {
    window.open(mutations[0].target.src);
    //I only listen for one mutation and want to open the url in a new window
    audioObserver.disconnect();
    //don't listen in order to not cause infinite loop
    document.getElementsByTagName('audio')[0].parentNode.removeChild(document.getElementsByTagName('audio')[0]);
    //remove the element in order to avoid reloading
});
observerConfig = {
    attributes: true,
    childList: false,
    characterData: false
};
audioObserver.observe(document.getElementsByTagName('audio')[0], observerConfig);

我对任何实现都很满意,即不一定是MutationObserver。是否真的有可能劫持属性更改

你说得对,
MutationObserver
不能满足你的需要。按照这种工作方式,浏览器在脚本运行时收集变异记录,然后在脚本生成时将这些记录一次性传递给观察者。它几乎是异步的。这就是为什么变异观察者比同步调度的变异事件表现得更好。当观察者运行时,
audio
元素将已经收到URL并开始加载它


假设您正在讨论的
onclick
处理程序设置元素的
.src
属性,您需要为此定义一个自定义setter,以便您可以在
audio
元素的实现处理该值之前拦截该值

您可以在JavaScript中定义如下设置器:

在Chrome中,这将使得以后无法调用原始setter,但听起来您并不担心这一点


修改元素属性的另一种方法是使用
setAttribute
方法。如果您想要截取这个,您可以重新定义元素的
setAttribute
方法

下面是另一个使用
setAttribute
的示例:


当你对一个方法进行修补时,你可以保存原始的方法函数,这可能很有用。

@dave这是如何解决音频重新加载问题的?我发现使用setTimeout占用的CPU太多,这似乎是一项可以通过其他方法完成的任务。也许您可以覆盖onclick函数,但如果没有它,就无法提供太多帮助example@juvian覆盖到什么:)?该函数在获取URL时发挥了神奇的作用,因为这不是服务器端控制的环境,只有客户端可用的环境。操作
preload
属性可能有助于解决此问题,而不会发生任何劫持。我将尝试此功能,并尽快将其标记为答案。顺便说一句,我已经检查了audio元素,它确实有一个preload属性,我也将禁用它。我尝试了它,但它不起作用,它只是返回了audio元素,但是jsfiddle示例似乎起了作用。还有一件事:处理程序确实更改了src属性,因为MutationObserver对象确实有一个属性log(当我尝试它时,它显示了src属性)。我甚至尝试删除它,然后在同一个div中创建另一个音频标记,但仍然不起作用:(在firefox中,我得到:TypeError:无法重新定义不可配置的属性'src',即使我将其设置为可配置,仍然没有发生任何事情(至少ff中没有错误)。
var el = document.getElementsByTagName('audio')[0];
Object.defineProperty(el, 'src', {
    set: function (newSrc) {
        console.log('they set src to ' + newSrc);
    }
});
var el = document.getElementsByTagName('audio')[0];
var origSetAttribute = el.setAttribute;
el.setAttribute = function (name, value) {
    console.log('they set ' + name + ' to ' + value);
    // origSetAttribute.call(el, name, value);
};