模板语法
插值
文本
使用进行插值,值的内容在data中设置,双向绑定。
使用v-once
进行一次性插值
1 | <span v-once>这个将不会改变: {{ msg }}</span> |
Attribute(html元素属性)
使用v-bind
设置html元素属性
1 | <div v-bind:id="dynamicId"></div> |
v-bind可以省略,直接使用:id
格式
JavaScript表达式
{{XX}}
模版语法中可以使用js单个表达式,只能访问全局变量白名单,如math、data,不应该尝试访问用户定义的全局变量
指令
带有v-
前缀的特殊attribute
参数
v-bind 绑定Attribute(属性)
1 | <!-- 完整语法 --> |
v-on 绑定事件
1 | <!-- 完整语法 --> |
动态参数
通过中括号括起来的JavaScript表达式作为动态参数
1 | <a v-bind:[attributeName]="url"> ... </a> |
修饰符
以半角句号 .
指明的特殊后缀
1 | <form v-on:submit.prevent="onSubmit">...</form> |
计算属性和侦听器
计算属性
在computed中的方法
基础例子
1 | <div id="example"> |
1 | var vm = new Vue({ |
计算属性缓存vs方法
计算属性有缓存,只有在相关响应式依赖改变时才更新。
用例:有一个比较大开销的属性A,其他计算属性B依赖于A,若用计算属性将其缓存,避免了每次使用B时都要调用A的getter
计算属性vs侦听方法
涉及多个属性时,使用computed代替watch,可以使代码更简洁
1 | // 使用侦听 |
Class与Style绑定
绑定HTML Class
对象语法
1 | <div |
绑定的数据对象可以定义在data、computed中
1 | <div v-bind:class="classObject"></div> |
1 | data: { |
数组语法
可以将一个数组传给v-bind:class
,此时传入的值作为变量从data等属性中寻找
1 | <div v-bind:class="[activeClass, errorClass]"></div> |
也可以用三元表达式
1 | <!--作为js执行--> |
数组语法也可以嵌套对象语法
1 | <div v-bind:class="[{ active: isActive }, errorClass]"></div> |
用于组件
在自定义组件上使用class属性,将绑定到该组件根元素上,且已存在的class不会被覆盖
1 | <!--创建组件--> |
绑定内联样式
对象语法
1 | <!-- 读取对象值 --> |
数组语法
数组语法可以将多个样式对象应用到同一个元素上
1 | <!-- 嵌套对象使用 --> |
自动添加前缀
当 v-bind:style
使用需要添加浏览器引擎前缀的 CSS property 时,如 transform
,Vue.js 会自动侦测并添加相应的前缀。
条件渲染
v-if
因为 v-if
是一个指令,所以必须将它添加到一个元素上。可以把一个 <template>
元素当做不可见的包裹元素,并在上面使用 v-if
。最终的渲染结果将不包含 <template>
元素。
1 | <!-- 读取ok的值决定是否展示该部分内容 --> |
v-else
1 | <div v-if="Math.random() > 0.5">Now you see me</div> |
v-else-if
充当 v-if
的“else-if 块”,可以连续使用:
1 | <div v-if="type === 'A'"> A </div> |
用 key
管理可复用的元素
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。因此为元素增加key属性避免值重复。
1 | <template v-if="loginType === 'username'"> |
若没有设置key属性,那么在上面的代码中切换 loginType
将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input>
不会被替换掉——仅仅是替换了它的 placeholder
。
添加key属性后,每次切换时,输入框都将被重新渲染。
注意,<label>
元素仍然会被高效地复用,因为它们没有添加 key
attribute。
v-show
用法类似v-if
1 | <h1 v-show="ok">Hello!</h1> |
不同的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS property display
。
注意,v-show
不支持 <template>
元素,也不支持 v-else
。
v-if vs v-show
v-if
是“真正”的条件渲染,在切换过程中,对元素/组件销毁重建;
v-if
是“惰性的”,初始条件为假则不会渲染,直到条件为真才开始渲染;
v-show
无论何时都会被渲染,只是基于CSS进行切换;
v-if
切换开销高,v-show
初始渲染开销高。频繁切换使用v-show
,条件很少改变,使用v-if
。
列表渲染
v-for
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名。
1 | <ul id="example-1"> |
v-for
还支持一个可选的第二个参数,即当前项的索引。
1 | <ul id="example-2"> |
也可以用 of
替代 in
作为分隔符,因为它更接近 JavaScript 迭代器的语法:
1 | <div v-for="item of items"></div> |
v-for
使用对象
1 | <!-- 共有三个可用参数,对应object相应的属性值 --> |
在遍历对象时,会按 Object.keys()
的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。
维护状态
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
attribute:
1 | <div v-for="item in items" v-bind:key="item.id"> |
不要使用对象或数组之类的非基本类型值作为 v-for
的 key
。请用字符串或数值类型的值。
数组更新检测
变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
末尾增加新元素pop()
移除最后一个元素shift()
移除第一个元素unshift()
开头增加新元素splice()
移除或者替换已存在的元素和/或添加新元素sort()
排序reverse()
反转元素
替换数组
非变更方法,例如 filter()
、concat()
和 slice()
。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:
1 | example1.items = example1.items.filter(function (item) { |
若使用items渲染列表,Vue 不会丢弃现有DOM并重新渲染整个列表。为了使得DOM元素得到最大范围的重用,Vue 实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。
显示过滤/排序后的结果
想要显示一个经过滤后的数组,而不实际变更或重置原始数据,可以使用计算属性返回过滤后的数组并使用。
1 | <li v-for="n in evenNumbers">{{ n }}</li> |
1 | data: { |
计算属性不适用时,可以使用方法
1 | <ul v-for="set in sets"> |
1 | data: { |
在 v-for
里使用范围值
v-for
也可以接受整数。在这种情况下,它会把模板重复对应次数。
1 | <div> |
在<template>
上使用v-for
类似于 v-if
,你也可以利用带有 v-for
的 <template>
来循环渲染一段包含多个元素的内容。比如:
1 | <ul> |
在组件上使用 v-for
在自定义组件上,你可以像在任何普通元素上一样使用 v-for
。
然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 prop:
1 | <my-component |
不自动将 item
注入到组件里的原因是,这会使得组件与 v-for
的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。
事件处理
监听事件
可以用 v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
1 | <div id="example-1"> |
事件处理方法
当事件逻辑比较复杂时,可以接收一个需要调用的方法名称
1 | <div id="example-2"> |
内联处理器中的方法
可以在内联 JavaScript 语句中调用方法:
1 | <div id="example-3"> |
需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event
把它传入方法:
1 | <button v-on:click="say('hi', $event)"> |
事件修饰符
在事件处理程序中调用 event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
Vue.js 为 v-on
提供了事件修饰符。修饰符是由点开头的指令后缀来表示的。
.stop
.prevent
.capture
.self
.once
.passive
.once
.passive
1 | <!-- 阻止单击事件继续传播 --> |
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self
会阻止所有的点击,而 v-on:click.self.prevent
只会阻止对元素自身的点击。
按键修饰符
Vue 允许为 v-on
在监听键盘事件时添加按键修饰符:
1 | <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` --> |
可以直接将 KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
1 | <input v-on:keyup.page-down="onPageDown"> |
keyCode
的事件用法已经被废弃了并可能不会被最新的浏览器支持。为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
可以通过全局 config.keyCodes
对象自定义按键修饰符别名:
1 | // 可以使用 `v-on:keyup.f1` |
系统修饰键
可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
.ctrl
.alt
.shift
.meta
Win徽标键
1 | <!-- Alt + C --> |
.exact
修饰符
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件。
1 | <!-- 即使 Alt 或 Shift 被一同按下时也会触发 --> |
鼠标按钮修饰符
.left
.right
.middle
表单输入绑定
基础用法
用 v-model
指令在表单 <input>
、<textarea>
及 <select>
元素上创建双向数据绑定。
v-model
会忽略所有表单元素的value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。应通过 JavaScript 在组件的data
选项中声明初始值。
文本
1 | <input v-model="message" placeholder="edit me"> |
多行文本
1 | <textarea v-model="message" placeholder="add multiple lines"></textarea> |
复选框
1 | <!-- 单个复选框 --> |
单选按钮
1 | <div id="example-4"> |
选择框
单选框
1 | <div id="example-5"> |
多选框
1 | <div id="example-6"> |
v-for
动态渲染
1 | <select v-model="selected"> |
值绑定
复选框
对于单选按钮,复选框及选择框的选项,v-model
绑定的值通常是静态字符串 (对于复选框也可以是布尔值):
1 | <!-- 当选中时,`picked` 为字符串 "a" --> |
选择框的选项
1 | <input |
1 | // 当选中时 |
修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 。可以添加 lazy
修饰符,从而转为在 change
事件之后进行同步:
1 | <!-- 在“change”时而非“input”时更新 --> |
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符:
1 | <input v-model.number="age" type="number"> |
这通常很有用,因为即使在 type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()
解析,则会返回原始的值。
.trim
自动过滤用户输入的首尾空白字符
1 | <input v-model.trim="msg"> |
组件基础
基本示例
1 | // 定义一个名为 button-counter 的新组件 |
组件的复用
1 | <div id="components-demo"> |
注意当点击按钮时,每个组件都会各自独立维护它的 count
。因为你每用一次组件,就会有一个它的新实例被创建。
data
必须是一个函数
一个组件的 data
选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
组件的组织
通常一个应用会以一棵嵌套的组件树的形式来组织:
通过Prop向子组件传递数据
Prop 是你可以在组件上注册的一些自定义 attribute,在组件中使用props接收这些自定义属性的值
1 | Vue.component('blog-post', { |
使用时,将数据通过自定义attribute传递到组件中,数据类型可以是字符串、{对象}、[{对象数组}]
1 | <blog-post title="My journey with Vue"></blog-post> |
单个根元素
在组件中如果有多个元素,需要将其包裹在一个根元素中
1 | <div class="blog-post"> |
监听子组件事件
子组件向父组件通信,使用$emit
子组件调用父组件方法
子组件可以通过调用内建的 $emit
方法并传入事件名称来触发一个事件:
1 | <button v-on:click="$emit('enlarge-text')"> |
父组件监听该事件:
1 | <blog-post |
子组件向父组件传值
使用 $emit
的第二个参数来提供这个值:
1 | <button v-on:click="$emit('enlarge-text', 0.1)"> |
父级组件监听这个事件的时候,通过 $event
访问到被抛出的这个值:
1 | <blog-post |
或者,如果这个事件处理函数是一个方法:
1 | <blog-post |
那么这个值将会作为第一个参数传入这个方法:
1 | methods: { |
在组件上使用v-model
自定义事件也可以用于创建支持 v-model
的自定义输入组件。记住:
1 | <input v-model="searchText"> |
等价于:
1 | <input |
当用在组件上时,v-model
则会这样:
1 | <custom-input v-model="searchText"></custom-input> |
此时,子组件custom-input
组件内的 <input>
必须:
- 将其
value
attribute 绑定到一个名叫value
的 prop 上 - 在其
input
事件被触发时,将新的值通过自定义的input
事件抛出
1 | Vue.component('custom-input', { |
通过插槽分发内容
和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:
1 | <alert-box> |
在组件中使用slot
即可接受传递的内容:
1 | Vue.component('alert-box', { |
动态组件
在不同组件间切换(如多标签页面),可以通过 Vue 的 <component>
元素加一个特殊的 is
attribute 来实现:
1 | <!-- 组件会在 `currentTabComponent` 改变时改变 --> |