掌握了这些Vue指令,才算是入门Vue.js了,适合新手收藏【精心整理】

2,000 阅读24分钟

Vue.js的指令

指令(Directives)是带有 v- 前缀的特殊属性,指令属性的值一般是单个JavaScript表达式(v-for除外)。指令的功能是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。

常用的Vue指令有:


1、v-text 和 v-html

v-text 在标签中显示文本数据,数据对象中的数据会被原样输出,例如:

<span v-text="message"></span>
<!-- 简写方式 -->
<span>{{message}}</span>

在模板中输出真正的HTML,如果是使用 v-text 输出带标签的字符串的话,仅仅是想页面中输出带标签的HTML,但是不会对HTML代码进行解析,如果要解析HTML代码,就要使用 v-html 指令。例如:

<p v-text=“message”></p> <!-- 输出带有HTML标签的文本内容 -->
<p v-html="message"></p> <!-- 输出解析HTML代码后的内容 -->

<script type="text/javascript">
	var app = new Vue({
		el: '#app', //element
		data: {
			message: '<strong>Hello</strong> Vue!',
		}
	})
</script>

上面代码执行后,输出的结果为:

v-text 输出的结果是:<strong>Hello</strong> Vue!

v-html 输出的结果是:Hello Vue!

总结:

v-text{{}} 表达式渲染数据,不解析标签;

v-html 不仅可以渲染数据,而且可以解析标签;


2、v-cloak

作用: v-clock 指令主要是解决对插值表达式 {{}} 的渲染前闪烁问题。

简单来说,当网络比较慢时,网页还在加载vue.js,这就会导致Vue来不及渲染,这是页面就会显示Vue源代码。我们就可以使用 v-cloak 指令来解决这一问题。

演示:

HTML代码:

<div id="app">
    {{context}}
</div>

JS代码:

<script>
    var app = new Vue({
        el: '#app',
        data: {
            context:'互联网头部玩家钟爱的健身项目'
        }
    });
</script>

效果:

针对上面的这种情况,可以使用 v-cloak指令解决闪烁问题。JS代码不变,只需要在div中添加 v-cloak 指令。使用 v-cloak 指令设置样式,这些样式会在Vue实例编译结束时,从绑定的HTML元素上被移除。

代码示例:

HTML代码:

<div id="app" v-cloak>
    {{context}}
</div>

CSS代码:

[v-cloak]{
    display: none;
}

使用 v-cloak 指令之后的效果:

在简单项目中,使用 v-cloak 指令是解决屏幕闪动的好方法。但在大型、工程化的项目中(webpack、vue-router)只有一个空的 div 元素,元素中的内容是通过路由挂载来实现的,这时我们就不需要用到 v-cloak 指令了。


3、v-bind 属性绑定

v-bind 是用于绑定数据和元素属性的,例如:

<div class="app">
    <a v-bind:href="url">click me</a>
</div>  
var app = new Vue({
    el:'.app',
    data:{
        url:"https://www.baidu.com",
    }
});

v-bind 后面是 属性名="" ,可以理解为绑定了这个属性,属性的值去Vue实例的数据对象中获取,当数据对象中对应的属性值发生改变时,DOM中的属性值也会随着更新,可以在控制台输出测试。

同一个DOM元素上可以绑定多个属性,例如:

<div class="app">
    <a v-bind:href="url" v-bind:class="klass">click me</a>
    <img v-bind:src="imgsrc">
</div>  
var app = new Vue({
    el:'.app',
    data:{
        url:"https://www.baidu.com",
        imgsrc:"https://cn.vuejs.org/images/logo.png",
        class:"btn btn-default"
    }
});

v-bind 除了可以绑定一个简单类型的数据之外,还可以绑定一个对象,例如:

<div class="app">
    <a v-bind:class="{active:isActive}">click me</a>
</div>  

上面代码中,对象的名为 active ,表示要添加的类名, isActive 是vue中的数据,表示在什么情况下添加该类名,即在Vue实例的数据对象中对应的值(isActive的值)为真是,才为DOM元素的class中添加 active 的样式。

简写:

v-bind 指令可以简化英文的冒号 : ,示例:

<div class="app">
    <a v-bind:href="url">click me</a>
</div>  

可以简化为:

<div class="app">
    <a :href="url">click me</a>
</div>  

4、v-on 事件绑定

4.1、监听事件

可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。 示例代码:

<div id="app">
  <button v-on:click="counter += 1">Add 1</button>
  <p>计算结果:{{ counter }}</p>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    counter: 0
  }
})

上面代码运行后,每次点击按钮,数据对象中的 counter 属性的值就会加1。

4.2、事件处理方法

v-on 是用于绑定事件的,例如,有一个按钮,当点击该按钮时执行一些操作:

<div id="app">
	<button v-on:click="myclick">按钮</button>
</div>
var vm = new Vue({
	el: '#app',
	data: {
	},
	methods: {
		myclick:function() {
			console.log('hello world')
	}
}

<button>v-on:click 后面的值是一个方法,可以写出 myclick() ,如果没有参数的话,可以写出 myclick 。该事件对应的方法不是定义在数据对象data中,而是定义在Vue实例的methods中。

4.3、内联处理器中的方法

除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:

<div id="app">
  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="say('what')">Say what</button>
</div>
new Vue({
  el: '#app',
  methods: {
    say: function (message) {
      alert(message)
    }
  }
})

上面代码运行后,当点击两个按钮时,都会执行 say() 方法。

有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:

<button v-on:click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>
// ...
methods: {
  warn: function (message, event) {
    // 现在我们可以访问原生事件对象
    if (event) {
      event.preventDefault()
    }
    alert(message)
  }
}

4.4、多事件处理方法

v-on 可以绑定多个事件,例如:

<div id="app">
	<button v-on="{mouseenter:onenter,mouseleave:leave}">按钮</button>
</div>

或者是写成:

<div id="app">
	<button v-on:mouseenter="onenter" v-on:mouseleave="leave">按钮</button>
</div>
var vm = new Vue({
	el: '#app',
	data: {
	},
	methods: {
		onenter:function() {
			console.log('onenter...')
		},
		leave:function() {
			console.log('leave...')
		}
	}
})

当绑定多个事件时,需要传入一个对象,对象的键名就是事件名,对象的键值就是对应事件要执行的方法。

4.5、阻止表单默认提交

在使用form表单时,当点击提交按钮,浏览器就会默认发送一个get或者是post请求到指定页面,刷新整个页面。有时为了增加表单验证,需要阻止浏览器的默认行为,可以在绑定的提交方法中添加 $event 参数,$event 是Vue里面的事件对象,Vue可以识别,代码示例:

<div class="app">
    <form v-on:submit='onSubmit($event)'>
        <input type="text" >
        <button type="submit">提交</button>
    </form>
</div>  
var app = new Vue({
    el:'.app',
    data:{
        
    },
    methods:{
        onSubmit:function(e){
            e.preventDefault(); //阻止浏览器的默认行为
            console.log("onSubmited");
        }
    }
});

其实,在Vue中已经封装了阻止浏览器默认行为的修饰符,只需要在事件的后面加上 .prevent 修饰符,就可以组织默认事件,例如:

<div id="app">
	<form v-on:submit.prevent="onSubmit($event)">
		<input type="text">
		<button type="submit">提交</button>
	</form>
</div>
var vm = new Vue({
	el: '#app',
	data: {
	},
	methods: {
		onSubmit: function() {
			console.log('onsubmit....')
		}
	}
})

4.6、v-on事件简写

v-on 可以简写为 @ 符号,例如:

<div id="app">
	<button v-on:click="myclick">按钮</button>
</div>

可以简化为:

<div id="app">
	<button @click="myclick">按钮</button>
</div>

4.7、事件修饰符

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

4.8、按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

在Vue中已经废除了 keyCode 的事件用法,但是可以使用 keyCode 属性,例如:

<input v-on:keyup.13="submit">

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

有一些按键 (.esc 以及所有的方向键) 在 IE9 中有不同的 key 值, 如果你想支持 IE9,这些内置的别名应该是首选。

你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名

// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112

4.9、系统修饰符

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

  • .ctrl
  • .alt
  • .shift
  • .meta

例如:

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

请注意修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。如果你想要这样的行为,请为 ctrl 换用 keyCodekeyup.17

.exact修饰符

.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

鼠标按钮修饰符

  • .left
  • .right
  • .middle

这些修饰符会限制处理函数仅响应特定的鼠标按钮。

4.10、自定义按键修饰符别名

在Vue中可以通过config.keyCodes自定义按键修饰符别名。例如,由于预先定义了keycode 116(即F5)的别名为f5,因此在文字输入框中按下F5,会触发prompt方法,出现alert

<div id="app">
	<input type="text" v-on:keydown.f5="prompt()" />
</div>
Vue.config.keyCodes.f5 = 116;
var vm = new Vue({
	el: '#app',
	data: {
		
	},
	methods: {
		prompt: function() {
			alert("按下了F5!")
		}
	}
})

5、v-if 和 v-show 条件渲染

5.1、v-if

v-if 指令用于条件性地渲染一块内容,这块内容只会在指令的表达式返回 true 时被渲染。例如:

<div id="app">
	<div v-if="seen">可以被控制的内容</div>
</div>
var vm = new Vue({
	el: '#app',
	data: {
		seen: true
	}
})

上面代码中,v-if 指令将根据表达式 seen 的值(true或false)来决定是否插入 div 元素。

可以使用 v-else-ifv-else 指令配合 v-if 一起使用,例如:

<div id="app">
	<div v-if="score >= 90 && score <= 100">优秀</div>
	<div v-else-if="score > 60 && score <=90">良好</div>
	<div v-else>不及格</div>
</div>
var vm = new Vue({
	el: '#app',
	data: {
		score: 90
	}
})

v-else 的元素必须紧跟在 v-ifv-else-if 的元素后面,而 v-else-if 的元素也必须紧跟在 v-if 元素的后面,v-elsev-else-if 都不能单独使用。

由于 v-if 是一个指令,所以必须将它添加到一个元素上,但是如果想要切换多个元素,可以使用 <template> 元素当做不可见的包裹元素,并在该元素上使用 v-if ,最终渲染的结果不会包含 <template> 元素。例如:

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

5.2、使用 key 管理可复用的元素

Vue会尽可能高效地渲染元素,通常会复用已有元素,而不是从头开始渲染。这么做除了使Vue变得非常快之外,还有一些其他好处。例如,如果项目中设计了两种用户登录的方式,可以使用 v-if 实现不同登录方式的切换。

<div id="app">
	<template v-if="loginType">
		<label>用户名:</label>
		<input placeholder="请输入用户名">
	</template>
	<template v-else>
		<label>邮箱:</label>
		<input placeholder="请输入邮箱">
	</template>
	<button @click="toggleType">切换登录方式</button>
</div>
var vm = new Vue({
	el: '#app',
	data: {
		loginType: true
	},
	methods: {
		toggleType: function() {
			this.loginType = !this.loginType;
		}
	}
})

上面的代码中,切换 loginType 将不会清除用户已经输入的内容,因为两个模板使用了相同的元素,<input>

元素被复用了,不会被替换掉,而是仅仅替换了元素中的 placeholder 属性的值。效果如下:

这种情况肯定是不符合实际的需求的,所以Vue提供了一种方式来解决这个问题,即为不需要复用的元素上添加一个 key 属性,告诉Vue这是两个独立的元素,不要复用它们。示例代码:

<div id="app">
	<template v-if="loginType">
		<label>用户名:</label>
		<input placeholder="请输入用户名" key="username-input">
	</template>
	<template v-else>
		<label>邮箱:</label>
		<input placeholder="请输入邮箱" key="email-input">
	</template>
	<button @click="toggleType">切换登录方式</button>
</div>

input 添加 key 属性之后,每次切换时,输入框都将被重新渲染,效果如下:

由于 <label> 元素没有添加 key 属性,所以仍然会被高效地复用。

5.3、v-show

Vue还提供了一种根据条件展示元素的选项,这就是 v-show 指令,示例:

<div id="app">
	被控制的内容:<span v-show="ok">Hello</span>
</div>
var vm = new Vue({
	el: '#app',
	data: {
		ok: false
	}
})

v-if 不同的是,v-show 的值无论是什么,被该指令修饰的元素始终会被渲染并保留在DOM中,v-show 只是简单地切换元素的CSS属性 display:none。上面代码在浏览器中的效果如下:

这里需要注意的是,v-show 不支持 <template> 元素,也不支持 v-else

5.4、v-if 和 v-show 的区别

(1)显隐过程:

虽然两个指令都可以动态的显示DOM元素,但是在执行上还是有很大区别的:

  • v-if是动态的向DOM树内添加或删除DOM元素;
  • v-show是通过设置DOM元素的display样式属性控制显示或隐藏;

(2)编译过程:

  • v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;
  • v-show只是简单的基于css切换;

(3)编译条件:

  • v-if是惰性的,如果初始条件为假,则什么都不做;只有在条件第一次为真时才开始局部编译(当编译被缓存后,再次切换时会进行局部卸载);
  • v-show是在任何条件下(首次条件是否为真)都会被编译,然后被缓存,而且DOM元素保留;

(4)性能消耗:

  • v-if有更高的切换性能消耗;
  • v-show有更高的初始渲染性能消耗;

(5)使用场景:

  • v-if适合运行时条件少改变的场景;
  • v-show适合频换切换的场景;

5.5、总结

v-if判断是否加载,可以减轻服务器的压力,在需要时加载,但是会造成更高的切换开销;

v-show调整DOM元素的CSS的display属性,可以使客户端操作更加流畅,但是有更高的初始渲染开销;

v-if 注意事项

官方文档中不建议 v-if 和 v-for 一起使用,当它们一起使用时,v-for 具有比 v-if 更高的优先级,这就意味着 v-if 将分别重复运行于每个 v-for 循环中。


6、v-for 列表渲染

6.1、遍历数组

可以使用 v-for 指令基于一个数组来渲染列表。v-for 指令需要使用“元素 in 数组”形式的特殊语法,即 item in items 的语法形式,其中 items 是源数据的数组,item 是被遍历的数组元素的别名。示例代码:

<ul id="app">
	<li v-for="item in list">{{item}}</li>
</ul>
var vm = new Vue({
	el: '#app',
	data: {
		list: [1,2,3,4,5]
	}
})

运行结果:

  • 1
  • 2
  • 3
  • 4
  • 5

v-for 块中,我们可以访问所有父作用域的属性。v-for 还支持一个可选的第二个参数,即当前项的索引。

<ul id="app">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
var vm = new Vue({
  el: '#app',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

运行结果:

  • Parent - 0 - Foo
  • Parent - 1 - Bar

也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:

<div v-for="item of items"></div>

6.2、遍历对象

可以用 v-for 来遍历一个对象的属性,示例代码:

<ul id="app">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
new Vue({
  el: '#app',
  data: {
    object: {
      name: 'Tom',
      age: 20,
      sex: '男'
    }
  }
})

结果:

  • Tom
  • 20

也可以提供第二个的参数为 property 名称 (也就是键名):

<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>

结果:

name:Tom
age:20
sex:男

还可以用第三个参数作为索引:

<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>

结果:

0. name:Tom
1. age:20
2. sex:男

注意:使用v-for遍历对象时,会按照 Object.keys() 的结果遍历,但是不能保证它的结果在通过的JavaScript引擎下都一致。

6.3、遍历整数

v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

结果:

 1 2 3 4 5 6 7 8 9 10

6.4、在<template>上使用v-for

类似于 v-if,你也可以利用带有 v-for 的 ` 来循环渲染一段包含多个元素的内容。比如:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

6.5、使用key属性

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一 key 属性:

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>

建议尽可能在使用 v-for 时提供 key 属性,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

key属性的注意事项:

  • v-for循环时,key属性只能使用number和string类型;
  • key在使用时,必须使用v-bind属性绑定的形式,指定key的值;
  • 在组件中使用v-for循环时,必须在使用v-for的同时,指定唯一的key属性值;

6.6、数组的更新操作

Vue将被侦听的数组的变异方法(mutation method)进行了包裹,这里的变异方法,是指数组对象提供的调用后会改变数组原始数据的方法。同时,也有非变异方法(non-mutation method),非变异方法不会改变原始数组,而是返回一个新数组。

Vue可以侦听数组的变异方法,所以数组的变异方法被调用后也会触发视图的更新,这些方法包括:

  • push(): 向数组的末尾添加一个或更多元素,并返回新的长度;
  • pop(): 删除数组的最后一个元素并返回删除的元素;
  • shift(): 删除并返回数组的第一个元素;
  • unshift(): 向数组的开头添加一个或更多元素,并返回新的长度;
  • splice(): 从数组中添加或删除元素;
  • sort(): 对数组的元素进行排序;
  • reverse(): 反转数组的元素顺序;

非变异方法不会更改原始数组,总是返回一个新数组,非变异方法包括:

  • filter(): 检测数值元素,并返回符合条件所有元素的数组;
  • concat(): 连接两个或更多的数组, 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本;
  • slice(): 选取数组的的一部分,并返回一个新数组;

所以当使用非变异方法时,可以用新数组替换旧数组:

vm.lsit = vm.list.filter(function(item){
	return item.msg.match(/Foo/)
})

上面代码中,将 filter() 方法返回的新数组替换了Vue实例的数据对象中的数组,虽然对Vue实例的数据对象重新赋值,但是并不会重新渲染整个列表,因为Vue为了使得DOM元素得到最大范围的重用二实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

但是,由于JavaScript的限制,Vue不能检测以下数组的变动:

  • 使用索引直接设置数组项时,例如:vm.items[indexOfItem] = newValue
  • 直接修改数组的长度,例如: vm.items.length = newLength

举个例子:

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

解决第一类问题,即使用索引设置数组项:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
//或者使用 vm.$set 实例方法,该方法是全局方法Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)
// 使用数组的splice方法
vm.items.splice(indexOfItem, 1, newValue)

解决第二类问题,即修改数组length属性,可以使用 splice 方法:

vm.items.splice(newLength)

6.7、对象的更新操作

还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的

vm.b = 2
// `vm.b` 不是响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。例如,对于:

var vm = new Vue({
  data: {
    user: {
      name: 'Anika'
    }
  }
})

你可以添加一个新的 age 属性到嵌套的 user 对象:

Vue.set(vm.user, 'age', 27)

你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:

vm.$set(vm.user, 'age', 27)

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign()_.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性, 应该这样做:

vm.user = Object.assign({}, vm.user, {
  age: 27,
  favoriteColor: 'Vue Green'
})

6.8、显示过滤/排序后的结果

有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。

例如:

<li v-for="n in evenNumbers">{{ n }}</li>
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法:

<li v-for="n in even(numbers)">{{ n }}</li>
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

7、v-model 表单数据绑定

7.1、基本用法

双向数据绑定是Vue的核心特性之一,Vue的响应式原理是实现了数据—>视图,而双向数据绑定,就是在完成前面那一步之后,又做了视图—>数据的操作。 v-model 指令可以在表单元素,例如:<input><textarea> 以及 <select> 等元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

v-model 会忽略所有表单元素的 valuecheckedselected属性的初始值,以Vue实例的数据作为数据来源,可以通过Vue实例中的数据对象data中声明表单的初始值。

文本

<div id="app">
	<input v-model="msg" />
	<p>结果:{{msg}}</p>
</div>
var vm = new Vue({
	el: '#app',
	data: {
		msg: ''
	}
})

多行文本

<div id="app">
	<textarea v-model="msg"></textarea>
	<p>结果:{{msg}}</p>
</div>
var vm = new Vue({
	el: '#app',
	data: {
		msg: ''
	}
})

在文本区域插值 ({{text}}) 并不会生效,应用 v-model 来代替。

复选框

单个复选框绑定布尔值:

<div id="app">
	<input type="checkbox" v-model="checked" />
	<label>{{ checked }}</label>
</div>
var vm = new Vue({
	el: '#app',
	data: {
		checked: false
	}
})

多个复选框,绑定到一个数组:

<div id='app'>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>
new Vue({
  el: '#app',
  data: {
    checkedNames: []
  }
})

单选按钮

<div id="app">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>
new Vue({
  el: '#example-4',
  data: {
    picked: ''
  }
})

下拉框

单选时:

<div id="app">
  <select v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>
new Vue({
  el: '#app'
  data: {
    selected: ''
  }
})

多选时:

<div id="app">
  <select v-model="selected" multiple style="width: 50px;">
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>
new Vue({
  el: '#app',
  data: {
    selected: []
  }
})

v-for 渲染的动态选项:

<select v-model="selected">
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
  el: '#app',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})

7.2、值绑定

对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值):

<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a">

<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">

<!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

但是有时我们可能想把值绑定到 Vue 实例的一个动态属性上,这时可以用 v-bind 实现,并且这个属性的值可以不是字符串。

复选框

<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'

这里的 true-valuefalse-value attribute 并不会影响输入控件的 value attribute,因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交,(比如“yes”或“no”),请换用单选按钮。

单选按钮

<input type="radio" v-model="pick" v-bind:value="a">
// 当选中时
vm.pick === vm.a

下拉框的选项

<select v-model="selected">
    <!-- 内联对象字面量 -->
  <option v-bind:value="{ number: 123 }">123</option>
</select>
// 当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123

7.3、修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >

.number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

<input v-model.number="age" type="number">

这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。

.trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

<input v-model.trim="msg">