条件渲染
v-if
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。
<template v-if="type">
<label>Username</label>
<input type="text" placeholder="enter your username">
</template>
<template v-else>
<label>Email</label>
<input type="text" placeholder="enter your email">
</template>
<button @click="toggleType">切换</button>
那么在上面的代码中切换 loginType
将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input>
不会被替换掉——仅仅是替换了它的 placeholder
。
可以通过添加一个具有唯一值的 key
属性,来达到每次切换时,输入框都将被重新渲染
<template v-if="type">
<label>Username</label>
<input type="text" placeholder="enter your username" key="username">
</template>
<template v-else>
<label>Email</label>
<input type="text" placeholder="enter your email" key="email">
</template>
<button @click="toggleType">切换</button>
注意,<label>
元素仍然会被高效地复用,因为它们没有添加 key
属性。
v-show
<template v-show="false">
<p>哈哈哈</p>
</template>
上述内容仍然会被显示出来!注意, v-show
不支持 <template>
语法,也不支持 v-else
。开发中,使用ElementUI进行v-show判断,内容却一直展示,不生效的原因多数是因为此导致!
-
v-if
是“真正的”条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 -
v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说, v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件不太可能改变,则使用 v-if
较好。
列表渲染
数组
<!-- item 是数组元素 -->
<li v-for="item in items"> {{ item.message }} </li>
<!-- index 当前项的索-->
<li v-for="(item, index) in items"> {{ item.message }} </li>
改变原数组的方法,如:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
可以检测变化;不改变原数组的方法,如filter()、concat()、slice()
不会自动变化。
// 用新数组替换旧数组(Vue做了相关处理,非常高效的操作)
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
对于直接修改数组某一项值,或者修改其长度,可以通过以下方式实现:
Vue.set(example1.items, indexOfItem, newValue)
example1.items.splice(newLength)
示例:对象数组中,没有对象属性发生改变,数组列表会自动响应
<ul>
<li v-for="(item, index) in list" :key="item.name">
{{item.name}} - {{item.age}}
</li>
</ul>
<!-- 修改文本框值,list列表自动发生变化 -->
<input type="text" v-model="list[0].name">
完整示例参考地址:https://jsfiddle.net/381510688/wxg4c0th/
对象
<!-- value 是属性值 -->
<li v-for="value in object"> {{ value }} </li>
<!-- key 是属性名 -->
<li v-for="(value, key) in object"> {{ value }} </li>
<!-- index 是索引 -->
<li v-for="(value, key, index) in object"> {{ value }} </li>
Vue 不能检测对象属性的添加或删除。
// 全局方法
Vue.set(vm.someObject, 'b', 2);
// 实例方法
this.$set(this.someObject,'b',2);
使用 Object.assign()
或 _.extend()
方法来添加属性。但是,添加到对象上的新属性不会触发更新。在这种情况下可以创建一个新的对象,让它包含原对象的属性和新的属性(开发中会经常遇到):
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
注意:当 Vue.js 用 v-for
正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。不提供key会发出告警。
当 v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级。
这意味着 v-if
将分别重复运行于每个 v-for
循环中。当你想为仅有的一些项渲染节点时,这种优先级的机制会十分有用,如下:
<!-- 未完成的项目才被罗列出来 -->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
事件处理
事件监听的方式违背了关注点分离(separation of concern)传统理念。但是,使用 v-on
有几个好处:
- 可以轻松定位事件处理函数对应的Javascript方法
- 无须在JavaScript里手动绑定事件,你的ViewModel代码可以是非常纯粹的逻辑,和DOM完全解耦,易于测试
- 当ViewModel被销毁时,所有的事件处理器都会自动被删除
监听事件
<!-- 直接编写javascript代码 -->
<button v-on:click="counter += 1">增加 1</button>
<!-- 接收一个定义的方法来调用 -->
<button v-on:click="greet">Greet</button>
<!-- 内联处理器里的方法 -->
<button v-on:click="warn('Form cannot be submitted yet.', $event)"></button>
注意:访问原生 DOM 事件。可以用特殊变量 $event
把它传入方法。
事件修饰符
在事件处理程序中调用 event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。
如,上述内联处理器方式,可以通过传入的$event进行处理。
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) event.preventDefault()
alert(message)
}
}
这样会导致一个问题,在methods中方法即处理了数据逻辑,同时又处理了DOM相关事宜。为了解决这个问题,Vue.js 为 v-on
提供了 事件修饰符。通过由点(.)表示的指令后缀来调用修饰符。
-
.stop
:阻止单击事件冒泡 -
.prevent
:禁止默认行为 -
.capture
:使用事件捕获模式 -
.self
:只当事件在该元素本身(比如不是子元素)触发时触发回调【不接受冒泡上来的事件】 -
.once
:点击事件将只会触发一次【不像其它只能对原生的 DOM 事件起作用的修饰符,.once
修饰符还能被用到自定义的组件事件上。】
修饰符可以串联使用,但需要注意顺序。
<!-- 不接受冒泡上来的事件 -->
<div id="app" @click.self="clickApp($event)">
<button @click="clickBtn($event)">通过event阻止行为</button>
<!-- 方法处理器,不能使用clickBtn() -->
<a href="htt
target="_blank" @click.prevent.self="clickBtn">
Button<span>阻止所有的点击</span>
</a>
<a href="ht
target="_blank" @click.self.prevent="clickBtn">
Button<span>只会阻止元素上的点击</span>
</a>
</div>
说明:点击Button字样,都会执行响应的click事件但不会跳转。点击第一个a标签内的span无任何反应;点击第二个a标签内的span会跳转到响应地址。所以,使用修饰符时,顺序很重要!
完整参照示例:https://jsfiddle.net/381510688/dLr3vabx/
键值修饰符
<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">
为了便于记忆,Vue为最常用的按键提供了别名。
修饰符
| 说明
|
.enter | 捕获 “回车” 键
|
.tab | 捕获 “Tab” 键
|
.delete | 捕获 “删除” 和 “退格” 键
|
.esc | 捕获 “Esc” 键
|
.space | 捕获 “空格” 键
|
.up | 捕获 “上箭头” 键
|
.down | 捕获 “下箭头” 键
|
.left | 捕获 “左箭头” 键
|
.right | 捕获 “右箭头” 键
|
可以通过全局 config.keyCodes
对象自定义键值修饰符别名
Vue.config.keyCodes = {
v: 86,
f1: 112,
// camelCase 不可用
mediaPlayPause: 179,
// 取而代之的是 kebab-case 且用双引号括起来
"media-play-pause": 179,
up: [38, 87]
}
<input type="text" @keyup.media-play-pause="method">
修饰键
可以用.ctrl
、.alt
、.shift
、.meta
修饰符开启鼠标或键盘事件监听,使在按键按下时发生响应。
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
鼠标按钮修饰符
修饰符.left
、.right
、middle
限制处理程序监听特定的滑鼠按键。