Vue3之Class绑定

11,154 阅读2分钟

操作元素的class列表是数据绑定的一个常见需求。因为是attribute,所以我们可以用v-bind处理它们:只需要通过表达式计算出字符串结果即可。但是,字符串的拼接麻烦且容易造成错误,所以Vue.js做了专门的增强,表达式结果的类型除了字符串之外,还可以是对象或数组。

对象语法

<div :class="{ active: isActive }"></div>

上面代码中active这个class是否存在取决于数据propertyisActive。 也可以在对象中传入更多字段来动态切换多个class。另外,:class也可以与普通的classattribute共存。

<div
    class="static"
    :class="{ active: isActive, 'text-danger': hasError }"
></div>
data(){
    return {
        isActive: true,
        hasError: false
    }
}

渲染的结果为:

<div class="static active"></div>

isActivehasError变化时,class列表将相应地更新。 绑定的数据对象不必内联定义在模板里:

<div :class="classObject"></div>
data(){
    return {
        classObject: {
            active: true,
            'text-danger': false
        }
    }
}

渲染的结果和上面是一样的。我们也可以在这里绑定一个返回对象的计算属性。这是一个常用且强大的模式:

<div :class="classObject"></div>
data(){
    return {
        isActive: true,
        error: null
    }
},
computed: {
    classObject(){
        return {
            active: this.isActive && !this.error,
            'text-danger': this.error && this.error.type === 'fatal'
        }
    }
}

数组语法

<div :class="[activeClass, errorClass]"></div>
data(){
    return {
        activeClass: 'active',
        errorClass: 'text-danger'
    }
}

渲染的结果为:

<div class="active text-danger"></div>

也可以使用三元表达式来根据条件切换列表中的class:

<div :class="[isActive? activeClass : '', errorClass]"></div>

不过,当有多个条件class时,这样写有些繁琐,所以在数组语法中也可以使用对象语法:

<div :class="[{ active: isActive}, errorClass]"></div>

在组件上使用

当你在带有单个根元素的自定义组件上使用classattribute时,这些class会被添加到很元素上,并且此元素上的现有class不会被覆盖:

const app = Vue.createApp({})

app.component('my-component', {
    template: `<p class="foo bar">Hi!</p>`
})
<div id="app">
    <my-component class="baz boo"></my-component>
</div>

HTML将被渲染为:

<p class="foo bar baz boo">Hi!</p>.

如果你的组件有多个根元素,你需要使用$attrs组件属性来定义哪些部分将接受这个class:

<div id="app">
    <my-component class="baz"></my-component>
</div>
const app = Vue.createApp({})

app.component('my-component', {
    template: `
        <p :class="$attrs.class">Hi!</p>
        <span>This is a child component</span>
    `
})