4.Vue指令(Directives)

目录


Vue专栏目录(点击进入…)


Vue指令(Directives)


Vue指令(Directives)

指令(Directives)是带有“v-”前缀的特殊attribute(属性)。指令attribute的值预期是单个JavaScript表达式(v-for是例外情况)
v-bind属性称为指令。指令带有前缀v-以指示它们是Vue提供的特殊属性,它们将特殊的反应性行为应用于渲染的DOM

指令职责:当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM

指令描述
v-bind元素属性绑定,简写“:”
v-text元素文本绑定
v-html元素html值绑定
v-if动态条件判断
v-showcss静态渲染条件
v-for循环遍历
v-on事件监听,简写“@”
v-model表单双向绑定
v-once渲染一次,即为静态内容
v-pre跳过编译,即为不编译
v-cloakVue实例加载完成后编译

(1)v-bind(元素属性绑定,简写“:”★)

用来动态的绑定一个或者多个特性。没有参数时,可以绑定到一个包含键值对的对象。常用于动态绑定class和style。以及href等。简写为一个冒号:“:”


1.html代码

除了文本插值,还可以像这样绑定元素属性:v-bind:title

<script src="./js/vue.js" type="text/javascript" charset="utf-8"></script>

<div id="oneVue">
	{{vueData}} me too! <br> <span v-bind:title="message">Hello</span>
</div>

<script type="text/javascript">
	const oneVue = new Vue({
		el : "#oneVue",
		data : {
			vueData : 'First study vue!',
			message : 'You loaded this page on '+ new Date().toLocaleString()
		}
	});
</script>

2.vue反应性

如果再次打开JavaScript控制台并输入oneVue.message = ‘some new message’,鼠标放到span上的时候信息已更新
在这里插入图片描述

class类属性切换例子

1.html
<div id="app">
    ①:对象语法
    当data里面定义的isActive等于true时,is-active这个class类属性才会被添加
    当data里面定义的hasError等于true时,text-danger这个class类属性才会被添加
	<div :class="{'is-active':isActive, 'text-danger':hasError}"></div>

	②:对象语法
	errorClass在data对应的类一定会添加
	is-active是对象语法,根据activeClass对应的取值决定是否添加
	<p :class="[{'is-active':activeClass},errorClass]">12345</p>
	
	③:直接绑定数据对象
	在vue实例的data中定义了classObject对象,这个对象里面是所有类名及其真值
	当里面的类的值是true时会被渲染
    <div :class="classObject">12345</div>
</div>
var app = new Vue({
	el: '#app',
	data: {
	    // ①:对象语法
		isActive: true,  
		hasError: false
		
		// ②:数组语法
		activeClass: false,
		errorClass: 'text-danger'
		
		// ③:直接绑定数据对象
		classObject:{
			'is-active': false,
			'text-danger':true
		}
	}
})

渲染结果:

 ①:对象语法
<!--因为hasError: false,所以text-danger不被渲染-->
<div class = "is-active"></div>

②:数组语法
<!--因为activeClass: false,所以is-active不被渲染-->
<p class = "text-danger"></p>

③:直接绑定
<!--因为'is-active': false,所以is-active不被渲染-->
<div class = "text-danger"></div>

当data里面定义的isActive等于true时,is-active这个class类属性才会被添加
当data里面定义的hasError等于true时,text-danger这个class类属性才会被添加


(2)v-on(监听DOM事件,简写:“@”)

使用v-on指令来附加事件侦听器,主要用来监听DOM事件,以便执行一些代码块。表达式可以是一个方法名

<div id="app">
    <button @click="consoleLog"></button>
</div>

var app = new Vue({
	el: '#app',
	methods:{
		consoleLog:function (event) {
			console.log(1)
		}
	}
})

1.html代码

<div id="oneVue">
	<p>{{ message }}</p>
	<button v-on:click="reverseMessage">Reverse Message</button>
</div>

<script type="text/javascript">
	const oneVue = new Vue({
		el : "#oneVue",
		data : {
			dataMessage : 'Hello Vue.js!'
		},
		methods : {
			reverseMessage : function() {
				this.message = this.message.split('').reverse().join('')
			},
		}
	});
</script>

2.vue反应性

注意:在这种方法中,无需接触DOM就可以更新应用程序的状态,所有DOM操作均由Vue处理,并且编写的代码集中在基础逻辑上

在这里插入图片描述


(3)v-text(文本)

v-text主要用来更新textContent(标签文本值),等同于JS的text属性

两者等价:

<span v-text="msg"></span>
<span>{{ msg }}</span>

(4)v-html(html代码)

双大括号的方式会将数据解释为纯文本,而非HTML。为了输出真正的HTML,可以用v-html指令。它等同于JS的innerHtml属性

<div v-html="rawHtml"></div>

这个div的内容将会替换成属性值rawHtml,直接作为HTML进行渲染


(5)v-if(动态条件)

v-if、v-else、 v-else-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素

①:v-if

<a v-if="ok">yes</a>

如果属性值ok为true,则显示。否则,不会渲染这个元素

②:v-if/v-else
v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。

<a v-if="ok">yes</a>
<a v-else>No</a>

③:v-if/v-else-if/v-else
v-else-if充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句

<div v-if="type==='A'">A</div>
<div v-else-if="type==='B'">B</div>
<div v-else-if="type==='C'">C</div>
<div v-else>Not A,B,C</div>

1.html代码

<div id="oneVue">
	<span v-if="seen"> Now you see me </span>
</div>

<script type="text/javascript">
	const oneVue = new Vue({
		el : "#oneVue",
		data : {
			seen : true
		}
	});
</script>

2.vue反应性

不仅可以将数据绑定到文本和属性,还可以将其绑定到DOM的结构。此外,Vue还提供了功能强大的过渡效果系统,当Vue插入/更新/删除元素时,该系统可以自动应用过渡效果;还有很多其他指令,每个指令都有其自己的特殊功能。
在这里插入图片描述

(6)v-show(css条件渲染)

用于根据条件展示元素。和v-if不同的是,如果v-if的值是false,则这个元素被销毁,不在DOM中。但是v-show的元素会始终被渲染并保存在DOM中,它只是简单的切换css的dispaly属性

<h1 v-show="ok">hello world</h1>

注意:v-if有更高的切换开销,v-show有更高的初始渲染开销。
因此,如果要非常频繁的切换,则使用v-show较好;如果在运行时条件不太可能改变,则v-if较好


(7)v-for(循环遍历)

可用于使用Array中的数据显示项目列表:用v-for指令根据遍历数组来进行渲染

两种遍历形式(in/of

①:使用in。index是一个可选参数,表示当前项的索引
<div v-for="(item,index) in items"></div>
②:使用of
<div v-for="item of items"></div>

在v-for中,拥有对父作用域属性的完全访问权限

<ul id="app">
    <li v-for="item in items">
        {{parent}}-{{item.text}}
    </li>
</ul>

var example = new Vue({
	el:'#app',
	data:{
		parent:'父作用域'
		items:[
			{text:'文本1'},
			{text:'文本2'}
		]
	}
})

会被渲染为:

<ul id="app">
    <li>父作用域-文本1</li>
    <li>父作用域-文本2</li>
</ul>

注意:当v-for和v-if同处于一个节点时,v-for的优先级比v-if更高。这意味着v-if将运行在每个v-for循环中


1.html代码

<div id="oneVue">
	<ol>
		<li v-for="todo in todos">
			{{ todo.text }}
		</li>
	</ol>
</div>

<script type="text/javascript">
	const oneVue = new Vue({
		el: "#oneVue",
		data: {
			todos: [
				{text: 'Learn JavaScript'},
				{text: 'Learn Vue'},
				{text: 'Build something awesome'}
			]
		}
	});
</script>

2.vue反应性

在控制台中,输入oneVue.todos.push({ text: ‘New item’ })。可以看到被附加到列表中
在这里插入图片描述


(8)v-model(表单双向绑定)

用于在表单上创建双向数据绑定,使表单输入和应用程序状态之间的双向绑定变得轻而易举
v-model会忽略所有表单元素的value、checked、selected特性的初始值。因为它选择Vue实例数据做为具体的值

v-model修饰符

修饰符描述
.lazy默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步
.numbe自动将用户的输入值转化为数值类型
.trim自动过滤用户输入的首尾空格
<input v-model.lazy="msg">
<input v-model.number="msg">
<input v-model.trim="msg">

1.html代码

<div id="oneVue">
	<p>{{ fromMessage }}</p>
	<input v-model="fromMessage ">
</div>

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

这个例子中直接在浏览器input中输入别的名字,下面的p#formMessage的内容会直接跟着变。这就是双向数据绑定


(9)v-once(渲染一次:静态内容)

v-once关联的实例,只会渲染一次。之后的重新渲染,实例及其所有的子节点将被视为静态内容跳过,可以用于优化更新性能

<span v-once>This will never change:{{ msg }}</span>  // 单个元素
<div v-once> // 有子元素
    <h1>comment</h1>
    <p>{{ msg }}</p>
</div>

<my-component v-once:comment="msg"></my-component>  // 组件
<ul>
    <li v-for="i in list">{{ i }}</li>
</ul>

上面的例子中,msg、list即使产生改变,也不会重新渲染


(10)v-pre(跳过编译)

v-pre主要用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签。跳过大量没有指令的节点加快编译

<div id="app">
    <span v-pre>{{ message }}</span>  // 这条语句不进行编译
    <span>{{ message }}</span>
</div>

最终仅显示第二个span的内容


(11)v-cloak(实例加载完成后编译)

用来保持在元素上直到关联实例结束时进行编译

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

const app = new Vue({
	el:'#app',
	data:{
		message:'hello world'
	}
})

在页面加载时会闪烁,先显示:

<div>
    {{ message }}
</div>

然后才会编译为:

<div>
    hello world!
</div>

指令参数、指令缩写(v-bind、v-on)

(1)指令参数

一些指令能够接收一个“参数”,在指令名称之后以冒号表示

1.v-bind指令参数

v-bind指令可以用于响应式地更新HTML attribute。href是参数,v-bind指令将该元素的href attribute与表达式url的属性值绑定

<a v-bind:href="url">...</a>

2.v-on指令参数

v-on指令,用于监听DOM事件,参数是监听的事件名

<a v-on:click="doSomething">...</a>

(2)指令简写

以“v-”前缀作为一种视觉提示,用来识别模板中Vue特定的attribute。当在使用Vue.js为现有标签添加动态行为(dynamic behavior)时,“v-”前缀很有帮助,然而,对于一些频繁用到的指令来说,就会感到使用繁琐。同时,在构建由Vue管理所有模板的单页面应用程序(SPA - single page application)时,“v-”前缀也变得没那么重要了。因此,Vue为v-bind和v-on这两个最常用的指令,提供了特定简写

1.v-bind指令缩写:“:”

<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>

2.v-on指令缩写:“@”

<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>

它们看起来可能与普通的HTML略有不同,但“:”与“@”对于attribute名来说都是合法字符,在所有支持Vue的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的


Class与Style绑定(v-bind:“:”)

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


绑定HTML Class

(1)对象语法

可以传给v-bind:class一个对象,以动态地切换class

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

表示active这个class存在与否将取决于数据property isActive的truthiness

可以在对象中传入更多字段来动态切换多个class。此外,v-bind:class指令也可以与普通的class attribute共存。当有如下模板:

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

data: {
	isActive: true,
	hasError: false
}

结果渲染为:

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

当isActive或者hasError变化时,class列表将相应地更新。
例如:如果hasError的值为true,class列表将变为"static active text-danger"

绑定的数据对象不必内联定义在模板里:

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

data: {
	classObject: {
		active: true,
		'text-danger': false
	}
}	

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

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

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

(2)数组语法

可以把一个数组传给v-bind:class,以应用一个class列表

<div v-bind:class="[activeClass, errorClass]"></div>

data: {
	activeClass: 'active',
	errorClass: 'text-danger'
}

渲染为:

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

如果也想根据条件切换列表中的class,可以用三元表达式:

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

这样写将始终添加errorClass,但是只有在isActive是truthy[1]时才添加activeClass。当有多个条件class时这样写有些繁琐。所以在数组语法中也可以使用对象语法:

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

(3)用在组件上

当在一个自定义组件上使用class property时,这些class将被添加到该组件的根元素上面。这个元素上已经存在的class不会被覆盖

例如:如果声明了这个组件

Vue.component('my-component', {
	template: '<p class="foo bar">Hi</p>'
})

然后在使用它的时候添加一些class:

<my-component class="baz boo"></my-component>

HTML将被渲染为:

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

对于带数据绑定class也同样适用:

<my-component v-bind:class="{ active: isActive }"></my-component>

当isActive为true时,HTML将被渲染成为:

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

绑定内联样式

(1)对象语法

v-bind:style的对象语法十分直观——看着非常像CSS,但其实是一个JavaScript对象

CSS property 名可以用驼峰式(camelCase)或短横线分隔(kebab-case,记得用引号括起来)来命名:

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

data: {
	activeColor: 'red',
	fontSize: 30
}

直接绑定到一个样式对象通常更好,这会让模板更清晰:

<div v-bind:style="styleObject"></div>

data: {
	styleObject: {
		color: 'red',
		fontSize: '13px'
	}
}

同样的,对象语法常常结合返回对象的计算属性使用


(2)数组语法

v-bind:style的数组语法可以将多个样式对象应用到同一个元素上

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

(3)自动添加前缀

当v-bind:style使用需要添加浏览器引擎前缀的CSS property时,如transform,Vue.js会自动侦测并添加相应的前缀


(4)多重值(2.3.0+)

从2.3.0起可以为style绑定中的property提供一个包含多个值的数组,常用于提供多个带前缀的值

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

这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的flexbox,那么就只会渲染 display: flex


动态指令参数(2.6.0新增)

2.6.0开始,可以用方括号括起来的JavaScript表达式作为一个指令的参数

<a v-bind:[attributeName]="url"> ... </a>

注意:参数表达式的写法存在一些约束
这里的attributeName会被作为一个JavaScript表达式进行动态求值,求得的值将会作为最终的参数来使用。
例如:如果Vue实例有一个data property attributeName,其值为“href”,那么这个绑定将等价于v-bind:href。

同样,可以使用动态参数为一个动态的事件名绑定处理函数:

<a v-on:[eventName]="doSomething"> ... </a>

在这个示例中,当eventName的值为“focus”时,v-on:[eventName]将等价于v-on:focus


动态参数的值约束
动态参数预期会求出一个字符串,异常情况下值为null。这个特殊的null值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。

动态参数表达式的约束
动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在HTML attribute名里是无效的。例如:

<!-- 这会触发一个编译警告 -->
<a v-bind:['foo' + bar]="value"> ... </a>

解决办法是使用没有空格或引号的表达式,或用计算属性替代这种复杂表达式。

在DOM中使用模板时(直接在一个HTML文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把attribute名全部强制转为小写:

<a v-bind:[someAttr]="value"> ... </a>

注意:在DOM中使用模板时这段代码会被转换为“v-bind:[someattr]”。除非在实例中有一个名为“someattr”的 property,否则代码不会工作


事件处理(v-on:“@”)

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

<div id="app">
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>

var app = new Vue({
	el: '#app',
	data: {
		counter: 0
	}
})

事件处理方法

许多事件处理逻辑会更为复杂,所以直接把JavaScript代码写在v-on指令中是不可行的。因此v-on还可以接收一个需要调用的方法名称

<div id="app">
	<!-- greet是在下面定义的方法名 -->
	<button v-on:click="greet">Greet</button>
</div>

var app = new Vue({
el: '#app',
	data: {
		name: 'Vue.js'
	},
	// 在methods对象中定义方法
	methods: {
		greet: function (event) {
			// this在方法里指向当前Vue实例data下属性
			alert('Hello ' + this.name + '!')
			// event是原生DOM事件
			if (event) {
				alert(event.target.tagName)
			}
		}
	}
})

// 也可以用 JavaScript 直接调用方法
app.greet() // 输出 => 'Hello Vue.js!'

内联处理器中的方法

除了直接绑定到一个方法,也可以在内联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)
		}
	}
})

访问原生DOM事件

有时也需要在内联语句处理器中访问原始的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)
	}
}

条件渲染(v-if、v-show)

v-if

1.v-if

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

<h1 v-if="awesome">Vue is awesome!</h1>

也可以用 v-else 添加一个“else 块”:

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no</h1>

在<template>元素上使用v-if条件渲染分组
因为v-if是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个<template>元素当做不可见的包裹元素,并在上面使用v-if。最终的渲染结果将不包含<template>元素。


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

2.v-else-if(2.1.0新增)

v-else-if,顾名思义,充当v-if的“else-if 块”,可以连续使用

<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>

必须紧跟在带v-if或者v-else-if的元素之后

3.v-else

可以使用v-else指令来表示v-if的“else块”

<div v-if="Math.random() > 0.5">Now you see me</div>
<div v-else>Now you don't</div>

类似于v-else-if,v-else元素必须紧跟在带v-if或者v-else-if的元素的后面,否则它将不会被识别


key管理可复用的元素

Vue会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使Vue变得非常快之外,还有其它一些好处

例如:如果允许用户在不同的登录方式之间切换:复用已有元素

<template v-if="loginType === 'username'">
	<label>Username</label>
	<input placeholder="Enter your username">
</template>

<template v-else>
	<label>Email</label>
	<input placeholder="Enter your email address">
</template>	

那么在上面的代码中切换loginType将不会清除用户已经输入的内容。因为两个模板使用了相同的元素;不会被替换掉,仅仅是替换了它的placeholder,这样也不总是符合实际需求


独立元素:不复用(key)

Vue提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的key attribute即可

<template v-if="loginType === 'username'">
	<label>Username</label>
	<input placeholder="Enter your username" key="username-input">
</template>

<template v-else>
	<label>Email</label>
	<input placeholder="Enter your email address" key="email-input">
</template>

注意:现在,每次切换时,输入框都将被重新渲染;


v-show

用于根据条件展示元素的选项是v-show指令。用法大致一样

<h1 v-show="ok">Hello!</h1>

不同的是带有v-show的元素始终会被渲染并保留在DOM中。v-show只是简单地切换元素的CSS property display
注意:v-show不支持<template>元素,也不支持v-else


v-if 与v-show比较

(1)v-if

“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做;直到条件第一次变为真时,才会开始渲染条件块


(2)v-show

相比之下,v-show就简单得多,不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换。
一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show 较好;如果在运行时条件很少改变,则使用v-if较好

总结:v-if资源开销大,v-show适合频繁切换


列表渲染(for)

(1)v-for将一个数组对应为一组元素

可以用v-for指令基于一个数组来渲染一个列表。v-for指令需要使用item in items形式的特殊语法,其中items是源数据数组,而item则是被迭代的数组元素的别名

<ul id="example-1">
	<li v-for="item in items" :key="item.message">
		{{ item.message }}
	</li>
</ul>

var example1 = new Vue({
	el: '#example-1',
	data: {
		items: [
			{ message: 'Foo' },
			{ message: 'Bar' }
		]
	}
})

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

	<ul id="example-2">
	<li v-for="(item, index) in items">
		{{ parentMessage }} - {{ index }} - {{ item.message }}
	</li>
</ul>

var example2 = new Vue({
	el: '#example-2',
	data: {
		parentMessage: 'Parent',
		items: [
			{ message: 'Foo' },
			{ message: 'Bar' }
		]
	}
})	

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

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

(2)v-for中使用对象

也可以用v-for来遍历一个对象的property

<ul id="v-for-object" class="demo">
	<li v-for="value in object">
		{{ value }}
	</li>
</ul>

new Vue({
	el: '#v-for-object',
	data: {
		object: {
			title: 'How to do lists in Vue',
			author: 'Jane Doe',
			publishedAt: '2016-04-10'
		}
	}
})

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

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

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

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

在遍历对象时,会按Object.keys()的结果遍历,但是不能保证它的结果在不同的JavaScript引擎下都一致


维护状态

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

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(例如:表单输入值)的列表渲染输出。

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

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

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

因为它是Vue识别节点的一个通用机制,key并不仅与v-for特别关联
不要使用对象或数组之类的非基本类型值作为v-for的key。请用字符串或数值类型的值。


数组更新检测

(1)变更方法

Vue将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
也就是能够直接使用,调用以下方法会改变原数组

方法描述
push()向数组的末尾添加一个或多个元素,并返回新的长度
pop()用于删除并返回数组的最后一个元素
shift()用于把数组的第一个元素从其中删除,并返回第一个元素的值
unshift()向数组的开头添加一个或更多元素,并返回新的长度
splice()向/从数组中添加/删除/替换元素,然后返回被删除的元素
sort()用于对数组的元素进行排序
reverse()用于颠倒数组中元素的顺序

splice()

方法描述
删除可以删除任意数量的项
参数:splice(要删除的第一项的位置删除项的项数)
插入可以向指定位置插入任意数量的项
参数:splice(插入起始位置要删除的项数(0)插入的任意数量项(n+))
如果要插入多个项,可以再传入第四、第五,一直任意多个项。
替换可以向指定位置插入任意数量的项,且同时删除任意数量的项
参数 :splice(起始位置要删除的项数(0)插入的任意数量项(n+))
插入的项数是不必与删除的项数相等

splice()参数

参数描述
index必需。整数,规定添加/删除元素的位置,使用负数可从数组结尾处规定位置
howmany必需。要删除的元素数量。如果设置为 0,则不会删除元素
item1, …, itemX可选。向数组添加的新元素

(2)替换数组

变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法:filter()、concat()和slice()。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:

可能认为这将导致Vue丢弃现有DOM并重新渲染整个列表。幸运的是,事实并非如此。Vue为了使得DOM元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作

注意事项:由于JavaScript的限制,Vue不能检测数组和对象的变化

方法描述
filter()通过检查指定数组中符合条件的所有元素,并返回一个新数组。
注意:filter()不会对空数组进行检测
concat()用于连接两个或多个数组,并返回一个新数组。
slice()返回一个新的数组,包含从start到end(不包括该end元素)的 元素

filter(function(currentValue,index,arr), thisValue)

方法描述
function(currentValue, index,arr) 必须。函数,数组中的每个元素都会执行这个函数
函数参数描述
currentValue必须。当前元素的值
index可选。当前元素的索引值
arr可选。当前元素属于的数组对象
thisValue可选。对象作为该执行回调时使用,传递给函数,用作 “this” 的值。
如果省略了 thisValue ,“this” 的值为 “undefined”

concat(arrayX,arrayX,…,arrayX)

参数描述
arrayX必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个。

slice(start,end)

参数描述
start必需。规定从何处开始选取。
如果是负数,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
end可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。
如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。
如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

在v-for里使用值范围

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

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

在<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>

v-if与v-for一起使用

不推荐同时使用v-if和v-for

当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中。当只想为部分项渲染节点时,这种优先级的机制会十分有用

<li v-for="todo in todos" v-if="!todo.isComplete">
	{{ todo }}
</li>

上面的代码将只渲染未完成的todo。


而如果目的是有条件地跳过循环的执行,那么可以将v-if置于外层元素(或)上

<ul v-if="todos.length">
	<li v-for="todo in todos">
		{{ todo }}
	</li>
</ul>
<p v-else>No todos left!</p>

表单输入绑定(v-model)

可以用v-model指令在表单<input>、<textarea>及<select>元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理

v-model会忽略所有表单元素的value、checked、selected attribute的初始值而总是将Vue实例的数据作为数据来源。通过JavaScript在组件的data选项中声明初始值

v-model在内部为不同的输入元素使用不同的property并抛出不同的事件:
①text和textarea元素使用value property和input事件
②checkbox和radio使用checked property和change事件
③select字段将value作为prop并将change作为事件
对于需要使用输入法(如中文、日文、韩文等)的语言,会发现v-model不会在输入法组合文字过程中得到更新。如果也想处理这个过程,请使用input事件


(1)文本

<input v-model="message" placeholder="edit me">

(2)多行文本

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

<textarea v-model="message" placeholder="add multiple lines"></textarea>	

(3)复选框

单个复选框,绑定到布尔值:

<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>

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

<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>
<span>Checked names: {{ checkedNames }}</span>

new Vue({
	el: '...',
	data: {
		checkedNames: []
	}
})

(4)单选按钮

<div id="example-4">
	<input type="radio" id="one" value="One" v-model="picked">
	<label for="one">One</label>
	<input type="radio" id="two" value="Two" v-model="picked">
	<label for="two">Two</label>
	<span>Picked: {{ picked }}</span>
</div>

new Vue({
	el: '#example-4',
	data: {
		picked: ''
	}
})

(5)选择框

1.单选时:

<div id="example-5">
	<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: '...',
	data: {
		selected: ''
	}
})

如果v-model表达式的初始值未能匹配任何选项,元素将被渲染为“未选中”状态。在iOS中,这会使用户无法选择第一个选项。因为这样的情况下,iOS不会触发change事件。因此,更推荐像上面这样提供一个值为空的禁用选项


2.多选时(绑定到一个数组):

<div id="example-6">
	<select v-model="selected" multiple style="width: 50px;">
	<option>A</option>
	<option>B</option>
	<option>C</option>
	</select>
	<span>Selected: {{ selected }}</span>
</div>

new Vue({
	el: '#example-6',
	data: {
		selected: []
	}
})

3.用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: '...',
	data: {
		selected: 'A',
		options: [
			{ text: 'One', value: 'A' },
			{ text: 'Two', value: 'B' },
			{ text: 'Three', value: 'C' }
		]
	}
})

(6)值绑定

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

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

<!-- `toggle`truefalse -->
<input type="checkbox" v-model="toggle">

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

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


(7)复选框

<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no">

//当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'

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


(8)单选按钮

<input type="radio" v-model="pick" v-bind:value="a">

//当选中时
vm.pick === vm.a

(9)选择框的选项

<select v-model="selected">
	<!-- 内联对象字面量 -->
	<option v-bind:value="{ number: 123 }">123</option>
</select>

//当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未禾

您的支持是我最宝贵的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值