Luna Tech

Tutorials For Dummies.

Vue: Class and Style Bindings

2022-03-19


0. Intro

Reference

改变 element’s class and inline style 是一种常见的需要 data binding 的情况,因为 class 和 inline style 都是 html attributes,我们可以通过 v-bind 来完成这个任务,通过一些 expression calculation 来返回一个最终 string value 即可。

但是这么做的问题在于,string manipulation 容易发生错误,所以 vue 提供了一些额外的 api。


1. :class API (short for v-bind:class) - Binding to Objects

Example 1

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

active 是 css class name isActive 是 data property,通过 truthiness 来 toggle css class。

Example 2

我们可以在使用 :class 的同时继续使用 class attribute,两者会叠加。

<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>

Example 3

我们可以 create object 直接 pass 给 :class,不需要全部都写在 template 里面。

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

Example 4

我们还可以用 computed property 来做 binding,这也是常见用法。

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

2. Binding to Arrays

Example 1

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

render:

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

Example 2

用 ternary expression 来 toggle class in the list.

expression evaluation is based on truthiness.

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

Example 3

我们也可以在 array 里面加 object,这样的写法看起来更简洁。

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

3. With Components

Merging of the classes (Single root element)

When you use the class attribute on a component with a single root element, those classes will be added to the component’s root element, and merged with any existing class already on it.

Example 1

<!-- child component template -->
<p class="foo bar">Hi!</p>
<!-- when using the component -->
<my-component class="baz boo"></my-component>

结果:

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

Example 2

<!-- child component template -->
<p class="foo bar">Hi!</p>
<my-component :class="{ active: isActive }"></my-component>

结果(当 isActive 为 truthy):

<p class="foo bar active">Hi</p>

Merging of the classes (Multiple root elements)

If your component has multiple root elements, you would need to define which element will receive this class. You can do this using the $attrs component property:

Example

这里只有 p 接收到了 class,span 没有接收到。

<!-- my-component template using $attrs -->
<p :class="$attrs.class">Hi!</p>
<span>This is a child component</span>
<my-component class="baz"></my-component>

结果:

<p class="baz">Hi!</p>
<span>This is a child component</span>

Fallthrough Attributes


4. Binding Inline Styles v-bind:style

这个 :style API 跟 :class API 差不多,都支持 object 和 array,也通常会跟 computed property 一起使用。

Convention: Although camelCase keys are recommended, :style also supports kebab-cased CSS property keys (corresponds to how they are used in actual CSS), e.g., <div :style="{ 'font-size': fontSize + 'px' }"></div>

Binding to Objects

Example 1

<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data() {
  return {
    activeColor: 'red',
    fontSize: 30
  }
}

Example 2

推荐使用 style object,而不是把逻辑都写在 template 里面。

<div :style="styleObject"></div>
data() {
  return {
    styleObject: {
      color: 'red',
      fontSize: '13px'
    }
  }
}

Example 3: Multiple Values

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

这种情况会根据 browser support 来确定 style。

This will only render the last value in the array which the browser supports. In this example, it will render display: flex for browsers that support the unprefixed version of flexbox.

Auto-prefixing

When you use a CSS property that requires a vendor prefix in :style, Vue will automatically add the appropriate prefix. Vue does this by checking at runtime to see which style properties are supported in the current browser. If the browser doesn’t support a particular property then various prefixed variants will be tested to try to find one that is supported.

Binding to Arrays

Example 1

<div :style="[baseStyles, overridingStyles]"></div>