vue3 style CSS变量注入

4,658 阅读2分钟

近期有个需求,就是隐藏video播放器里的进度条,一开始用下面的方法

<video src="xxxx" controls="controls"></video>
video::-webkit-media-controls-timeline {
		display: none;
	}

但由于后面视频链接改成了m3u8,就用了一个叫DPlayer的插件,但问题来了,这个插件没有相关的设置进度条,于是就想通过css来处理,但css不能写死,需要读取后端的值来控制。

本来是可以通过以下方式实现的

<div class="text">1111</div>
setup() {
        return {
            color: 'red',
        }
},
<style scoped lang="scss">
.text {
	color: v-bind(color);
}
</style>

浏览器中是这样的

image.png

image.png

因为DPlayer是在js中初始化的,html中是(id随便取,js初始化的时候保持一致)

<div id="dplayer" class="dplayer-div"></div>

然后就通过css抓取找到了控制进度条的class(playDisplay已在setup中定义)

<style scoped lang="scss">
::v-deep .dplayer-div {
	.dplayer-controller {
		.dplayer-bar-wrap {
			display: v-bind(playDisplay);
		}
	}
}
<style>

但没有效果,然后就看了篇文章,了解了大概原理 当检测到这种 CSS 变量时,SFC 编译器将执行以下操作:

  1. 重写到一个带有哈希变量名称

    上面的display就变成

    display: var(--7450f29b-playDisplay);

  2. 相应的变量将作为内联样式被注入到组件的根元素中

    比如

<div style="--6b53742-color:red;" class="text">hello</div>

所以display没有效果估计是第二步出了问题,文章还说到可以用useCssVars来注入 CSS 变量

import { useCssVars } from 'vue'
export default {
  setup() {
    //...
    useCssVars(_ctx => ({
      playDisplay: _ctx.playDisplay,
    }))
  },
}

但还没有效果,心态崩了,然后也是那篇文章给了我灵感,useCssVars修改了一下就好了,对应的css也要变,最终效果就是

<div id="dplayer" class="dplayer-div"></div>
import { useCssVars } from 'vue'
export default {
  setup() {
    //...
    const playDisplay = ref('')
    playDisplay.value = 'none'
    useCssVars(_ctx => ({
      '7450f29b-playDisplay': _ctx.playDisplay,
    }))
    return{
       playDisplay
    }
  },
}
<style scoped lang="scss">
::v-deep .dplayer-div[data-v-7450f29b] {
	.dplayer-controller {
		.dplayer-bar-wrap {
			display: v-bind(playDisplay);
		}
	}
}

(关于::v-deep的知识点可以参考这个文章

最新更新: 那个方法放到线上后就行不通了,哈希值会变,最后使用了一个很直接的方法,直接操作dom(放在我这个项目里面的话就是要在dPlayer初始化后使用)

document.querySelector(".dplayer-bar-wrap").style.display = "none";