【问题标题】:Alternative for setting the srcObject using VueJS使用 VueJS 设置 srcObject 的替代方法
【发布时间】:2018-02-03 21:36:14
【问题描述】:

设置 html 视频元素的“src”属性不适用于 Vue.js 和 Vuex:

<video id="myVideoEl" :src="myStreamSrc" autoplay="autoplay">

myStreamSrc 是一个计算值,由事件处理程序设置为突变:

AddStream: function (state, plMyStream) {
  state.myRTCPeerConnection.addStream(plMyStream)
  state.myStreamSrc = plMyStream
}

当我使用该代码运行我的应用程序时,我收到以下错误:

不支持“text/html”的HTTP“Content-Type”。媒体负载 资源http://localhost:8080/[object%20MediaStream] 失败。

当我执行以下操作时:

state.myVideoEl = document.querySelector('#myVideoEl')
state.myVideoEl.srcObject = payloadWithMyStream

我没有收到任何错误,并且显示了流。问题是,我不能使用被剪断的工作代码,因为引用的元素稍后会添加到 DOM 中。当我使用 v-if Vuex.js 属性绑定 div 中的 html 视频元素时,此代码 sn-p 不起作用。然后我得到“未定义”的结果(因为页面加载时不存在带有视频元素的 div 元素)。

设置srcObject 和设置src 属性有区别吗?我以为当我设置srcObject 时,video 元素会有一个src 属性,但它没有。

是否可以在video html属性中设置srcObject

更多信息,请访问我的 Vue.js 论坛: https://forum.vuejs.org/t/reference-elements-when-they-rendered-with-v-if/16474/13

【问题讨论】:

  • 你试过&lt;video v-if="myStreamSrc" id="myVideoEl" :src="myStreamSrc" autoplay="autoplay"&gt;吗?
  • 尝试了您的建议。我得到同样的错误。

标签: javascript vue.js webrtc vuejs2 vuex


【解决方案1】:

你试过了吗

<video v-if="myStreamSrc" id="myVideoEl" :srcObject ="myStreamSrc" autoplay="autoplay"> ?

否则我会建议你为这种情况编写一个组件:

var videoComponent = {
  template: '<video ref="myVideoEl" :srcObject ="myStreamSrc" autoplay="autoplay">'
  props: ['myStreamSrc']
}
Vue.component("video-component", videoComponent)

在父模板中

<video-component v-if="myStreamSrc" :myStreamSrc="myStreamSrc"></video-component>

或者在父级中,您可以只为 srcObject 放置一个观察者,我假设它等于 false,直到加载了正确的视频源。在这种情况下,您可以等到源目标设置完毕,然后以工作方式进行。

...
watchers:{
    myStreamSrc: function (newValue, oldValue) {
      if(!oldValue && !!newValue){
        this.nextTick(function () {
          state.myVideoEl = document.querySelector('#myVideoEl')
          state.myVideoEl.srcObject = payloadWithMyStream
        })
      }
  }
}

提示: 当您将ref="myVideoEl" 设置为html 元素而不是id="myVideoEl" 时,您可以使用$refs.myVideoEl 而不是document.querySelector('#myVideoEl')。这只是一种味道。

PS:我直接在stackoverflow中写了代码,没有拼写检查...

【讨论】:

  • 试过了,":srcObject ="myStreamSrc" 不行,没有报错,好像不支持。第二个和第三种方案都不行,因为设置了“srcObject”或者通过“$refs”引用的 html 元素后来通过“v-if”添加到 DOM 中找不到和引用。这是我的主要问题。
  • 好的,那么请在 vuejs.org/v2/api/#Vue-nextTick 函数中添加依赖于 id 或 ref 的所有内容
  • 谢谢,它有效!但是为什么我必须使用“nextTick”功能呢?为什么我不能只使用“v-if”,观察变化并在观察变量更改为true后设置视频html元素的“srcObject”?如果这样做,则无法在 DOM 中找到该元素。为什么它只适用于“nextTick”功能?
  • NextTick 确保新元素已添加到 DOM,而 v-if 不关心这一点。一切都是异步触发的。如果我的回答对您来说是正确的,请接受并评价它。在大多数情况下,您将需要 nextTick 。文档说“延迟回调在下一个 DOM 更新周期后执行。在更改一些数据以等待 DOM 更新后立即使用它。这与全局 Vue.nextTick 相同,只是回调是 this上下文会自动绑定到调用此方法的实例。"
【解决方案2】:

想加入我的(类似)解决方案。我正在为 Vue 使用 Nuxt 框架。通过 Vuex 设置 MediaStream 对我也不起作用。通过单击非子组件中的按钮启动网络摄像头的状态,我需要在此其他组件中设置视频对象的媒体流。

在您单击按钮以切换我的视图以及启动navigator.mediaDevices 时运行的方法中,我最终这样做了(可能不是最干净的?)。

let constraints = (window.constraints = {
        audio: false,
        video: {
          facingMode: "user"
        }
      });

      navigator.mediaDevices
        .getUserMedia(constraints)
        .then((stream) => {
          let videoTracks = stream.getVideoTracks();
          if (this.$store.state.debug) console.log("Got stream with constraints:", constraints);
          if (this.$store.state.debug) console.log("Using video device: " + videoTracks[0].label);
          stream.oninactive = function() {
            if (this.$store.state.debug) console.log("Stream inactive");
          };
          // NOTE: this is done this way because I couldnt set it via Vuex state
          document.getElementById('user-media__source').srcObject = stream;
        })
        .catch((error) => {
          if (error.name === "ConstraintNotSatisfiedError") {
            if (this.$store.state.debug) console.log(`The resolution ${constraints.video.width.exact} "x" ${constraints.video.width.exact} px is not supported by your device.`);
          } else if (error.name === "PermissionDeniedError") {
            if (this.$store.state.debug) console.log(`Permissions have not been granted to use your camera and microphone, you need to allow the page access to your devices in order for the demo to work.`);
          }
        });

因此,由于我需要设置源的组件已经创建/安装,所以我刚刚解雇了通常的 document.getElementById('XXXX').srcObject =,它就像我想要的那样工作。

【讨论】:

    【解决方案3】:

    srcObject是修饰符不是html属性,所以需要写

    <video :srcObject.prop="myStreamSrc" autoplay/>
    

    请参阅 Priansh Shah 的回答以了解 2019 年的更新。

    【讨论】:

      【解决方案4】:

      为较新版本的 Vue 发布更新的解决方案,以防有人遇到此问题并遇到与我相同的错误。

      2019 年更新:

      <video :src-object.prop.camel="stream">
      

      第一个变化是使用 v-bind 绑定到srcObject,下面是一个简写示例:

      <video :srcObject.prop="stream">
      

      但是 srcObject 是驼峰式的,所以在 HTML 中它只是变成 srcobject(小写),这被认为是不同的属性,因此不会触发视频。

      如果您使用的是 Vue document.getXXXXX(...).srcObject = stream 手动触发它。

      但是,如果您使用的是 Vue v2.1+,那么您很幸运,因为现在也有一个 API 修饰符:

      <video :src-object.prop.camel="stream">
      

      .camel 将kebab-case 转换为camel case,所以要得到srcObject,我们反过来得到src-object.camel。将它与.propv-bind 结合起来,我们就得到了上面的语法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-26
        • 2014-09-21
        • 2023-03-14
        • 2021-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-14
        相关资源
        最近更新 更多