Vue.js的指令
1.内部指令
指令是特殊的带有前缀 v-的特性。指令的值限定为绑定表达式,指令的职责就是当表达式的值改变时把某些特殊的行为应用到DOM上。
- 基础指令:
- v-show
- v-else
- v-model
- v-repeat[1.0-]
- v-for[1.0+]
- v-text
- v-el
- v-html
- v-on
- v-bind?
- v-ref
- v-pre
- v-cloak
- v-if
(1) v-if
v-if指令可以完全根据表达式的值在DOM中生成或移除一个元素。如果v-if表达式赋值为false,那么对应的元素就会从DOM中移除;否则,对应元素的一个克隆将被重新插入DOM中。
代码示例:
<body class="native">
<div id="example">
<p v-if="greeting">
</div>
</body>
<script>
var exampleAVM2 = new Vue({
el: '#example',
data:{
greeting: false
}
})
</script>
渲染的最终效果为:
<body class="native">
<div id="example">
</div>
<script>...</script>
</body>
因为v-if是一个指令,需要将它添加到一个元素上。但是如果想切换多个元素,则可以把 <template></template> 元素当作包装元素,并在其上使用v-if,最终的渲染结果不会包含它。
代码示例:
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
渲染的最终效果为:
<body class="native">
<div id="example">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</div>
</body>
(2) v-show
v-show指令是根据表达式的值来显示或者隐藏HTML元素,当v-show赋值为false时,元素将被隐藏。查看DOM时,会发现元素上多了一个内联样式 style=“display: none”。
代码示例:
<body>
<input type="text" v-model="message" placeholder="edit me">
<div id="example">
<p v-show="greeting">Hello!</p>
</div>
</body>
<script>
var exampleVM2 = new Vue({
el:'#example',
data:{
greeting: false
}
})
</script>
渲染的最终效果为
<body class="native">
<input type="text" v-model="message" placeholder="edit me">
<div id="example">
<p style="display: none">Hello!</p>
</div>
<script></script>
</body>
注意:v-show不支持<template> 语法
1)v-if与v-show的渲染区别:
a. v-show不支持<template> 语法,v-if支持<template> 语法;
b. 在切换v-if模块时,Vue.js有一个局部编译/卸载的过程,因为v-if中的模版可能包括数据绑定或子组件,v-if是真实的条件渲染,因为它会确保条件块在切换时合适地销毁或重建条件块内的事件监听器和子组件。
c. v-if是 惰性 的——如果初始渲染时条件为假,则什么也不做,在条件第一次变为真的时候才开始进行局部编译的工作(编译会被缓存起来)。相比之下,v-show简单的多——元素始终被编译并保留,只是简单的基于css切换。
2)v-if与v-show的使用场景对比:
一般来说,v-if具有更高的切换消耗(因为它只在值为true的时候才会渲染),而v-show具有更高的初始渲染消耗。因此,如果需要进行频繁的切换,则使用v-show较好;如果在运行条件不太可能改变的时候,则使用v-if比较好。
(3) v-else
v-else与js中的 else有异曲同工之处,它在使用的时候必须和v-if或v-show一起配合,充当else的功能,不能单独使用。 代码示例如下
<body class="native">
<div id="example">
<p v-if="ok">我是对的</p>
<p v-else>我是错的</p>
</div>
</body>
<script>
var exampleVM2 = new Vue({
el: "example",
data:{
ok: false
}
})
</script>
######1)v-else使用注意事项: 将v-show 用在组件上 时,因为指令的优先级v-else会出现问题,所以不要这样做。代码示例如下:
<custom-component v-show="condition"></custom-component>
<p v-else>这可能也是一个组件<p>
我们可以用另一个v-show来代替v-else,代码示例如下:
<custom-component v-show="condition"></custom-component>
<p v-show="!condition">这可能也是一个组件<p>
(4) v-model
v-model指令用来在input、select、text、checkbox、radio等表单控件元素上创建双向数据绑定。根据控件类型v-model自动选取正确的方法更新元素。尽管有点神奇,但是v-model不过是语法糖,在用户输入事件中更新数据,以及特别处理一些极端例子。代码示例如下:
<body id="example">
<form>
姓名:
<input type="text" v-model="data.name" placeholder="">
<br/>
性别:
<input type="radio" id="man" value="One" v-model="data.sex">
<label for="man">男</label>
<input type="radio" id="male" value="Two" v-model="data.sex">
<label for="male">女</label>
<br/>
兴趣:
<input type="checkbox" id="book" value="book" v-model="data.interest">
<label for="book">阅读</label>
<input type="checkbox" id="swim" value="swim" v-model="data.interest">
<label for="swim">游泳</label>
<input type="checkbox" id="game" value="game" v-model="data.interest">
<label for="game">游戏</label>
<input type="checkbox" id="song" value="song" v-model="data.interest">
<label for="song">唱歌</label>
<br/>
身份;
<select v-model="data.identity">
<option value="teacher" selected>教师</option>
<option value="doctor" >医生</option>
<option value="lawyer" >律师</option>
</select>
</form>
</body>
<script>
new Vue({
el:"",
data:{
name:"",
sex:"",
interest:[],
identity:""
}
})
</script>
渲染的最终效果为:
除了以上的使用方法,在v-model指令后面还可以添加多个参数(number、lazy、debounce)。
1)number:
如果想将用户的输入自动转换为Number类型(如果原值的转换结果为NaN,则返回的是原值),则可以添加一个number特性。
2)lazy:
在默认情况下,v-model在input事件中同步输入框的值与数据,我们可以添加一个lazy特性,从而将数据改到change事件中发生,代码示例如下:
<body id="example">
<input v-model="msg" lazy><br/>
{{msg}}
</body>
<script>
var exampleVM2 = new Vue({
el:"#example",
data:{
msg: '内容是在change事件后才改变的~'
}
})
</script>
我们在input框内输入“依然不变”,虽然触发了input事件,但是因为加入了lazy属性,msg的值一直没有发生变化。 总结:当添加了.lazy修饰符后,双向绑定的数据就不同步了,相当于在input输入框失去焦点后触发的change事件中同步。
3)debounce:
设置一个最小的延时,在每次敲击之后延时同步输入框的值与数据。如果每次更新数据都要进行高耗操作(例如,在input中输入内容时要随时发送AJAX请求——可能在数据更新之后要随时进行计算或者向后端发送请求的操作),那么它较为有用。 代码示例如下:
<body id="example">
<input v-model="msg" debounce="5000"><br/>
{{msg}}
</body>
<script>
var exampleVM2 = new Vue({
el:"#example",
data:{
msg:'内容是在5000ms后才改变的'
}
})
</script>
在5000ms之内我们将输入框中的值清空,下面的展示信息也并不会发生改变,只有在5000ms之后数据才会有进一步的更新。
(5) v-for
我们可以使用v-for基于源数据重复渲染元素。我们也可以使用$index来呈现相对应的数据索引。 代码示例如下:
<body id="example">
<ul>
<li v-for="(item, index) in items" class="item-{{$index}" :key="index">
{{ index }} - {{ parentMessage }} {{ item.msg }}
</li>
</ul>
</body>
<script>
var demo = new Vue({
el:"#demo",
data:{
parentMessage:'滴滴',
items:[
{ msg:"滴滴顺风车"},
{ msg:"滴滴专车"}
]
}
})
</script>
v-for需要特殊的别名,形式为“item in items” (items是数据数组,item是当前数组元素的别名)。v-for在开始时对传入的表达式做了语法分析,不是“item in/of items”的形式,将给出警告信息。Vue.js 1.0.17及以后版本支持of分隔符,更接近javascript遍厉器语法。
(6) v-text
v-text指令可以更新元素的textContent。在内部,{{ Mustache }}插值也被编译为 textNode的v-text指令。代码示例如下:
<span v-text="msg"></span><br/>
<!-- same as>
<span>{{msg}}</span>
(7) v-html
v-html指令可以更新元素的innerHTML。内容按普通HTML插入——数据绑定被忽略。如果想复用模版片段,则应当使用partials。 在内部,{{{ Mustache }}}插值也会被编译为锚节点上的一个v-html指令。 注:不建议在网站上直接动态渲染任意HTML片段,很容易导致XSS攻击。
<div v-html="html">
<div>{{ html }}</div>
</div>
(8) v-bind
v-bind指令用于响应更新HTML特性,将一个或多个attribute,或者一个组件prop动态绑定到表达式。v-bind可以简写为:
<img v-bind:src="imageSrc">
<img :src="imageSrc">
在绑定class或style时,支持其他类型的值,如数组或对象。代码示例如下:
<body id="example">
<div :class="[classA, {classB: isB, classC: isC }]"></div>
</body>
<script>
var demo = new Vue({
el: '#example',
data:{
classA: 'A',
isB : false,
isC: true
}
})
</script>
渲染的效果为:
<body id="example">
<div class="A classC"></div>
<script>...</script>
</body>
</html>
没有参数时,可以绑定到一个对象。注意,此时class和style绑定不支持数组和对象(对象key会转换为小写)。代码示例如下:
<body id="example">
<div v-bind="{ id: someProp, 'OTHERAttr': otherProp}"></div>
</body>
<script>
var exampleVN2 = new Vue({
el:'#example',
data:{
someProp: 'idName',
otherProp: 'prop'
}
})
</script>
渲染的结果如下:
<body id="example">
<div id="idName" otherattr="prop"></div>
</body>
在绑定prop时,prop必须在子组件中声明。可以用修饰符指定不同的绑定类型。修饰符为: 1) .sync(双向绑定,只能用于prop绑定) 2) .once(单次绑定,只能用于prop绑定) 3) .camel(将绑定的特性名字转换为驼峰命名。只能用于普通HTML特性的绑定,通常用于绑定用驼峰命名的SVG特性,比如viewBox)
<my-component :prop="someThing"></my-component>
<my-component :prop.sync="someThing"></my-component>
<my-component :prop.once="someThing"></my-component>
(9) v-on(使用的很多)
v-on指令用于绑定事件监听器。事件类型由参数指定;表达式可以是一个方法的名字或一个内联语句;如果没有修饰符,也可以省略。 使用在普通元素上时,只能监听原生DOM事件;在使用自定义元素组件上时,也可以监听子组件触发的自定义事件。 在监听原生DOM事件时,如果只定义一个参数,DOM event为事件的唯一参数;如果在内联语句处理器中访问原生DOM事件,则可以用特殊变量
e
v
e
n
t
把
它
传
入
方
法
。
V
u
e
.
j
s
1.0.11
及
以
后
版
本
在
监
听
自
定
义
事
件
时
,
内
联
语
句
可
以
访
问
一
个
event把它传入方法。 Vue.js 1.0.11 及以后版本在监听自定义事件时,内联语句可以访问一个
event把它传入方法。Vue.js1.0.11及以后版本在监听自定义事件时,内联语句可以访问一个argument属性,它是一个数组,包含了传给子组件的$emit回调的参数。
<button v-on:click="doThis"></button>
<button v-on:click="doThat('Hello', $event)"></button>
<button @click="doThis"></button>
v-on后面不仅可以跟参数,还可以增加修饰符: 1).stop 调用event.stopPropagation() 解释说明:阻止事件继续传播,即阻止事件冒泡 2).prevent 调用even.preventDefault() 3).capture 添加事件侦听器时使用 capture模式 4).self 只当事件是从侦听器绑定的元素本身触发时才触发回调。 5).{keyCode | keyAlias}——只在指定键上触发回调。Vue.js提供的键值有:[esc:27、tab: 9、enter:13、space:32、‘delete’:[8,46]、up:38、left:37、right:39、down:40]。
<button @click.stop="doThis"></button>
<button @click.prevent="doThis"></button>
<form @submit.prevent></form>
<button @click.stop.prevent="doThis">stop</button>
<input @keyup.enter="onEnter">
<input @keyup.13="onEnter">
(10) v-ref(新版弃用)
(11) v-el(新版弃用)
(12) v-pre
编译时候跳过当前的元素和它的子元素。可以用来显示原始Mustache标签。跳过大量没有指令的节点会加快编译。 注意: 不要在有插值语句,或者点击事件或者添加了标签属性的元素上加pre等等 1)跳过其所在节点的编译过程 2)可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
(13) v-cloak
v-cloak这个指令保持在元素上直到关联实例结束编译。AngularJS也提供了相同的功能。当和CSS规则如[v-cloak]{display:none}一起使用时,这个指令可以隐藏未编译的Mustache标签直到实例准备完毕,否则在渲染页面时,有可能用户会先看到Mustache标签,然后看到编译后的数据。用法如下:
[v-cloak]{
display: none;
}
<div v-cloak>
{{ message }}
</div>
备注: 可以使用 v-cloak 指令设置样式,这些样式会在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除。 当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码。我们可以使用 v-cloak 指令来解决这一问题。 在简单项目中,使用 v-cloak 指令是解决屏幕闪动的好方法。但在大型、工程化的项目中(webpack、vue-router)只有一个空的 div 元素,元素中的内容是通过路由挂载来实现的,这时我们就不需要用到 v-cloak 指令了。
2.常见问题解析
(1) v-on可以绑定多个方法吗?
v-on可以绑定多种类型的方法,可以是click事件,可以是focus事件,也可以是change事件,根据业务需求进行选择。但是如果v-on绑定了两个甚至多个click事件,那么v-on只会绑定第一个click事件,其他的会被自动忽略。 <input type=“text” :value=“name” @input=“onInput” @focus=“onFocus” @blur=“onBlur”>
(2) 一个Vue实例可以绑定多个element元素吗?
这个疑问产生的原因是没有理解el的概念。el为实例提供挂载元素,值可以是CSS选择符,或实际的HTML元素,或返回HTML元素的函数。注意,元素只用作挂载点,如果提供了模版,则元素被替换,除非replace为false。元素可以用vm.
e
l
访
问
。
用
在
V
u
e
.
e
x
t
e
n
d
中
必
须
是
函
数
值
,
这
样
所
有
实
例
不
会
共
享
元
素
。
如
果
在
初
始
化
时
指
定
了
这
个
选
项
,
实
例
将
立
即
进
入
编
译
过
程
;
否
则
,
需
要
调
用
v
m
.
el访问。 用在Vue.extend中必须是函数值,这样所有实例不会共享元素。 如果在初始化时指定了这个选项,实例将立即进入编译过程;否则,需要调用vm.
el访问。用在Vue.extend中必须是函数值,这样所有实例不会共享元素。如果在初始化时指定了这个选项,实例将立即进入编译过程;否则,需要调用vm.mount(),手动开始编译。
(3) 在Vue中如何让v-for循环出来的列表里面的click事件只对当前列表内元素有效?
比如模版如下,想点击li控制span的显隐:
<li @click="show">
<span>1</span>
</li>
从数据角度出发,定义好数据结构,然后操作数据:
<body id="example">
<div>
<ul id="app">
<li v-for="item in items" @click="toggle(item)">
<span v-show="item.show">{{ item.content }}<span>
</li>
</ul>
</div>
</body>
<script>
new Vue({
el:'#app',
data: function(){
return{
items:[
{
content: '1 item',
show: true},
{
content:'2 item',
show: true
},
{
content:'3 item',
show: true
}
]
}
},
methods:{
toggle: function(item){
item.show = !item.show
}
}
})
</script>
或者通过$event对象,获取当前事件源,然后操作下面的span元素,方法很多。
|