在 CSS 中使用 v-bind() 动态设置背景图片

412 阅读1分钟

v-bind 的使用

首先看下官网的介绍:vuejs.org/api/sfc-css…

使用很简单:

<template>
  <div class="text">hello</div>
</template>

<script>
export default {
  data() {
    return {
      color: 'red'
    }
  }
}
</script>

<style>
.text {
  color: v-bind(color);
}
</style>

Vue3 项目中想要动态的给一个元素 card-img 应用背景图片,使用 v-bind() in CSS 功能:

<template>
  <div class="card-img"></div>
</template>

<script>         
const imgUrl = computed(() => {
  return new URL(
    `../img${config.value.picture}.jpg`,
    import.meta.url,
  ).href
})
</script>

<style>
.card-img {
  background-image: url(v-bind(imgUrl));
}
  </style>

我们上面应用背景图片的做法是不正确的,查看页面元素,会发现样式中没有 backgroud-image,这里的问题是有多个语法错误:

  • CSS 的 url 函数形式为:url(''),路径需要引号包裹。
  • v-bind 是独立指令,不能作为字符串的一部分。

修改:

background-image: v-bind('url(' + imgUrl + ')');
// 或
background-image: v-bind(`url(${imgUrl})`); 

这样也不行,这是因为 v-bind 支持使用 JavaScript 表达式,但是必须被引号包裹。

所以,正确的做法:

background-image: v-bind("'url(' + imgUrl + ')'");
// 或
background-image: v-bind("`url('${imgUrl}')`");

v-bind 中的内容需要用引号包裹,同时注意 url 函数的引号。但是我有个疑问,v-bind 中 them.color 是一个变量,在我们的使用中,'url(' + imgUrl + ')' 或者 url('${imgUrl}') 不是一个字符串吗?为什么不是这样使用:

background-image: v-bind("url('${imgUrl}')");

但是以上用法有问题,url 就是字符串 'imgUrlVue并不会对其中的{imgUrl}',Vue 并不会对其中的 {imgUrl} 进行变量替换,从而最终只会得到字面量 "url(${imgUrl})"。

v-bind 的原理

  • v-bind 在 中的表达式会被编译为 CSS 自定义属性(CSS Variable),而 CSS 自定义属性的值必须是字符串。
  • Vue 将表达式的结果转换为 CSS 自定义属性,并注入到组件的根元素中。
  • 在 CSS 中,Vue 会将 v-bind 替换为对应的 CSS 变量。

以上两种写法,查看 CSS 值:

background-image: var(--83b60a21-'url('\ +\ imgUrl\ +\ ')');

background-image: var(--83b60a21-`url('${imgUrl}')`);

组件根元素,被注入 CSS 自定义属性:

总结

在 Vue 中通过 <style> 标签使用 v-bind() 实现 CSS 动态绑定时,需要注意:

  • 表达式整体必须用引号包裹。
  • 构造的字符串必须符合 CSS 语法要求(如 url() 内部路径需加引号)。
  • 不能将 v-bind() 当作字符串的一部分嵌入 CSS 函数中。