NervJS / taro

开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/
https://docs.taro.zone/
Other
35.4k stars 4.78k forks source link

编译至小程序平台下的 video 组件, v-bind 绑定的 muted 参数没有生效 #9550

Closed xiamibuchi closed 2 years ago

xiamibuchi commented 3 years ago

相关平台

微信小程序

复现仓库

https://github.com/xiamibuchi/taro-demo 小程序基础库: 2.17.0 使用框架: Vue 2

复现步骤

对 video 标签设置 :muted="muted",muted 初始值为 true,video 播放时未静音,并且切换 muted 的值时 video 的静音状态也未改变。必须用 ref 获取 video,用 setAttribute 才能成功生效

<template>
  <view class="index">
    <video
      ref="video"
      class="test-video"
      autoplay
      :muted="muted"
      src="https://pl.taptap.com/best-segments.m3u8?etag=lhT1oZjytEqkRLwbOpP8Ng_c_dZx&ts=1623952122&sign=45fcfcdf49e2e3b6a70ec514f23138fc68121073"
    ></video>
    <button @tap="changeMuted">切换静音</button>
    <view>当前{{ muted ? "已" : "未" }}静音</view>
  </view>
</template>

<script>
import "./index.scss";
export default {
  data() {
    return {
      muted: true
    };
  },
  methods: {
    changeMuted() {
      this.muted = !this.muted;
      const video = this.$refs.video;
      // 必须使用以下语句才可设置 video 的 muted
      // video.setAttribute("muted", this.muted);
    }
  }
};
</script>

期望结果

修改 muted 时,video 的静音状态跟随改变

实际结果

video 的静音状态没有跟随改变

环境信息

Taro CLI 3.1.1 environment info:
    System:
      OS: macOS 11.2.2
      Shell: 5.8 - /bin/zsh
    Binaries:
      Node: 14.15.4 - ~/.nvm/versions/node/v14.15.4/bin/node
      Yarn: 1.22.10 - ~/.nvm/versions/node/v14.15.4/bin/yarn
      npm: 6.14.10 - ~/.nvm/versions/node/v14.15.4/bin/npm
    npmPackages:
      @tarojs/components: 3.1.1 => 3.1.1 
      @tarojs/mini-runner: 3.1.1 => 3.1.1 
      @tarojs/runtime: 3.1.1 => 3.1.1 
      @tarojs/taro: 3.1.1 => 3.1.1 
      @tarojs/webpack-runner: 3.1.1 => 3.1.1 
      babel-preset-taro: 3.1.1 => 3.1.1 
      eslint-config-taro: 3.1.1 => 3.1.1 
yaoshuaibing commented 2 years ago

遇到同样问题

Chen-jj commented 2 years ago

@xiamibuchi @yaoshuaibing 原因是 video 组件的 muted 属性会被编译为 domProps,这样会以 DOM property 的形式而不是 attribtue 的形式去设置该值。

可以看到编译结果,muted 被编译为 domProps:

var render = function() {
  var _vm = this
  var _h = _vm.$createElement
  var _c = _vm._self._c || _h
  return _c("view", { staticClass: "index" }, [
    _c("video", {
      ref: "video",
      attrs: { src: "https://media.w3.org/2010/05/sintel/trailer.mp4" },
      domProps: { muted: _vm.muted }
    }),
    _c("button", { on: { tap: _vm.changeMuted } }, [_vm._v(" 切换静音 ")]),
    _c("view", [_vm._v("当前" + _vm._s(_vm.muted ? "已" : "未") + "静音")])
  ])
}

再顺着 Vue template compiler 的源码往下看,可以发现有一个配置项名为 mustUseProp,该配置默认会把以下组件的特定属性作为 domProps。

// node_modules/vue-template-compiler/build.js
var mustUseProp = function (tag, type, attr) {
  return (
    (attr === 'value' && acceptValue(tag)) && type !== 'button' ||
    (attr === 'selected' && tag === 'option') ||
    (attr === 'checked' && tag === 'input') ||
    (attr === 'muted' && tag === 'video')
  )
};

因此 Taro 需要传入自定义的 mustUseProp 配置:

mustUseProp: function () {
  return false
}