[TOC]
Vue2 备忘清单
渐进式 JavaScript 框架 Vue 2 备忘清单的快速参考列表,包含常用 API 和示例。
入门
介绍
Vue 是一套用于构建用户界面的渐进式框架
注意:Vue 2.x 版本对应 Vue Router 3.x 路由版本
快速创建 Vue 项目 (Vue CLI)
npx @vue/cli create hello-world
声明式渲染
<div id="app">
{{ message }}
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
基础例子
<div id="example">
<p>原始信息: "{{ message }}"</p>
<p>
计算的反向信息: "{{ reversedMessage }}"
</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('')
.reverse().join('')
}
}
})
结果
原始信息: "Hello"
计算的反向信息: "olleH"
绑定元素属性
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date()
.toLocaleString()
}
})
条件
<div id="app-3">
<p v-if="seen">现在你看到我了</p>
</div>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
控制切换一个元素是否显示
循环
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
var app4 = new Vue({
el: '#app-4',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛项目' }
]
}
})
点击事件处理
<div id="app-5">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">
反转消息
</button>
</div>
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('')
.reverse().join('')
}
}
})
输入事件处理
<div id="app-6">
<p>{{ message }}</p>
<input v-model="message">
</div>
v-model
指令,它能轻松实现表单输入和应用状态之间的双向绑定
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
模板语法
文本
<span>Message: {{ msg }}</span>
<span v-once>
这个将不会改变: {{ msg }}
</span>
使用 v-once
指令,执行一次性地插值,当数据改变时,插值处的内容不会更新
原始 HTML
<p>解释为普通文本: {{ rawHtml }}</p>
<p>
使用 v-html 指令:
<span v-html="rawHtml"></span>
</p>
使用 v-html
指令,输出真正的 HTML
属性
<div v-bind:id="dynamicId"></div>
<button v-bind:disabled="isDisabled">
Button
</button>
如果 isDisabled
的值是 null/undefined/false 则 disabled
不会被渲染出来
JavaScript 表达式
<div id="app">
<span>消息: {{ msg }}</span>
<span>{{ msg + '这是字符串' }}</span>
<span>{{ isWorking ? '是':'否' }}</span>
<span>{{ msg.getDetials() }}</span>
<div v-bind:id="'list-' + id"></div>
<div>
指令
<p v-if="seen">
现在你看到我了
</p>
v-if
指令将根据表达式 seen
的值的真假来插入/移除 \
元素
指令参数
<a v-bind:href="url">...</a>
v-bind
指令将该元素 href
属性与表达式 url
的值绑定
<a v-on:click="doSomething">...</a>
v-on
指令,用于监听 DOM 事件,oSomething 是事件名
指令动态参数 v2.6
<a v-on:[eventName]="doSomething">...</a>
当 eventName
的值为 focus
时,v-on:[eventName]
将等价于 v-on:focus
指令修饰符
<form v-on:submit.prevent="onSubmit">
...
</form>
.prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
指令缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>
Class 与 Style 绑定
对象语法
<div v-bind:class="{ active: isActive }">
</div>
传给 v-bind:class
一个对象,以动态地切换 class
与普通的 class 属性共存
```html {2}
如下 data
js
data: {
isActive: true,
hasError: false
}
结果渲染为
html
### 绑定的数据对象不必内联定义在模板里
<!--rehype:wrap-class=row-span-3-->
html
如下 data
js
data: {
classObject: {
active: true,
‘text-danger’: false
}
}
结果渲染为
html
### 三元表达式
html
### 数组
html
### 数组语法
html
如下 data
js
data: {
activeClass: ‘active’,
errorClass: ‘text-danger’
}
结果渲染为
html
### 内联样式
html
如下 data
js
data: {
activeColor: ‘red’,
fontSize: 30
}
结果渲染为
html
### 内联样式对象通常更好
html
如下 data
js
data: {
styleObject: {
color: ‘red’,
fontSize: ‘13px’
}
}
同样的,对象语法常常结合返回对象的计算属性使用
### 内联样式数组语法
html
### 内联样式多重值
html
条件渲染
---
### v-if
html
Vue is awesome!
Oh no 😢
### v-else-if
<!--rehype:wrap-class=row-span-2-->
html
A
B
C
Not A/B/C
`@2.1.0` 新增,必须紧跟在带 `v-if` 或者 `v-else-if` 的元素之后
### v-else
<!--rehype:wrap-class=row-span-2-->
html
现在你看到我了
现在你看不见我了
`v-else` 元素必须紧跟在带 `v-if` 或者 `v-else-if` 的元素的后面
### \<template> 上使用 v-if 条件渲染分组
html
Paragraph 1
### 用 key 管理可复用的元素
<!--rehype:wrap-class=col-span-2-->
html
### v-show
html
Hello!
带有 `v-show` 的元素始终会被渲染并保留在 DOM 中,只是简单地切换元素的 `CSS` 属性 `display`
列表渲染
---
### v-for
html {3}
- {{ item.message }}
```js
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
### v-for 可选的第二个参数(索引)
html {2}
<li v-for="(item, index) in items">
{{ index }}
{{ item.message }}
</li>
如下 data
js
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
也可以用 of
替代 in
作为分隔符
html
<div v-for="item of items"></div>
### v-for 使用对象
html
<li v-for="value in object">
{{ value }}
</li>
如下 data
js
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
渲染结果
How to do lists in Vue
Jane Doe
2016-04-10
提供第二个的参数为 property 名称 (也就是键名)
html
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
还可以用第三个参数作为索引
html
<div v-for="(value,name,index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
### v-for/v-if
html {2,3}
<li
v-for="todo in todos"
v-if="!todo.isComplete"
>
{{ todo }}
</li>
只渲染未完成的 todo,下面加上 v-else
示例
html
<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>
### 组件上使用 v-for
html
<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
现在是必须的
事件处理
—-
### 监听事件
html {2}
<div id="example-1">
<button v-on:click="counter += 1">
+1
</button>
<p>按钮已被点击 {{ counter }} 次。</p>
</div>
js
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})
### 事件处理方法
html {3}
<div id="example-2">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">
你好
</button>
</div>
js
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})
也可以用 JavaScript 直接调用方法
js
example2.greet() // => 'Hello Vue.js!'
### 内联处理器中的方法
html {2,5}
<div id="example-3">
<button v-on:click="say('hi')">
弹出 hi
</button>
<button v-on:click="say('what')">
弹出 what
</button>
</div>
js {4}
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
访问原始的 DOM 事件,用特殊变量 $event
html
<button v-on:click="say('what', $event)">
提交
</button>
js
methods: {
say: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) {
event.preventDefault()
}
alert(message)
}
}
### 事件修饰符
html
<!-- 阻止单击事件继续传播 -->
<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>
<!-- 当 event.target 是当前元素自身时触发 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
### 事件修饰符 passive
html
<!-- 滚动事件的默认行为(即滚动行为)会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 包含 event.preventDefault() 的情况 -->
<p v-on:scroll.passive="onScroll">
...
</p>
这个 .passive
修饰符尤其能够提升移动端的性能。
### 按键修饰符
html
<!-- 在 key 是 Enter 时调用 vm.submit() -->
<input v-on:keyup.enter="submit">
<!-- 在 key 是 PageDown 时被调用 -->
<input v-on:keyup.page-down="onPageDown">
<!-- Alt + C -->
<input v-on:keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div v-on:click.ctrl="doSomething">
### .exact 修饰符
html
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="ctrlClick">
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">
计算属性和侦听器
—-
### 基础例子
html
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>
计算的反向消息: "{{ reversedMessage }}"
</p>
</div>
js
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('')
.reverse().join('')
}
}
})
### 计算属性缓存 vs 方法
html
<p>
计算的反向消息:"{{ reversedMessage() }}"
</p>
在组件中,我们可以将同一函数定义为一个方法而不是一个计算属性
js
methods: {
reversedMessage: function () {
return this.message.split('')
.reverse().join('')
}
}
两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。
### 计算属性 vs 侦听属性
html
<div id="demo">{{ fullName }}</div>
js
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
}
}
})
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
js
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName
+ ' ' + this.lastName
}
}
})
### 计算属性的 setter
js
computed: {
fullName: {
get: function () { // getter
return this.firstName + ' ' + this.lastName
},
set: function (newValue) { // setter
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
表单输入绑定
—-
### 文本
html
<input v-model="msg" placeholder="编辑我">
<p>msg is: {{ msg }}</p>
### 多行文本
html {3}
<span>Multiline message is:</span>
<textarea
v-model="message"
placeholder="添加多行"></textarea>
<p>{{ message }}</p>
### 复选框
html {4}
<input
type="checkbox"
id="checkbox"
v-model="checked"
>
<label for="checkbox">{{ checked}}</label>
### 多个复选框
html
<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
js
new Vue({
el: '...',
data: {
checkedNames: []
}
})
### 单选按钮
html
<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>
—-
js
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
### 选择框
html
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
—-
js
new Vue({
el: '...',
data: {
selected: ''
}
})
### 选择框(数组)
html
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<div>Selected: {{ selected }}</div>
—-
js
new Vue({
el: '...',
data: {
selected: []
}
})
### v-for 渲染的动态选项
html {3-4}
<select v-model="selected">
<option
v-for="option in options"
v-bind:value="option.value"
>
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
—-
js {6-8}
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
### 值绑定
html
<!-- 当选中时,pc 为字符串 "a" -->
<input type="radio" v-model="pc" value="a">
<!-- toggle 为 true 或 false -->
<input type="checkbox" v-model="toggle">
<!-- 选中第一个选项时selected为字符串 abc -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>
### 单选按钮
html
<input
type="radio"
v-model="pick"
v-bind:value="a">
当选中时
js
vm.pick === vm.a
### 复选框
html {3}
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
—-
js
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'
### 选择框的选项
html
<select v-model="selected">
<!-- 内联对象字面量 -->
<option v-bind:value="{ number: 123 }">
123
</option>
</select>
当选中时
js
typeof vm.selected // => 'object'
vm.selected.number // => 123
### 修饰符
html
<!-- lazy:在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">
<!-- number:自动将用户的输入值转为数值类型 -->
<input v-model.number="age" type="number">
<!-- trim:自动过滤用户输入的首尾空白字符 -->
<input v-model.trim="msg">
组件基础
—-
### 单文件组件
- 将 HTML
/CSS
/JS
三部分存放到一个 Hello.vue
文件中
html
<template>
<p>{{ title }} World!</p>
</template>
<script>
export default {
name: 'Hello',
props: {
title: {
type: String,
default: 'Hello'
}
},
data: function() {
return {
greeting: "Hello"
};
}
};
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>
- 使用 Hello.vue
组件
html
<script>
import Vue from "vue";
import Hello from "./Hello";
export default {
components: { Hello }
}
</script>
<template>
<div>
<Hello :title="'aaaa'"></Hello>
</div>
</template>
### 基本示例
js
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `
<button v-on:click="count++">
你点击了我 {{ count }} 次
</button>
`
})
组件是可复用的 Vue
实例
html
<div id="components-demo">
<button-counter></button-counter>
</div>
—-
js
new Vue({
el: '#components-demo'
})
组件的复用
html
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
### 单个根元素
js {4}
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
—-
html
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
>
</blog-post>
### 向子组件传递数据
js
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
当值传递给一个 prop
attribute
的时候,变成了组件实例的一个 property
html
<blog-post title="写博客"></blog-post>
<blog-post title="如此有趣"></blog-post>
### data
必须是一个函数
js
data: function () {
return {
count: 0
}
}
组件的 data
选项必须是一个函数
### 监听子组件事件
js {7}
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>
`
})
—-
html {3}
<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
可以使用 $emit
的第二个参数来提供这个值
html {2}
<button
v-on:click="$emit('enlarge-text', 0.1)"
>
Enlarge text
</button>
通过 $event
访问到被抛出的这个值
html {3}
<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>
如果这个事件处理函数是一个方法
html {3}
<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>
那么这个值将会作为第一个参数传入这个方法
js
methods: {
onEnlargeText: function(enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
### 在组件上使用 v-model
自定义事件也可以用于创建支持 v-model
的自定义输入组件。
html
<input v-model="searchText">
等价于
html
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
当用在组件上时,v-model 则会这样:
html
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
为了让它正常工作,这个组件内的 \ 必须:
- 将其 value
attribute 绑定到一个名叫 value
的 prop
上
- 在其 input
事件被触发时,将新的值通过自定义的 input
事件抛出
—-
js
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
现在 v-model
就应该可以在这个组件上完美地工作起来了
html {2}
<custom-input
v-model="searchText"
>
</custom-input>
### 通过插槽分发内容
html
<alert-box>
发生了不好的事情。
</alert-box>
—-
js {5}
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
### 动态组件示例
```html
- `、`
- `、`` 和 `` 和 `