Vue手册
wukong

Vue手册

[TOC]

Vue实例

关联数据和DOM

1
2
3
4
<!-- HTML -->
<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
<!-- HTML -->
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
1
2
3
4
5
6
7
// JavaScript
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date().toLocaleString()
}
}

if条件

1
2
3
4
<!-- HTML -->
<div id="app-3">
<p v-if="seen">现在你看到我了</p>
</div>
1
2
3
4
5
6
7
// JavaScript
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})

for循环

1
2
3
4
5
6
7
8
<!-- HTML -->
<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
11
12
13
14
15
16
// JavaScript
var app4 = new Vue({
el: '#app-4',
data: {
todos: [{
text: '学习 JavaScript'
},
{
text: '学习 Vue'
},
{
text: '整个牛项目'
}
]
}
})

v-on事件监听

1
2
3
4
5
<!-- HTML -->
<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
// JavaScript
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function() {
this.message = this.message.split('').reverse().join('')
}
}
})

v-model双向绑定

1
2
3
4
5
<!-- HTML -->
<div id="app-6">
<p>{{ message }}</p>
<input v-model="message">
</div>
1
2
3
4
5
6
7
// JavaScript
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})

freeze冻结 阻止修改

1
2
3
4
5
6
<!-- HTML -->
<div id="app">
<p>{{ foo }}</p>
<!-- 这里的 `foo` 不会更新! -->
<button v-on:click="foo = 'baz'">Change it</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
// JavaScript
var obj = {
foo: 'bar'
}

Object.freeze(obj)

new Vue({
el: '#app',
data: obj
})

vue生命周期

1
2
3
4
5
6
7
8
9
10
11
// JavaScript
new Vue({
data: {
a: 1
},
created: function() {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"

image

模板语法

文本

1
2
3
<!-- HTML -->
<!-- v-once当数据改变时,插值处的内容不会更新 -->
<span v-once>这个将不会改变: {{ msg }}</span>

原始 HTML

1
2
3
4
<!-- HTML -->
<!-- 容易导致 XSS 攻击 -->
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

Attribute

1
2
3
4
<!-- HTML -->
<div v-bind:id="dynamicId"></div>
<!-- null、undefined 、false -->
<button v-bind:disabled="isButtonDisabled">Button</button>

使用 JavaScript 表达式

1
2
3
4
5
6
7
8
9
<!-- HTML -->
<!-- 数据作用域下作为 JavaScript 被解析,只能单个表达式 -->
{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div v-bind:id="'list-' + id"></div>

只能访问全局变量白名单,不能访问用户自定义全局变量

1
2
3
4
5
6
7
if (process.env.NODE_ENV !== 'production') {
const allowedGlobals = makeMap(
'Infinity,undefined,NaN,isFinite,isNaN,'
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,'
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,'
'require' // for Webpack/Browserify
)

参数

1
2
3
4
5
<!-- HTML -->
<!-- v-bind 响应式更新HTML attribute -->
<a v-bind:href="url">...</a>
<!-- v-on 监听DOM事件 -->
<a v-on:click="doSomething">...</a>

动态参数

1
2
3
4
5
<!-- HTML -->
<a v-bind:[attributeName]="url"> ... </a>
<!-- 避免使用大写字符来命名键名,因为浏览器会把 attribute 名全部强制转为小写 -->
<!-- eventName 改为 eventname -->
<a v-on:[eventName]="doSomething"> ... </a>

修饰符

1
2
3
<!-- HTML -->
<!-- 指明的特殊后缀 -->
<form v-on:submit.prevent="onSubmit">...</form>

计算属性和侦听器

computed 计算

计算属性具有缓存, 用于获取返回值

1
2
3
4
5
6
<!-- HTML -->
<div id="example">
<p>Original message: "{{ message }}"</p>
<input v-model="message">
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// JavaScript
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function() {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})

watch 侦听

监听特定值得前后变化, 用于执行

1
2
3
4
5
6
7
8
// JavaScript
watch: {
status: function(value, oldValue) {
this.status = value
this.page = 1
this.getData(1)
},
},

Class 与 Style 绑定

class对象语法

1
2
<!-- HTML -->
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
1
2
3
4
5
// JavaScript
data: {
isActive: true,
hasError: false
}

style内联样式

1
2
3
<!-- HTML -->
<div v-bind:style="styleObject"></div>
<div v-bind:style="[baseStyles, overridingStyles]"></div>
1
2
3
4
5
6
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}

条件渲染

v-if

v-else-if

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- HTML -->
<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>

独立,不复用

1
2
3
4
5
6
7
8
9
10
<!-- HTML -->

<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>

v-for

数组

1
2
3
4
5
6
<!-- HTML -->
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// JavaScript
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [{
message: 'Foo'
},
{
message: 'Bar'
}
]
}
})

对象

1
2
3
4
5
6
<!-- HTML -->
<ul id="v-for-object" class="demo">
<li v-for="(value, name,index) in object">
{{index}}.{{ name }}: {{ value }}
</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
// JavaScript
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})

数组更新检测

变异方法

  • push()向数组的末尾添加一个或多个元素,并返回新的长度
  • pop()删除并返回数组的最后一个元素。
  • shift()把数组的第一个元素从其中删除,并返回第一个元素的值
  • unshift()向数组的开头添加一个或更多元素,并返回新的长度。
  • splice()向/从数组中添加/删除项目,然后返回被删除的项目
  • sort()对数组的元素进行排序。
  • reverse()颠倒数组中元素的顺序。

替换数组

  • filter() 创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
  • concat() 用于连接两个或多个数组。
  • slice() 可从已有的数组中返回选定的元素。

事件处理

监听事件

v-on 监听DOM事件,运行js代码

1
2
3
4
5
<!-- HTML -->
<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
1
2
3
4
5
6
7
// JavaScript
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})

事件处理方法

1
2
3
4
5
<!-- HTML -->
<div id="example-3">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
1
2
3
4
5
6
7
8
new Vue({
el: '#example-3',
methods: {
say: function(message) {
alert(message)
}
}
})

事件修饰符

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
<!-- HTML -->
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></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>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

按键修饰符

1
2
3
<!-- HTML -->
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

表单输入绑定

文本

1
2
3
4
5
<!-- HTML -->
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

复选框

1
2
3
4
5
6
7
8
9
10
11
<!-- HTML -->
<div id='example-3'>
<input type="checkbox" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
1
2
3
4
5
6
7
// JavaScript
new Vue({
el: '#example-3',
data: {
checkedNames: []
}
})

单选按钮

1
2
3
4
5
6
7
8
9
10
<!-- HTML -->
<div id="example-4">
<input type="radio" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
1
2
3
4
5
6
7
// JavaScript
new Vue({
el: '#example-4',
data: {
picked: ''
}
})

选择框

单选

1
2
3
4
5
6
7
8
<!-- HTML -->
<!-- 多选时select中增加 `multiple` ,data中的selected改为数组 -->
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// JavaScript
new Vue({
el: '...',
data: {
selected: 'A',
options: [{
text: 'One',
value: 'A'
},
{
text: 'Two',
value: 'B'
},
{
text: 'Three',
value: 'C'
}
]
}
})

修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:

1
2
3
<!-- HTML -->
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">

.number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
这通常很有用,因为即使在 type=”number” 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。

1
2
<!-- HTML -->
<input v-model.number="age" type="number">

.trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

1
2
<!-- HTML -->
<input v-model.trim="msg">

组件注册

通过 Vue.component 全局注册,名称使用 kebab-case样式
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝

1
2
3
4
5
6
<!-- HTML -->
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
1
2
3
4
5
6
7
8
9
10
// JavaScript
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function() {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

传递数据到子组件

1
2
3
4
5
6
<!-- HTML -->
<blog-post post-title="My journey with Vue"></blog-post>
<blog-post post-title="Blogging with Vue"></blog-post>
<blog-post post-title="Why Vue is so fun"></blog-post>

<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title" v-bind:content="post.content" v-bind:publishedAt="post.publishedAt" v-bind:comments="post.comments"></blog-post>
1
2
3
4
5
// props 选项将其包含在该组件可接受的 prop 列表中
Vue.component('blog-post', {
props: ['post-title'],
template: '<h3>{{ title }}</h3>'
})

动态组件

在不同组件之间进行动态切换

1
2
3
<!-- HTML -->
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

特殊渲染

1
2
3
4
5
<!-- HTML -->
<!-- <ul>、<ol>、<table> 和 <select> -->
<table>
<tr is="blog-post-row"></tr>
</table>

局部注册

外部构建后 导入

1
2
3
4
5
6
7
8
9
10
11
12
// JavaScript
import BaseButton from './BaseButton.vue'
import BaseIcon from './BaseIcon.vue'
import BaseInput from './BaseInput.vue'

export default {
components: {
"base-button": BaseButton,
"base-icon": BaseIcon,
"base-input": BaseInput
}
}

Prop

传递静态或动态 Prop

1
2
3
4
5
6
7
8
9
<!-- HTML -->
<!-- <blog-post title="My journey with Vue"></blog-post> -->

<!-- 尽可能使用v-bind -->
<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post v-bind:title="post.title + ' by ' + post.author.name"></blog-post>

Prop 验证

控制台的警告, 方便他人调用

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
// JavaScript
Vue.component('my-component', {
props: {
// 基础的类型检查 ( `null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function() {
return {
message: 'hello'
}
}
},
// 自定义验证函数
propF: {
validator: function(value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})

type 类型

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

过滤器

常用于文本预处理

1
2
3
4
5
6
7
8
9
10
11
12
<!-- HTML -->
<!-- 在双花括号中 -->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

<!-- 串联 -->
{{ message | filterA | filterB }}

<!-- 传参 -->
{{ message | filterA('arg1', arg2) }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// JavaScript
filters: {
capitalize: function(value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}

// 全局过滤器
Vue.filter('capitalize', function(value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})

new Vue({
// ...
})
 Comments