渐进式 JavaScript 框架 Vue 2 备忘清单的快速参考列表,包含常用 API 和示例。
入门
介绍
Vue 是一套用于构建用户界面的渐进式框架
注意:Vue 2.x 版本对应 Vue Router 3.x 路由版本
快速创建 Vue 项目
1
| npx @vue/cli create hello-world
|
参考: Vue CLI 创建一个项目
声明式渲染
1 2 3
| <div id="app"> {{ message }} </div>
|
1 2 3 4 5 6
| var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } })
|
基础例子
1 2 3 4 5 6
| <div id="example"> <p>原始信息: "{{ message }}"</p> <p> 计算的反向信息: "{{ reversedMessage }}" </p> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { reversedMessage: function () { return this.message.split('') .reverse().join('') } } })
|
结果
1 2
| 原始信息: "Hello" 计算的反向信息: "olleH"
|
绑定元素属性
1 2 3 4 5
| <div id="app-2"> <span v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定的提示信息! </span> </div>
|
1 2 3 4 5 6 7
| var app2 = new Vue({ el: '#app-2', data: { message: '页面加载于 ' + new Date() .toLocaleString() } })
|
条件
1 2 3
| <div id="app-3"> <p v-if="seen">现在你看到我了</p> </div>
|
1 2 3 4 5 6
| var app3 = new Vue({ el: '#app-3', data: { seen: true } })
|
控制切换一个元素是否显示
循环
1 2 3 4 5 6 7
| <div id="app-4"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div>
|
1 2 3 4 5 6 7 8 9 10
| var app4 = new Vue({ el: '#app-4', data: { todos: [ { text: '学习 JavaScript' }, { text: '学习 Vue' }, { text: '整个牛项目' } ] } })
|
点击事件处理
1 2 3 4 5 6
| <div id="app-5"> <p>{{ message }}</p> <button v-on:click="reverseMessage"> 反转消息 </button> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12
| var app5 = new Vue({ el: '#app-5', data: { message: 'Hello Vue.js!' }, methods: { reverseMessage: function () { this.message = this.message.split('') .reverse().join('') } } })
|
输入事件处理
1 2 3 4
| <div id="app-6"> <p>{{ message }}</p> <input v-model="message"> </div>
|
v-model
指令,它能轻松实现表单输入和应用状态之间的双向绑定
1 2 3 4 5 6
| var app6 = new Vue({ el: '#app-6', data: { message: 'Hello Vue!' } })
|
模板语法
文本
1 2 3 4
| <span>Message: {{ msg }}</span> <span v-once> 这个将不会改变: {{ msg }} </span>
|
使用 v-once
指令,执行一次性地插值,当数据改变时,插值处的内容不会更新
原始 HTML
1 2 3 4 5
| <p>解释为普通文本: {{ rawHtml }}</p> <p> 使用 v-html 指令: <span v-html="rawHtml"></span> </p>
|
使用 v-html
指令,输出真正的 HTML
属性
1 2 3 4
| <div v-bind:id="dynamicId"></div> <button v-bind:disabled="isDisabled"> Button </button>
|
如果 isDisabled
的值是 null/undefined/false 则 disabled
不会被渲染出来
JavaScript 表达式
1 2 3 4 5 6 7
| <div id="app"> <span>消息: {{ msg }}</span> <span>{{ msg + '这是字符串' }}</span> <span>{{ isWorking ? '是':'否' }}</span> <span>{{ msg.getDetials() }}</span> <div v-bind:id="'list-' + id"></div> <div>
|
指令
1 2 3
| <p v-if="seen"> 现在你看到我了 </p>
|
v-if
指令将根据表达式 seen
的值的真假来插入/移除 <p> 元素
指令参数
1
| <a v-bind:href="url">...</a>
|
v-bind
指令将该元素 href
属性与表达式 url
的值绑定
1
| <a v-on:click="doSomething">...</a>
|
v-on
指令,用于监听 DOM 事件,oSomething 是事件名
指令动态参数 v2.6
1
| <a v-on:[eventName]="doSomething">...</a>
|
当 eventName
的值为 focus
时,v-on:[eventName]
将等价于 v-on:focus
指令修饰符
1 2 3
| <form v-on:submit.prevent="onSubmit"> ... </form>
|
.prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
指令缩写
1 2 3 4 5 6
| <a v-bind:href="url">...</a>
<a :href="url">...</a>
<a :[key]="url"> ... </a>
|
Class 与 Style 绑定
对象语法
1 2 3
| <div v-bind:class="{ active: isActive }">
</div>
|
传给 v-bind:class
一个对象,以动态地切换 class
与普通的 class 属性共存
{2}1 2 3 4 5 6 7
| <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }" ></div>
|
如下 data
1 2 3 4
| data: { isActive: true, hasError: false }
|
结果渲染为
1
| <div class="static active"></div>
|
绑定的数据对象不必内联定义在模板里
1
| <div v-bind:class="classObject"></div>
|
如下 data
1 2 3 4 5 6
| data: { classObject: { active: true, 'text-danger': false } }
|
结果渲染为
1
| <div class="static active"></div>
|
三元表达式
1 2 3 4
| <div v-bind:class="[ isActive ? activeClass : '' ]"> </div>
|
数组
1 2 3
| <div v-bind:class="[ { active: isActive }, errorClass ]"></div>
|
数组语法
1 2 3 4
| <div v-bind:class="[ activeClass, errorClass ]"> </div>
|
如下 data
1 2 3 4
| data: { activeClass: 'active', errorClass: 'text-danger' }
|
结果渲染为
1
| <div class="active text-danger"></div>
|
内联样式
1 2 3 4
| <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
|
如下 data
1 2 3 4
| data: { activeColor: 'red', fontSize: 30 }
|
结果渲染为
1
| <div style="color: red; font-size: 30px;"></div>
|
内联样式对象通常更好
1
| <div v-bind:style="styleObject"></div>
|
如下 data
1 2 3 4 5 6
| data: { styleObject: { color: 'red', fontSize: '13px' } }
|
同样的,对象语法常常结合返回对象的计算属性使用
内联样式数组语法
1 2 3
| <div v-bind:style="[ baseStyles, overridingStyles ]"></div>
|
内联样式多重值
1 2 3
| <div :style="{ display: ['-webkit-box', 'flex'] }"></div>
|
条件渲染
v-if
1 2
| <h1 v-if="awesome">Vue is awesome!</h1> <h1 v-else>Oh no 😢</h1>
|
v-else-if
1 2 3 4 5 6
| <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>
|
@2.1.0
新增,必须紧跟在带 v-if
或者 v-else-if
的元素之后
v-else
1 2 3 4 5 6
| <div v-if="Math.random() > 0.5"> 现在你看到我了 </div> <div v-else> 现在你看不见我了 </div>
|
v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面
<template> 上使用 v-if 条件渲染分组
1 2 3
| <template v-if="ok"> <p>Paragraph 1</p> </template>
|
用 key 管理可复用的元素
1 2 3 4 5 6 7 8
| <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="输入用户名" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="输入邮箱" key="email-input"> </template>
|
v-show
1 2 3
| <h1 v-show="ok"> Hello! </h1>
|
带有 v-show
的元素始终会被渲染并保留在 DOM 中,只是简单地切换元素的 CSS
属性 display
列表渲染
v-for
{3}1 2 3 4 5 6 7
| <ul id="example-1"> <li v-for="item in items" :key="item.message"> {{ item.message }} </li> </ul>
|
1 2 3 4 5 6 7 8 9
| var example1 = new Vue({ el: '#example-1', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } })
|
v-for 可选的第二个参数(索引)
{2}1 2 3 4
| <li v-for="(item, index) in items"> {{ index }} {{ item.message }} </li>
|
如下 data
1 2 3 4 5 6
| data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] }
|
也可以用 of
替代 in
作为分隔符
1
| <div v-for="item of items"></div>
|
v-for 使用对象
1 2 3
| <li v-for="value in object"> {{ value }} </li>
|
如下 data
1 2 3 4 5 6 7
| data: { object: { title: 'How to do lists in Vue', author: 'Jane Doe', publishedAt: '2016-04-10' } }
|
渲染结果
1 2 3
| How to do lists in Vue Jane Doe 2016-04-10
|
提供第二个的参数为 property 名称 (也就是键名)
1 2 3
| <div v-for="(value, name) in object"> {{ name }}: {{ value }} </div>
|
还可以用第三个参数作为索引
1 2 3
| <div v-for="(value,name,index) in object"> {{ index }}. {{ name }}: {{ value }} </div>
|
v-for/v-if
{2,3}1 2 3 4 5 6
| <li v-for="todo in todos" v-if="!todo.isComplete" > {{ todo }} </li>
|
只渲染未完成的 todo,下面加上 v-else
示例
1 2 3 4 5 6
| <ul v-if="todos.length"> <li v-for="todo in todos"> {{ todo }} </li> </ul> <p v-else>No todos left!</p>
|
注意: v-for
和 v-if
不推荐一起使用参考官方文档
组件上使用 v-for
1 2 3 4 5 6
| <my-component v-for="(item, index) in items" v-bind:item="item" v-bind:index="index" v-bind:key="item.id" ></my-component>
|
2.2.0+
的版本里,当在组件上使用 v-for
时,key
现在是必须的
事件处理
监听事件
{2}1 2 3 4 5 6
| <div id="example-1"> <button v-on:click="counter += 1"> +1 </button> <p>按钮已被点击 {{ counter }} 次。</p> </div>
|
1 2 3 4 5 6
| var example1 = new Vue({ el: '#example-1', data: { counter: 0 } })
|
事件处理方法
{3}1 2 3 4 5 6
| <div id="example-2"> <button v-on:click="greet"> 你好 </button> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var example2 = new Vue({ el: '#example-2', data: { name: 'Vue.js' }, methods: { greet: function (event) { alert('Hello ' + this.name + '!') if (event) { alert(event.target.tagName) } } } })
|
也可以用 JavaScript 直接调用方法
内联处理器中的方法
{2,5}1 2 3 4 5 6 7 8
| <div id="example-3"> <button v-on:click="say('hi')"> 弹出 hi </button> <button v-on:click="say('what')"> 弹出 what </button> </div>
|
{4}1 2 3 4 5 6 7 8
| new Vue({ el: '#example-3', methods: { say: function (message) { alert(message) } } })
|
访问原始的 DOM 事件,用特殊变量 $event
1 2 3
| <button v-on:click="say('what', $event)"> 提交 </button>
|
1 2 3 4 5 6 7 8 9
| methods: { say: function (message, event) { if (event) { event.preventDefault() } alert(message) } }
|
事件修饰符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <a v-on:click.stop="doThis"></a>
<form v-on:submit.prevent="submit"></form>
<a v-on:click.stop.prevent="doThat"></a>
<form v-on:submit.prevent></form>
<div v-on:click.capture="doThis">...</div>
<div v-on:click.self="doThat">...</div>
<a v-on:click.once="doThis"></a>
|
事件修饰符 passive
1 2 3 4 5 6
|
<p v-on:scroll.passive="onScroll"> ... </p>
|
这个 .passive
修饰符尤其能够提升移动端的性能。
按键修饰符
1 2 3 4 5 6 7 8
| <input v-on:keyup.enter="submit">
<input v-on:keyup.page-down="onPageDown">
<input v-on:keyup.alt.67="clear">
<div v-on:click.ctrl="doSomething">
|
.exact 修饰符
1 2 3 4 5 6
| <button v-on:click.ctrl="onClick">
<button v-on:click.ctrl.exact="ctrlClick">
<button v-on:click.exact="onClick">
|
计算属性和侦听器
基础例子
1 2 3 4 5 6
| <div id="example"> <p>Original message: "{{ message }}"</p> <p> 计算的反向消息: "{{ reversedMessage }}" </p> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { reversedMessage: function () { return this.message.split('') .reverse().join('') } } })
|
计算属性缓存 vs 方法
1 2 3
| <p> 计算的反向消息:"{{ reversedMessage() }}" </p>
|
在组件中,我们可以将同一函数定义为一个方法而不是一个计算属性
1 2 3 4 5 6
| methods: { reversedMessage: function () { return this.message.split('') .reverse().join('') } }
|
两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。
计算属性 vs 侦听属性
1
| <div id="demo">{{ fullName }}</div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } } })
|
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
1 2 3 4 5 6 7 8 9 10 11 12 13
| var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { return this.firstName + ' ' + this.lastName } } })
|
计算属性的 setter
1 2 3 4 5 6 7 8 9 10 11 12
| computed: { fullName: { get: function () { return this.firstName + ' ' + this.lastName }, set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } }
|
表单输入绑定
文本
1 2
| <input v-model="msg" placeholder="编辑我"> <p>msg is: {{ msg }}</p>
|
多行文本
{3}1 2 3 4 5
| <span>Multiline message is:</span> <textarea v-model="message" placeholder="添加多行"></textarea> <p>{{ message }}</p>
|
复选框
{4}1 2 3 4 5 6
| <input type="checkbox" id="checkbox" v-model="checked" > <label for="checkbox">{{ checked}}</label>
|
多个复选框
1 2 3 4 5 6 7 8
| <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> <br> <span>Checked names: {{ checkedNames }}</span>
|
如下 data
1 2 3 4 5 6
| new Vue({ el: '...', data: { checkedNames: [] } })
|
单选按钮
1 2 3 4 5 6 7 8 9 10
| <div id="example-4"> <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <br> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <div>Picked: {{ picked }}</div> </div>
|
1 2 3 4 5 6
| new Vue({ el: '#example-4', data: { picked: '' } })
|
选择框
1 2 3 4 5 6 7
| <select v-model="selected"> <option disabled value="">请选择</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span>
|
1 2 3 4 5 6
| new Vue({ el: '...', data: { selected: '' } })
|
选择框(数组)
1 2 3 4 5 6
| <select v-model="selected" multiple> <option>A</option> <option>B</option> <option>C</option> </select> <div>Selected: {{ selected }}</div>
|
1 2 3 4 5 6
| new Vue({ el: '...', data: { selected: [] } })
|
v-for 渲染的动态选项
{3-4}1 2 3 4 5 6 7 8 9
| <select v-model="selected"> <option v-for="option in options" v-bind:value="option.value" > {{ option.text }} </option> </select> <span>Selected: {{ selected }}</span>
|
{6-8}1 2 3 4 5 6 7 8 9 10 11
| new Vue({ el: '...', data: { selected: 'A', options: [ { text: 'One', value: 'A' }, { text: 'Two', value: 'B' }, { text: 'Three', value: 'C' } ] } })
|
值绑定
1 2 3 4 5 6 7 8 9
| <input type="radio" v-model="pc" value="a">
<input type="checkbox" v-model="toggle">
<select v-model="selected"> <option value="abc">ABC</option> </select>
|
单选按钮
1 2 3 4
| <input type="radio" v-model="pick" v-bind:value="a">
|
当选中时
复选框
{3}1 2 3 4 5 6
| <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" >
|
1 2 3 4
| vm.toggle === 'yes'
vm.toggle === 'no'
|
选择框的选项
1 2 3 4 5 6
| <select v-model="selected"> <option v-bind:value="{ number: 123 }"> 123 </option> </select>
|
当选中时
1 2
| typeof vm.selected vm.selected.number
|
修饰符
1 2 3 4 5 6 7 8
| <input v-model.lazy="msg">
<input v-model.number="age" type="number">
<input v-model.trim="msg">
|
组件基础
单文件组件
基本示例
1 2 3 4 5 6 7 8 9 10 11 12
| Vue.component('button-counter', { data: function () { return { count: 0 } }, template: ` <button v-on:click="count++"> 你点击了我 {{ count }} 次 </button> ` })
|
组件是可复用的 Vue
实例
1 2 3
| <div id="components-demo"> <button-counter></button-counter> </div>
|
1 2 3
| new Vue({ el: '#components-demo' })
|
组件的复用
1 2 3 4 5
| <div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div>
|
单个根元素
{4}1 2 3 4 5 6 7 8 9
| Vue.component('blog-post', { props: ['post'], template: ` <div class="blog-post"> <h3>{{ post.title }}</h3> <div v-html="post.content"></div> </div> ` })
|
1 2 3 4 5 6
| <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" > </blog-post>
|
向子组件传递数据
1 2 3 4
| Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' })
|
当值传递给一个 prop
attribute
的时候,变成了组件实例的一个 property
1 2
| <blog-post title="写博客"></blog-post> <blog-post title="如此有趣"></blog-post>
|
data
必须是一个函数
1 2 3 4 5
| data: function () { return { count: 0 } }
|
组件的 data
选项必须是一个函数
监听子组件事件
{7}1 2 3 4 5 6 7 8 9 10 11 12 13
| Vue.component('blog-post', { props: ['post'], template: ` <div class="blog-post"> <h3>{{ post.title }}</h3> <button v-on:click="$emit('enlarge-txt')" >放大文字 </button> <div v-html="post.content"></div> </div> ` })
|
{3}1 2 3 4
| <blog-post ... v-on:enlarge-text="postFontSize += 0.1" ></blog-post>
|
可以使用 $emit
的第二个参数来提供这个值
{2}1 2 3 4 5
| <button v-on:click="$emit('enlarge-text', 0.1)" > Enlarge text </button>
|
通过 $event
访问到被抛出的这个值
{3}1 2 3 4
| <blog-post ... v-on:enlarge-text="postFontSize += $event" ></blog-post>
|
如果这个事件处理函数是一个方法
{3}1 2 3 4
| <blog-post ... v-on:enlarge-text="onEnlargeText" ></blog-post>
|
那么这个值将会作为第一个参数传入这个方法
1 2 3 4 5
| methods: { onEnlargeText: function(enlargeAmount) { this.postFontSize += enlargeAmount } }
|
在组件上使用 v-model
自定义事件也可以用于创建支持 v-model
的自定义输入组件。
1
| <input v-model="searchText">
|
等价于
1 2 3 4
| <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" >
|
当用在组件上时,v-model 则会这样:
1 2 3 4
| <custom-input v-bind:value="searchText" v-on:input="searchText = $event" ></custom-input>
|
为了让它正常工作,这个组件内的 <input> 必须:
- 将其
value
attribute 绑定到一个名叫 value
的 prop
上
- 在其
input
事件被触发时,将新的值通过自定义的 input
事件抛出
1 2 3 4 5 6 7 8 9
| Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` })
|
现在 v-model
就应该可以在这个组件上完美地工作起来了
{2}1 2 3 4
| <custom-input v-model="searchText" > </custom-input>
|
通过插槽分发内容
1 2 3
| <alert-box> 发生了不好的事情。 </alert-box>
|
{5}1 2 3 4 5 6 7 8
| Vue.component('alert-box', { template: ` <div class="demo-alert-box"> <strong>Error!</strong> <slot></slot> </div> ` })
|
动态组件示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <div id="dynamic-component-demo" class="demo"> <button v-for="tab in tabs" v-bind:key="tab" v-bind:class="['tab-button', { active: currentTab === tab }]" v-on:click="currentTab = tab" > {{ tab }} </button> <component v-bind:is="currentTabComponent" class="tab"></component> </div>
<script> Vue.component("tab-home", { template: "<div>Home component</div>" }); Vue.component("tab-posts", { template: "<div>Posts component</div>" }); Vue.component("tab-archive", { template: "<div>Archive component</div>" }); new Vue({ el: "#dynamic-component-demo", data: { currentTab: "Home", tabs: ["Home", "Posts", "Archive"] }, computed: { currentTabComponent: function() { return "tab-" + this.currentTab.toLowerCase(); } } }); </script>
|
解析 DOM 模板时的注意事项
有些 HTML 元素,诸如 <ul>
、<ol>
、<table>
和 <select>
,对于哪些元素可以出现在其内部是有严格限制的。有些元素,诸如 <li>
、<tr>
和 <option>
,只能出现在其它某些特定的元素内部
1 2 3
| <table> <blog-post-row></blog-post-row> </table>
|
<blog-post-row>
会被作为无效的内容提升到外部
如果我们从以下来源使用模板的话,这条限制是不存在的
- 字符串 (例如:
template: '...'
)
- 单文件组件 (
.vue
)
<script type="text/x-template">
过渡 & 动画
单元素/组件的过渡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <template> <button v-on:click="show = !show"> 切换 </button> <transition name="fade"> <p v-if="show">切换内容</p> </transition> </template>
<script> export default { data: function() { return { show: true }; } }; </script>
<style scoped> .fade-enter-active, .fade-leave-active { transition: opacity .5s; } .fade-enter, .fade-leave-to { opacity: 0; } </style>
|
CSS 过渡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <template> <button @click="show = !show"> 切换渲染 </button> <transition name="slide-fade"> <p v-if="show">切换内容</p> </transition> </template> <script> export default { data: function() { return { show: true }; } }; </script> <style scoped> .slide-fade-enter-active { transition: all .3s ease; } .slide-fade-leave-active { transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0); } .slide-fade-enter, .slide-fade-leave-to { transform: translateX(10px); opacity: 0; } </style>
|
CSS 动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <template> <button @click="show = !show">切换展示</button> <transition name="bounce"> <p v-if="show">切换内容</p> </transition> </template> <script> export default { data: function() { return { show: true }; } }; </script> <style scoped> .bounce-enter-active { animation: bounce-in .5s; } .bounce-leave-active { animation: bounce-in .5s reverse; } @keyframes bounce-in { 0% { transform: scale(0); } 50% { transform: scale(1.5); } 100% { transform: scale(1); } } </style>
|
过渡的类名
:- |
:- |
v-enter |
定义进入过渡的开始状态 # |
v-enter-active |
定义进入过渡生效时的状态 # |
v-enter-to (2.1.8) |
定义进入过渡的结束状态 # |
v-leave |
定义离开过渡的开始状态 # |
v-leave-active |
定义离开过渡生效时的状态 # |
v-leave-to (2.1.8) |
定义离开过渡的结束状态 # |
如果你使用了 <transition name="my-tran">
,那么 v-enter
会替换为 my-tran-enter
。
自定义过渡的类名
:- |
:- |
enter-class |
# |
enter-active-class |
# |
enter-to-class (2.1.8+) |
# |
leave-class |
# |
leave-active-class |
# |
leave-to-class (2.1.8+) |
# |
1 2 3 4 5 6 7
| <transition name="custom-classes-transition" enter-active-class="animated tada" leave-active-class="animated bounceOutRight" > <p v-if="show">hello</p> </transition>
|
显性的过渡持续时间
<transition>
组件上的 duration
prop 定制一个显性的过渡持续时间 (以毫秒计):
1 2 3
| <transition :duration="1000"> ... </transition>
|
你也可以定制进入和移出的持续时间:
1 2 3 4 5 6
| <transition :duration="{ enter: 500, leave: 800 }"> ... </transition>
|
初始渲染的过渡
可以通过 appear
attribute 设置节点在初始渲染的过渡
1 2 3
| <transition appear> </transition>
|
这里默认和进入/离开过渡一样,同样也可以自定义 CSS 类名
1 2 3 4 5 6 7 8
| <transition appear appear-class="custom-appear-class" appear-to-class="custom-appear-to-class" appear-active-class="custom-appear-active-class" > </transition>
|
自定义 JavaScript 钩子:
1 2 3 4 5 6 7 8 9
| <transition appear v-on:before-appear="customBeforeAppearHook" v-on:appear="customAppearHook" v-on:after-appear="customAfterAppearHook" v-on:appear-cancelled="customAppearCancelledHook" > </transition>
|
无论是 appear
attribute 还是 v-on:appear
钩子都会生成初始渲染过渡
JavaScript 钩子
1 2 3 4 5 6 7 8 9 10 11 12 13
| <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter" v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave" v-on:leave="leave" v-on:after-leave="afterLeave" v-on:leave-cancelled="leaveCancelled" > </transition>
|
钩子函数可以结合 CSS transitions
/animations
使用,也可以单独使用
列表的进入/离开过渡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <template> <button v-on:click="add">添加</button> <button v-on:click="remove">删除</button> <transition-group name="list" tag="p"> <span v-for="item in items" v-bind:key="item" class="list-item"> {{ item }} </span> </transition-group> </template> <script> export default { data: function() { return { items: [1,2,3,4,5,6,7,8,9], nextNum: 10 }; }, methods: { randomIndex: function () { return Math.floor(Math.random() * this.items.length) }, add: function () { this.items.splice(this.randomIndex(), 0, this.nextNum++) }, remove: function () { this.items.splice(this.randomIndex(), 1) }, } }; </script> <style scoped> .list-item { display: inline-block; margin-right: 10px; } .list-enter-active, .list-leave-active { transition: all 1s; } .list-enter, .list-leave-to { opacity: 0; transform: translateY(30px); } </style>
|
Vue 2 API 参考
全局配置
:- |
:- |
silent |
取消所有的日志与警告 # |
optionMergeStrategies |
自定义合并策略的选项 # |
devtools |
是否允许 devtools 检查 # |
errorHandler |
未捕获错误的处理函数 (开发模式生效) # |
warnHandler (2.4.0) |
运行时警告处理函数 # |
ignoredElements |
忽略 Vue 之外的 (自定义元素) # |
keyCodes |
v-on 自定义键位别名 # |
performance (2.2.0) |
性能追踪 # |
productionTip (2.2.0) |
是否生成生产提示 # |
全局 API
:- |
:- |
Vue.extend |
Vue 构造器,创建一个“子类” # |
Vue.nextTick |
执行延迟回调 # |
Vue.set |
向响应式对象中添加一个属性 # |
Vue.delete |
删除对象的 property # |
Vue.directive |
注册或获取全局指令 # |
Vue.filter |
注册或获取全局过滤器 # |
Vue.component |
注册或获取全局组件 # |
Vue.use |
安装 Vue.js 插件 # |
Vue.mixin |
全局注册一个混入 # |
Vue.compile |
将模板字符串编译成 render 函数 # |
Vue.observable (2.6.0) |
让一个对象可响应 # |
Vue.version |
Vue 安装版本号 # |
数据
:- |
:- |
data |
实例的数据对象 # |
props |
接收来自父组件的数据 # |
propsData |
创建实例时传递 props # |
computed |
计算属性将被混入到 Vue 实例中 # |
methods |
将被混入到 Vue 实例中 # |
watch |
对象键是观察的表达式,值是回调函数 # |
DOM
:- |
:- |
el |
实例的挂载目标 # |
template |
字符串模板作为 Vue 实例的标识使用 # |
render |
字符串模板的代替方案 # |
renderError (2.2.0) |
render 错误时提供另一种渲染 # |
生命周期钩子
:- |
:- |
beforeCreate |
实例初始化之后 # |
created |
实例创建完成后被立即同步调用 # |
beforeMount |
在挂载开始之前被调用 # |
mounted |
实例被挂载后调用 # |
beforeUpdate |
数据改变后 DOM 更新之前调用 # |
updated |
数据更改更新完毕之后被调用 # |
activated |
keep-alive 缓存组件激活时调用 # |
deactivated |
keep-alive 缓存的组件失活时调用 # |
beforeDestroy |
实例销毁之前调用 # |
destroyed |
实例销毁后调用 # |
errorCaptured (2.5.0) |
来自后代组件的错误时被调用 # |
资源
:- |
:- |
directives |
包含 Vue 实例可用指令的哈希表 # |
filters |
包含 Vue 实例可用过滤器的哈希表 # |
components |
包含 Vue 实例可用组件的哈希表 # |
组合
:- |
:- |
parent |
指定已创建的实例之父实例 # |
mixins |
接收一个混入对象的数组 # |
extends |
声明扩展另一个组件 # |
provide/inject (2.2.0) |
祖组件向所有子孙后代注入依赖 # |
其它
:- |
:- |
name |
允许组件模板递归地调用自身 # |
delimiters |
改变纯文本插入分隔符 # |
functional |
使组件无状态和无实例 # |
model (2.2.0) |
使用 v-model 时定制 prop 和 event # |
inheritAttrs (2.4.0) |
# |
comments (2.4.0) |
是否保留模板中的HTML 注释 # |
实例方法 / 数据
:- |
:- |
vm.$watch |
观察 Vue 实例上的一个表达式 或者一个函数计算结果的变化 # |
vm.$set |
全局 Vue.set 的别名 # |
vm.$delete |
全局 Vue.delete 的别名 # |
实例 property
:- |
:- |
vm.$data |
观察的数据对象 # |
vm.$props (2.2.0) |
组件接收的 props 对象 # |
vm.$el |
实例使用的根 DOM 元素 # |
vm.$options |
实例的初始化选项 # |
vm.$parent |
父实例 # |
vm.$root |
当前组件树的根实例 # |
vm.$children |
当前实例的直接子组件 # |
vm.$slots |
访问被插槽分发的内容 # |
vm.$scopedSlots (2.1.0) |
访问作用域插槽 # |
vm.$refs |
DOM 元素和组件实例 # |
vm.$isServer |
是否运行于服务器 # |
vm.$attrs (2.4.0) |
包含父作用域中不作为 prop 被识别的属性绑定 ( # |
vm.$listeners (2.4.0) |
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器 # |
实例方法 / 事件
:- |
:- |
vm.$on |
监听当前实例上的自定义事件 # |
vm.$once |
监听一个自定义事件,只触发一次 # |
vm.$off |
移除自定义事件监听器 # |
vm.$emit |
触发当前实例上的事 # |
实例方法 / 生命周期
:- |
:- |
vm.$mount |
手动地挂载一个未挂载的实例 # |
vm.$forceUpdate |
迫使 Vue 实例重新渲染 # |
vm.$nextTick |
回调延迟执行 # |
vm.$destroy |
完全销毁一个实例 # |
指令
:- |
:- |
v-text |
更新元素的 textContent # |
v-html |
更新元素的 innerHTML # |
v-show |
切换元素的 display css 属性 # |
v-if |
有条件地渲染元素 # |
v-else |
# |
v-else-if (2.1.0) |
# |
v-for |
多次渲染元素或模板块 # |
v-on |
绑定事件监听器 # |
v-bind |
动态地绑定一个或多个属性 # |
v-model |
创建双向绑定 # |
v-slot |
提供插槽或接收 prop 的插槽 # |
v-pre |
跳过元素和它的子元素编译过程 # |
v-cloak |
保持在元素上直到实例结束编译 # |
v-once |
只渲染元素和组件一次 # |
特殊 attribute
:- |
:- |
key |
用在 Vue 的虚拟 DOM 算法 # |
ref |
元素或子组件注册引用信息 # |
is |
限制是否更新 # |
slot |
推荐 2.6.0 新增的 v-slot # |
slot-scope |
推荐 2.6.0 新增的 v-slot # |
scope |
2.5.0 新增的 slot-scope 取代 # |
内置的组件
:- |
:- |
<component> |
渲染一个元组件 为动态组件 # |
<transition> |
单个元素/组件的过渡效果 # |
<transition-group> |
多个元素/组件的过渡效果 # |
<keep-alive> |
不活动的实例缓存不销毁 # |
<slot> |
组件模板中的内容分发插槽 # |
v-on (事件)修饰符
:- |
:- |
v-on:click.stop # |
调用 event.stopPropagation()。 |
v-on:click.prevent # |
调用 event.preventDefault()。 |
v-on:click.capture # |
添加事件侦听器时使用 capture 模式。 |
v-on:click.self # |
只当事件是从侦听器绑定的元素本身触发时才触发回调。 |
v-on:click.{keyCode|keyAlias} # |
只当事件是从特定键触发时才触发回调。 |
v-on:click.native # |
监听组件根元素的原生事件。 |
v-on:click.once # |
只触发一次回调。 |
v-on:click.passive (2.3.0) # |
以 { passive: true } 模式添加侦听器 |
v-on (鼠标)修饰符
:- |
:- |
v-on:click.left # |
只当点击鼠标左键时触发 |
v-on:click.right # |
只当点击鼠标右键时触发 |
v-on:click.middle # |
只当点击鼠标中键时触发 |
在 (2.2.0) 中新增
系统修饰键
:- |
:- |
v-on:keyup.ctrl (2.1.0) |
# |
v-on:keyup.alt (2.1.0) |
# |
v-on:keyup.shift (2.1.0) |
# |
v-on:keyup.meta (2.1.0) |
# |
Keyboard 按键修饰符
:- |
:- |
v-on:keyup.enter |
# |
v-on:keyup.tab |
# |
v-on:keyup.delete |
捕获“删除”和“退格”键 # |
v-on:keyup.esc |
# |
v-on:keyup.space |
# |
v-on:keyup.up |
# |
v-on:keyup.down |
# |
v-on:keyup.left |
# |
v-on:keyup.right |
# |
v-bind 修饰符
:- |
:- |
v-bind.prop # |
作为一个 DOM property 绑定而不是作为 attribute 绑定。(差别在哪里?) |
v-bind.camel (2.1.0+) # |
将 kebab-case attribute 名转换为 camelCase。 |
v-bind.sync (2.3.0+) # |
语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。 |
另见