Vue: 不能使用 `:srcObject.prop` 将 prop 设置为 null

创建于 2018-12-03  ·  3评论  ·  资料来源: vuejs/vue

版本

2.5.17

转载链接

https://codesandbox.io/s/ppyq71wrxj

重现步骤

(见最小再现)

  1. 有一个带有HTMLMediaElement的组件,它将:srcObject.prop绑定到某个数据属性(以null开头):
<audio :srcObject.prop="stream">
  1. 将其设置为一些有效的MediaStream
this.stream = new MediaStream();
  1. 将其设置回null
this.stream = null;

什么是预期?

我希望 audio.srcObject 为空

实际发生了什么?

它保留为 MediaStream,并且日志中有一个 TypeError。


我注意到它在我第一次尝试编写 repro 示例时确实有效: https :

我不确定这有多大帮助,但根据堆栈跟踪,它与此代码相关,在updateDOMProps

  for (key in oldProps) {
    if (isUndef(props[key])) {
      elm[key] = '';
    }
  }

isUndef(null)正在评估 true,因此它试图将道具设置为'' ,但srcObject特别需要它是nullMediaStream

improvement

最有用的评论

也许我们不应该对.prop绑定应用转换

所有3条评论

也许我们不应该对.prop绑定应用转换

现在我已经查看了有问题的代码(src/platforms/web/runtime/modules/dom-props.js 中的updateDOMProps ),我想我对正在发生的事情有了更好的理解。 相关的测试用例(在 unit/modules/vdom/modules/dom-props.spec.js 中)使它看起来像是在防止删除:

  it('should remove the elements domProps', () => {
    const vnode1 = new VNode('a', { domProps: { src: 'http://localhost/' }})
    const vnode2 = new VNode('a', { domProps: {}})
    patch(null, vnode1)
    const elm = patch(vnode1, vnode2)
    expect(elm.src).toBe('')
  })

...除了将其设置为 setter 定义的任意值之外,没有通用的方法可以“删除” HTMLEmelent属性。 从这个意义上说,将空字符串转换为elm[key] = '';基本上是最接近标准方式的方法。 在<img>标签的情况下,将.src属性设置为空字符串旁边的任何内容会导致一些非常令人讨厌的行为:

09:48:05.267 const img = document.createElement('img')
09:48:08.948 img.src
09:48:08.953 ""
09:48:14.469 img.src = null
09:48:17.213 img.src
09:48:17.222 "https://localhost:8080/null"

(我确信这种行为是有充分理由的,而且到处都有合法的用例。)

因此,在这种情况下,空字符串似乎与 null/undef 道具的任何默认值一样合理。 我已经尝试将isUndef(props[key])支票更改props.hasOwnProperty(key) ,或者甚至只是将它直接与undefined ......做起来很简单,但它似乎并不真正如果用户依赖于通过将道具设置为 null 来删除道具的能力,则可行; 它不向后兼容。 dom-props.js特殊外壳属性/元素组合似乎太可怕了,甚至无法提及。

也就是说,我在那里做了太多假设吗? 该代码纯粹是为了防止新 vnode 中缺少道具吗? 测试的作者是否只考虑src属性,因为它是导致失败的原因? 期望用户在“删除”道具时从""nullundefined提供正确的值是否合理?

另一方面,我想在涉及绑定属性时谈论删除并没有真正意义......就像在<audio :srcObject.prop="stream">的例子中stream计算属性将不得不返回一些东西,所以我假设 vnode 内部有些东西超出了我的理解,这使得{stream: {some: thing}}可以被替换为{}

如果上述建议听起来不错,那么我会假设hasOwnProperty是正确的检查,结果应该是elm[key] = '' (就像我说的“标准”删除一样好,并且可能是最普遍适用的情况); 这周我可能会写一个拉取请求。 但如果这不是一个安全的改变,我不想花时间。

我认为这是由 f11449d916a468651d4fd5024c37e3eebbc9941f 修复的

此页面是否有帮助?
0 / 5 - 0 等级