渐进式 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: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
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>
<!-- 动态参数的缩写 (2.6.0+) -->
<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-forv-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">
<!-- `greet` 是在下面定义的方法名 -->
<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` 对象中定义方法
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})

也可以用 JavaScript 直接调用方法

1
example2.greet() // => 'Hello Vue.js!'

内联处理器中的方法

{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>
<!-- 当 event.target 是当前元素自身时触发 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

事件修饰符 passive

1
2
3
4
5
6
<!-- 滚动事件的默认行为(即滚动行为)会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 包含 event.preventDefault() 的情况 -->
<p v-on:scroll.passive="onScroll">
...
</p>

这个 .passive 修饰符尤其能够提升移动端的性能。

按键修饰符

1
2
3
4
5
6
7
8
<!-- 在 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 修饰符

1
2
3
4
5
6
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<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: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
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 () { // getter
return this.firstName + ' ' + this.lastName
},
set: function (newValue) { // setter
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
<!-- 当选中时,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>

单选按钮

1
2
3
4
<input
type="radio"
v-model="pick"
v-bind:value="a">

当选中时

1
vm.pick === vm.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 // => 'object'
vm.selected.number // => 123

修饰符

1
2
3
4
5
6
7
8
<!-- 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 文件中

    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
    <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 组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <script>
    import Vue from "vue";
    import Hello from "./Hello";

    export default {
    components: { Hello }
    }
    </script>
    <template>
    <div>
    <Hello :title="'aaaa'"></Hello>
    </div>
    </template>

基本示例

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 绑定到一个名叫 valueprop
  • 在其 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-leave-active 低于 2.1.8 版本 */
.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-leave-active 用于 2.1.8 以下版本 */
.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-leave-active 适用于 2.1.8 以下版本 */
.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 侦听器。

另见


评论
avatar
竹山一叶
技术分享 个人心得
Follow Me
公告
欢迎光临小站,这里是我日常工作和学习中收集和整理的总结,希望能对你有所帮助:)

本站的内容经过个人加工总结而来,也参考了网友们分享的资料,如有侵权,请第一时间联系我,我将及时进行修改或删除😊
目录
  1. 1. 入门
    1. 1.1. 介绍
      1. 1.1.1. 快速创建 Vue 项目
    2. 1.2. 声明式渲染
    3. 1.3. 基础例子
    4. 1.4. 绑定元素属性
    5. 1.5. 条件
    6. 1.6. 循环
    7. 1.7. 点击事件处理
    8. 1.8. 输入事件处理
  2. 2. 模板语法
    1. 2.1. 文本
    2. 2.2. 原始 HTML
    3. 2.3. 属性
    4. 2.4. JavaScript 表达式
    5. 2.5. 指令
    6. 2.6. 指令参数
    7. 2.7. 指令动态参数 v2.6
    8. 2.8. 指令修饰符
    9. 2.9. 指令缩写
  3. 3. Class 与 Style 绑定
    1. 3.1. 对象语法
    2. 3.2. 与普通的 class 属性共存
    3. 3.3. 绑定的数据对象不必内联定义在模板里
    4. 3.4. 三元表达式
    5. 3.5. 数组
    6. 3.6. 数组语法
    7. 3.7. 内联样式
    8. 3.8. 内联样式对象通常更好
    9. 3.9. 内联样式数组语法
    10. 3.10. 内联样式多重值
  4. 4. 条件渲染
    1. 4.1. v-if
    2. 4.2. v-else-if
    3. 4.3. v-else
    4. 4.4. <template> 上使用 v-if 条件渲染分组
    5. 4.5. 用 key 管理可复用的元素
    6. 4.6. v-show
  5. 5. 列表渲染
    1. 5.1. v-for
    2. 5.2. v-for 可选的第二个参数(索引)
    3. 5.3. v-for 使用对象
    4. 5.4. v-for/v-if
    5. 5.5. 组件上使用 v-for
  6. 6. 事件处理
    1. 6.1. 监听事件
    2. 6.2. 事件处理方法
    3. 6.3. 内联处理器中的方法
    4. 6.4. 事件修饰符
    5. 6.5. 事件修饰符 passive
    6. 6.6. 按键修饰符
    7. 6.7. .exact 修饰符
  7. 7. 计算属性和侦听器
    1. 7.1. 基础例子
    2. 7.2. 计算属性缓存 vs 方法
    3. 7.3. 计算属性 vs 侦听属性
    4. 7.4. 计算属性的 setter
  8. 8. 表单输入绑定
    1. 8.1. 文本
    2. 8.2. 多行文本
    3. 8.3. 复选框
    4. 8.4. 多个复选框
    5. 8.5. 单选按钮
    6. 8.6. 选择框
    7. 8.7. 选择框(数组)
    8. 8.8. v-for 渲染的动态选项
    9. 8.9. 值绑定
    10. 8.10. 单选按钮
    11. 8.11. 复选框
    12. 8.12. 选择框的选项
    13. 8.13. 修饰符
  9. 9. 组件基础
    1. 9.1. 单文件组件
    2. 9.2. 基本示例
    3. 9.3. 单个根元素
    4. 9.4. 向子组件传递数据
    5. 9.5. data 必须是一个函数
    6. 9.6. 监听子组件事件
    7. 9.7. 在组件上使用 v-model
    8. 9.8. 通过插槽分发内容
    9. 9.9. 动态组件示例
    10. 9.10. 解析 DOM 模板时的注意事项
  10. 10. 过渡 & 动画
    1. 10.1. 单元素/组件的过渡
    2. 10.2. CSS 过渡
    3. 10.3. CSS 动画
    4. 10.4. 过渡的类名
      1. 10.4.1. 自定义过渡的类名
    5. 10.5. 显性的过渡持续时间
    6. 10.6. 初始渲染的过渡
    7. 10.7. JavaScript 钩子
    8. 10.8. 列表的进入/离开过渡
  11. 11. Vue 2 API 参考
    1. 11.1. 全局配置
    2. 11.2. 全局 API
    3. 11.3. 数据
    4. 11.4. DOM
    5. 11.5. 生命周期钩子
    6. 11.6. 资源
    7. 11.7. 组合
    8. 11.8. 其它
    9. 11.9. 实例方法 / 数据
    10. 11.10. 实例 property
    11. 11.11. 实例方法 / 事件
    12. 11.12. 实例方法 / 生命周期
    13. 11.13. 指令
    14. 11.14. 特殊 attribute
    15. 11.15. 内置的组件
    16. 11.16. v-on (事件)修饰符
    17. 11.17. v-on (鼠标)修饰符
    18. 11.18. 系统修饰键
    19. 11.19. Keyboard 按键修饰符
    20. 11.20. v-bind 修饰符
  12. 12. 另见
最新文章
网站资讯
文章数目 :
437
已运行时间 :
本站总字数 :
431.6k
本站访客数 :
本站总访问量 :
最后更新时间 :
文章归档文章分类文章标签复制本文标题复制本文地址
随便逛逛