Vuejs绑定Class和Style

Published on 2016 - 06 - 17

Class binding

Object Syntax

A common need for data binding is manipulating an element’s class and its styles. For such cases, you can use v-bind:class. This can be used to apply classes conditionally, toggle them and/or apply many of them using one binded object et al.

The v-bind:class directive takes an object with the following format as an argument

{
    'classA': true,
    'classB': false,
    'classC': true,
}

and applies all classes with true value to the element. For example, the following element will have classA and classC classes.

<div v-bind:class="elClasses"></div>

data: {
    elClasses:
        {
            'classA': true,
            'classB': false,
            'classC': true
        }
}

To demonstrate how v-bind is used with class attributes, we are going to make an example of class toggling. Using v-bind:class directive, we are going to dynamically toggle the class of body element.

<html>
<head>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <title>Hello Vue</title>
</head>
<body class="text-center" v-bind:class="{ 'body-red' : color, 'body-blue' : !color }"
    <button v-on:click="flipColor" class="btn"> 
        Flip color!
    </button> 
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.js"></script> 
<script type="text/javascript">
new Vue({
    el: 'body',
    data: {
        color: true 
    },
    methods: {
        flipColor: function() {
            this.color = !this.color; 
        }
    } 
});
</script>
<style type="text/css">
.body-red { 
    background-color: #ff0000;
} 
.body-blue {
      background-color: #0000ff;
}
</style> 
</html>

We have applied a class to the body for our convenience and now body is referenced within our el property. What this code actually does, is “flipping” the background color with a hit of the button. Pressing it invokes the flipColor function that reverses the value of “color” originally set to true. Then the v-bind:class is going to toggle the class name to ‘body-red’ or ‘body-blue’ conditionally depending on the truthfulness of “color” value. That given, the style is going to apply on each class and give us the desired result according to which class is active.

The v-bind:class directive can co-exist with the plain class attribute.
So in our example, body always has the text-center class and conditionally one of body-red or body-blue.
Although you can use mustache interpolations such as class=”{{ className }}” to bind the class, it is not recommended to mix that style with v-bind:class. Use one or the other!

Array Syntax

We can also apply a list of classes to an element using an array of classnames.

<div v-bind:class="['classA', 'classsB', anotherClass]"></div>

Applying conditionally a class, can also be achieved with the use of inline if inside the array.

<div v-bind:class="['classA', condition ? 'classsB' : '']"></div>

Using inline if, the flipping colors example will look like:

<body class="text-center body" v-bind:class="[ color ? 'body-red' : 'body-blue']">
    <button v-on:click="flipColor" class="btn">
        Flip color! 
    </button>
</body>

new Vue({ 
    el: 'body', 
    data: {
        color: true 
    },
    methods: {
        flipColor: function() {
            this.color = !this.color;
        }
    }
});

Style binding

Object Syntax

The Object syntax for v-bind:style is pretty straightforward; it looks almost like CSS, except it’s a JavaScript object. We are going to use the shorthand Vue.js provides for the previously used directive, v-bind(:).

<!-- shorthand -->
<div :style="niceStyle"></div>
data: {
    niceStyle:
    {
        color: 'blue',
        fontSize: '20px'
    }
}

We can also declare the style properties inside an object :style=”...“ inline.

<div :style="{'color': 'blue', fontSize: '20px'}"></div>

We can even reference variables inside style object:

<!-- Variable 'niceStyle' is the same we used in the previous example -->
<div :style="{'color': niceStyle.color, fontSize: niceStyle.fontSize}">
</div>

It is often a good idea to use a style object and bind it, so the template is cleaner.

Array Syntax

Using inline array syntax for v-bind:style, we are able to apply multiple style objects to the same element, meaning here that every list item is going to have the color and fontsize of niceStyle and the font weight of badStyle.

<!-- shorthand -->
<div :style="[niceStyle, badStyle]"></div>

data: {
    niceStyle:
    {
        color: 'blue',
        fontSize: '20px'
    }
    badStyle:
    {
        fontweight: 'bold'
    }
}

Bindings in Action

<html>
<head>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.cs\ s" rel="stylesheet">
    <title>Hello Vue</title>
</head>
<body class="container-fluid">
    <ul>
        <li :class="{'completed' : task.done}" :style="styleObject" v-for="task in tasks">
            {{task.body}}
            <button @click="completeTask(task)" class="btn">
                Just do it! 
            </button>
        </li>
    </ul>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.js"></script> <script type="text/javascript">
new Vue({
    el: 'body',
    data: {
        tasks: [
            {body:"Feed the horses", done: true}
            {body: "Wash armor", done: true},
            {body:"Sharp sword", done: false},
        ],
        styleObject: {
            fontSize: '25px'
        }
    }, 
    methods: {
        completeTask: function(task) { 
            task.done = !task.done;
        } 
    },
});
</script>
<style type="text/css">
    .completed {
        text-decoration: line-through;
    } 
</style>
</html>

The above example has an array of objects called “tasks” and a styleObject which contains only one property. With the use of v-for, a list of tasks is rendered and each task has a “done” property with a boolean value. Depending on the value of “done”, a class is applied conditionally as before. If a task has been completed, then css style applies and then task has a text-decoration of line-through. Each task is accompanied by a button listening for the “click” event which triggers a method, altering the completion status of the task. The style attribute is binded to styleObject resulting in the change of ‘fontsize’ of all tasks. As you can see, the completedTasks method takes in the parameter task.

Reference