javascript - 代理 HTMLElement

标签 javascript proxy html5-video

我想检查库如何处理我传递给它的视频元素,所以我天真地这样做了:

cosnt videoElement = new Proxy(document.querySelector('video'), {
    get(target, key) {
        const name = typeof key === 'symbol'? key.toString() : key;
        console.info(`Accessing video.${ name }`)
        return target[key];
    }
});

但是我得到一个错误:

TypeError: Failed to execute 'contains' on 'Node': parameter 1 is not of type 'Node'.

有没有办法让它工作?


编辑:我获得了一些知识,我用它更新了我的代理作为休闲:

cosnt videoElement = document.querySelector('video');
cosnt proxyElement = new Proxy(videoElement , {
    get(target, key) {
        if (key == '___element___') {
            return video;
        }

        const name = typeof key === 'symbol'? key.toString() : key;
        console.info(`Accessing video.${ name }`);
        const value = video[key];
        if (value instanceof Function) {
            return video[key].bind(video);
        } else {
            return video[key];
        }
    },
    set(target, key, value) {
        const name = typeof key === 'symbol'? key.toString() : key;
        console.info(`Writing video.${ name } = ${ value }`);
        video[key] = value;
        return true;
    }
});

它是为了调试,所以我编辑了编译后的代码,并将所有 DOM 操作引用替换为 element.___element___

接下来我发现通过代理调用函数似乎有问题,所以我添加了 .bind(video) 部分。

最后设置值是抛出。所以我不得不用直接视频引用替换目标(事实上,我用视频替换了所有目标引用,只是为了确定),这让它起作用了......我不确定为什么或如何,但确实如此。

问题是:

  • 这真的应该是这样吗? (document.body.contains(myProxyElement) 部分)
  • 在代理内部设置时将视频元素的值设置为抛出似乎很奇怪,这是一个错误吗? (第三点,有点第二,我想它是连接的)

奖励: Playground

const video = document.querySelector('video');
const proxy = new Proxy(video, {
  get(target, key) {
    console.log(`Getting video.${typeof key === 'symbol'? key.toString() : key}`);
    const value = video[key];
    if (value instanceof Function) {
      return value.bind(video);
    } else {
      return value;
    }
  },
  set(target, key, value) {
    console.log(`Setting video.${typeof key === 'symbol'? key.toString() : key} =`, value);
    video[key] = value;
    return true;
  }
});

proxy.muted = true;
proxy.play();
proxy.controls = true;
try {
  console.log(document.body.contains(proxy));
} catch (e) {
  console.error('DOM operation failed', e);
}
video { max-width: 100%; }
<video src="//vjs.zencdn.net/v/oceans.mp4">

最佳答案

如评论中所述,Proxy 对象在调用 document.body.contains(proxy) 时不会自动转换为 Node >.

因此,您可以设置一个特定的键来返回代理的目标:

const video = document.querySelector('video');
const proxy = new Proxy(video, {
    get(target, key) {
        const value = video[key];
        if (value instanceof Function) {
            return value.bind(video);
        } else if (key == 'target') {
            return target;
        } else {
            return value;
        }
    },
    set(target, key, value) {
        target[key] = value;
        return true;
    }
});

然后你可以做:

console.log(document.body.contains(proxy.target));

编辑:

Is this really how it is supposed to be? (the document.body.contains(myProxyElement) part):

是的,我看不出有任何其他方法可以做到这一点。

Setting values to video element throwing when setting inside proxy seemed weird, is it a bug? (3rd point, kinda second too, I suppose it is connected):

由于我无法重现这个问题,所以很难说。也许尝试将 new Proxy(video, ... 替换为 new Proxy({}, ... 然后将视频设置为 proxy.video = video (您还必须更新 getset 中的逻辑)并查看其行为如何?

关于javascript - 代理 HTMLElement,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52075255/

相关文章:

javascript - Angular - mat-grid-list 不显示 <ng-content> 传递的子项

javascript - 从超链接调用 javascript 函数

java - 为什么日期在不同时区以相同的毫秒数变化?

javascript - Rangeerror Angular 6 超出最大调用堆栈

java - 你如何通过代理下载文件

.htaccess - htaccess 和 SSL 代理

html - 背景视频未在移动设备和台式机上的 Safari 浏览器中播放

google-chrome - HTML5 视频不会循环播放

linux - Kubernetes kuberadm 不使用代理

ios5 - Airplay 镜像 + 外部 UIScreen = 全屏 UIWebView 视频播放?