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-show css静态渲染条件
v-for 循环遍历
v-on 事件监听,简写“@”
v-model 表单双向绑定
v-once 渲染一次,即为静态内容
v-pre 跳过编译,即为不编译
v-cloak Vue实例加载完成后编译

(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">Hellospan>
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上的时候信息已更新
Vue指令(Directives)_第1张图片

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]">12345p>
	
	③:直接绑定数据对象
	在vue实例的data中定义了classObject对象,这个对象里面是所有类名及其真值
	当里面的类的值是true时会被渲染
    <div :class="classObject">12345div>
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处理,并且编写的代码集中在基础逻辑上

Vue指令(Directives)_第2张图片


(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">yesa>

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

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

<a v-if="ok">yesa>
<a v-else>Noa>

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

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

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插入/更新/删除元素时,该系统可以自动应用过渡效果;还有很多其他指令,每个指令都有其自己的特殊功能。
Vue指令(Directives)_第3张图片

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

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

<h1 v-show="ok">hello worldh1>

注意: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>父作用域-文本1li>
    <li>父作用域-文本2li>
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’ })。可以看到被附加到列表中
Vue指令(Directives)_第4张图片


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

<a :[key]="url"> ... a>

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


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

<a @click="doSomething">...a>

<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: '

Hi

'
})

然后在使用它的时候添加一些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 noh1>