vue.js是基于数据驱动的前端框架,不直接修改DOM结构,而是将数据的变化映射为DOM行为,本节主要学习vue.js的内置指令。

1.1 v-bind

v-bind用来绑定DOM元素属性(attribute),例如:

<img v-bind:src="avatar" alt="avatar">
  new Vue({
    data : {
      avatar : 'http://www.rome-web.com'
    }
  })

v-bind可简写:

<img :src="avatar" alt="avatar">

v-bind的三种修饰符:.sync/.once/.camel:

.sync:用于组建props属性,进行双向数据绑定,即父组件绑定传递给子组件的值;

.once:亦用于props属性,进行单次绑定(子组件单独维护这份数据,和父组件再无关系);

.camel:将绑定的特性名字转回驼峰命名;

注:在vue.js 2.x中,.sync/.once均被废弃,规定组建仅能单向传递,若子组件需要修改父组件,必须使用事件机制处理。

1.2 v-model

v-model对表单元素进行双向数据绑定,以下简单介绍text、radio、checkbox、select:

Text:

<script type="text/javascript">
    var vm = new Vue({
      el : '#app',
      data : {
        message : '',
        gender : '',
        checked : '',
        multiChecked : [],
        selected : '',
        multiSelected : []
      }
    });
  </script>
  <input type="text" v-model = "message">
  <span>您输入的是:{{message}}</span>

Radio:

<label>
  <input type="radio" value="male" v-model="gender">男
</label>
<label>
  <input type="radio" value="female" v-model="gender">女
</label>
<p>{{gender}}</p>

gengder值即为选中元素的value值。

Checkbox:

单个勾选:

<input type="checkbox" v-model="checked">
<span>checked : {{checked}}</span>

多个勾选,v-model使用相同属性名称,且属性为数组:

<label><input type="checkbox" value="1" v-model="multiChecked">1</label>
<label><input type="checkbox" value="2" v-model="multiChecked">2</label>
<label><input type="checkbox" value="3" v-model="multiChecked">3</label>
<p>multiChecked : {{multiChecked.join( ',')}}</p>

Selct:

也分为多选和单选两种,多选同样需要绑定到一个数组:

单选:

<select v-model="selected">
  <option selected>A</option>
  <option>B</option>
  <option>C</option>
</select>
<span>Selected : {{selected}}</span>

多选:

<select v-model="multiSelected" multiple>
  <option selected>A</option>
  <option>B</option>
  <option>C</option>
</select>
<span>MultiSelected : {{multiSelected.join( ',')}}</span>

表单控件的值,可以用v-bind绑定在vue实例的动态属性上:

// 1.Checkbox

<input type="checkbox" v-model="checked" v-bind:true-value = "a" v-bind:false-value = "b">
vm.checked == vm.a //选中 true
vm.checked == vm.b //未选中 true

// 2.Radio

<input type="radio" v-model="checked" v-bind:value="a">
vm.checked == vm.a //选中 true

// 3.Select option

<select v-model="selected">
  //对象字面量
  <option v-bind:value = "{num : 123}">123</option>
</select>
vm.selected .num //123
typeof vm.selected //'object'

1.3 v-if/v-else/v-show

v-if和v-else根据数据值来判断是否输出DOM元素,需要注意的是,v-else必须紧跟v-if,但是v-if包含的子元素嵌套,不影响使用,如下:

<div id="app">
  <div v-if="yes">
    <div v-if="inner">inner</div>
    <div v-else>not inner</div>
  </div>
  <div v-else>no</div>
</div>
<script type="text/javascript">
  var vm = new Vue({
    el : '#app',
    data : {
      yes : true,
      inner : false
    }
  });
</script>
//最终结果:inner

v-show同样可以根据数据条件显示DOM元素,也可以搭配v-else,用法和v-if一致,不过二者的区别在于,v-show会保存DOM元素的渲染,其只不过是切换元素的display属性,二者切换时,v-if引起DOM级别的变化,而v-show仅发生了样式的变化,其消耗的性能要低于v-if。v-if切换时,vue.js会有一个局部编译、卸载的过程,所以,v-if有更高的切换消耗,v-show有更高的初始渲染消耗,按需使用。

1.4 v-for

v-for用于列表渲染,用法和angular.js的ng-repeat用法类似:

<div id="app">
  <ul>
    <li v-for="item in items">
      <span>{{item.tit}}</span>
      <span>{{item.desc}}</span>
    </li>
  </ul>
</div>
<script type="text/javascript">
  var vm = new Vue({
    el : '#app',
    data : {
      items : [
        {tit : 'tit-1',desc : 'desc-1'},
        {tit : 'tit-2',desc : 'desc-2'},
        {tit : 'tit-3',desc : 'desc-3'}
      ]
    }
  });
</script>

angular.js的ng-repeat指令有个$index,"ng-repeat = item in items track by $index",同样v-for也有一个$index,如:

<li v-for="(item,index) in items">
  <span>{{index}}</span>
</li>

这是vue.js 2.x的写法,1.x中参数item是在index后面的,2.x这样修改是为了和forEach()等方法保持一致。同样,v-for的使用和ng-repeat相似之处在于,修改数据同样可以触发视图的更新。

2.x版本中,除了参数的顺序做了微调,属性track-by被v-bind:key代替:

<div v-for="item in items" track-by ="id"></div>
//修改为
<div v-for="item in items" v-bind:key="item.id"></div>

v-for="n in 10"中的n由0~9,调整为1~10

1.5 v-text

v-text用于更新元素的textContent,如果直接使用

<span>{{msg}}</span>

在生命周期的beforeCompile期间,此刻{{msg}}尚未编辑,可能看到一瞬间的{{msg}},而v-text不会有这个问题。

1.6 v-HTML

作用为更新元素的innerHTML,使用同v-text,避免编译前闪现。

1.7 v-el

v-el为DOM元素注册一个索引,可以直接访问DOM元素,通过所属实例的$els属性调用:

<div v-el:demo>el demo</div>
vm.$els.demo.innerHTML //el demo

v-el如果使用了驼峰命名,系统自动转为小写,可以使用“-”连接大写字母,v-el在vue.js 2.x中已经废弃。

1.8 v-ref

类似v-el,props绑定数据,用组件间通信进行逻辑上的交互。

<message v-ref:title content="title"></message>
<message v-ref:sub-title content="subTitle"></message>
var Message = Vue.extend({
  props : {'content'},
  template : '<h1>{{content}}</h1>'
});
Vue.component('message',Message);

尽量让组件操作自己内部的数据和状态,组件间的通信通过组件暴露的接口进行通信,而不是直接跨组件修改数据。

1.9 v-pre

跳过编辑这个元素和子元素:

<div v-pre>{{ uncompiled }}</div>
var vm = new Vue({
  el : '#app',
  uncompiled : '未编译的元素'
})

减少编译时间,显示原始的{{}}

1.10 v-cloak

在元素添加一个[v-cloak]属性,何以结合display:none,隐藏未编译的标签:

<div v-cloak>{{ msg }}</div>

1.11 v-once

vue 2.x新增的指令,用于标记元素或组件只渲染一次,即使以后绑定数据改变,也不会重新渲染编译,不需要更新:

<span v-once>{{ msg }}</span>
<my-component v-once:msg = "msg"></my-component>