什么是Vue
Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。
生命周期钩子
生命周期 | 描述 |
---|---|
beforeCreate | 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。 |
created | 在实例创建完成后,属性已绑定。挂载阶段还没开始,DOM还未生成,$el 属性目前不可见。 |
beforeMount | 在挂载开始之前被调用 |
mounted | 模板编译挂载之后(不保证组件已在doucument中) |
beforeUpdate | 组件更新之前 |
updated | 组件更新之后 |
activated | keep-alive 组件激活时调用 |
deactivated | keep-alive 组件停用时调用 |
beforeDestroy | 实例销毁前调用,在这一步,实例仍然完全可用 |
destroyed | 实例销毁后调用 |
errorCaptured | 当捕获一个来自子孙组件的错误时被调用 |
注意箭头函数的使用
不在选项属性或者回调上使用箭头函数,因为箭头函数是与父级作用域绑定在一起的,this指向的是最近的普通函数的作用域
1 | created: () => console.log(this.a); //Uncaught TypeError: Cannot read property of undefined |
计算属性和侦听器
计算属性
- 当有些数据需要随着其他数据的变动而变动时,数据依赖;
- 基于它们的依赖进行缓存的,不希望有依赖可使用方法实现;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter
//...
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
//...
侦听器: 当需要的数据在变化时执行异步执行或开销较大的操作
绑定 HTML Class
可同时写固定class和动态class1
<div :class="[icon, {isActive ? activeClass : ''}]"></div>
条件渲染
1.在 <template>
元素上使用 v-if 条件渲染分组1
2
3<template v-if>
<div>template元素不会渲染到页面上</div>
</template>
2.用 key 管理可复用的元素1
2
3
4
5
6
7
8
9
10<!--这两个元素是完全独立的,不要复用它们-->
<!--如果不使用 key 两个模板使用了相同的元素,<input> 不会被替换掉——仅仅是替换了它的 placeholder-->
<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>
3.v-if=’null、undefined 或 false’ 表示为 fasle
列表渲染
1.可用 of 替代 in, 因为它更接近 JavaScript 迭代器的用法1
<div v-for="item of items"></div>
2.一个对象的 v-for
在遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。1
2
3
4
5object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
1 | <div v-for="(value, key, index) in object"> |
1 | //结果 |
3.数组更新检测1
2
3
4
5
6
7
8
9var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
变异方法:触发视图更新
包括: pop(), push(), shift(), unshift(), splice(), sort(), reverse()1
example1.items.push({ message: 'AOA' })
替换数组: 用一个含有相同元素的数组去替换原来的数组是非常高效的操作
包括: filter(), concat(), slice(), 总是返回一个新数组1
2
3example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})注意事项: 由于 JavaScript 的限制,Vue 不能检测以下变动的数组
- 当你利用索引直接设置一个项时,响应式:
Vue.set(vm.items, indexOfItem, newValue)
或vm.$set(vm.items, indexOfItem, newValue)
- 当你修改数组的长度时:
vm.items.splice(newLength)
4.对象更改检测注意事项
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})
//添加单个属性
Vue.set(vm.userProfile, 'age', 27);
vm.$set(vm.userProfile, 'age', 27);
//添加多个属性
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
height: 188
})
5.显示过滤/排序结果
- 计算属性
1
<li v-for="n in evenNumbers">{{ n }}</li>
1 | data: { |
- methods
1
<li v-for="n in even(numbers)">{{ n }}</li>
1 | data: { |
事件处理
1.事件修饰符
- .stop: 阻止单击事件继续传播
- .prevent: 提交事件不再重载页面
- .capture: 添加事件监听器时使用事件捕获模式,即元素自身触发的事件先在此处理,然后才交由内部元素进行处理
- .self: 只当在 event.target 是当前元素自身时触发处理函数, 即事件不是从内部元素触发的
- .once: 点击事件将只会触发一次
- .passive: 尤其能够提升移动端的性能, 不和.prevent一起使用
2.按键修饰符
- .enter 回车键
<input @keyup.enter="submit">
- .delete 捕获“删除”和“退格”键
v-model修饰符
.lazy: 使用 change 事件进行同步1
2<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">
.number: 自动将用户的输入值转为数值类型1
<input v-model.number="age" type="number">
.trim: 自动过滤用户输入的首尾空白字符1
<input v-model.trim="msg">
v-model等价于1
2
3
4
5
6<input v-model="searchText">
<!--等价于-->
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
组件
1.data必须是一个函数,每个实例可以维护一份被返回对象的独立的拷贝
2.通过事件向父级组件发送消息: $emit(‘方法名字’, 参数), 通过方法名触发事件并传值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
45
46
47
48
49
50
51
52
53
54
55
56<!--应用页面-->
<div>
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post of posts"
:key="post.id"
:post="post"
@enlarge-text='enlarge'>
</blog-post>
</div>
<custom-input v-model="searchText"></custom-input>
</div>
<script>
//组件模板
Vue.component('blog-post', {
props: ['post'],
template: `
<div>
<p>{{post.title}}</p>
<button @click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
<div v-html="post.contet"></div>
</div>
`
})
//v-model
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
//vue实例
var vm = new Vue({
el: '#app',
data: {
posts: [
{ id: 1, title: 'My journey with Vue', contet: 'sdfasdfad' },
{ id: 2, title: 'Blogging with Vue', contet: 'sdfasdfad22' },
{ id: 3, title: 'Why Vue is so fun', contet: 'sdfasdfads1111' }
],
postFontSize: 1,
searchText: ''
},
methods: {
enlarge(e) {
this.postFontSize += e; //e: 0.1
}
}
})
</script>
3.插槽<slot></slot>
- 作用域插槽
例如一个<todo-list>
组件模板可能包含了以下代码:1
2
3
4
5
6
7
8
9<ul>
<li v-for="todo in todos" :key="todo.id">
<!-- 我们为每个 todo 准备了一个插槽,将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
现在当我们使用 <todo-list>
组件的时候,我们可以选择为待办项定义一个不一样的 <template>
作为替代方案,并且可以通过 slot-scope 特性从子组件获取数据1
2
3
4
5
6
7
8
9
10
11
12
13
14<todo-list :todos="todos">
<template slot-scope="slotProps">
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
<!-- ES2015解构赋值 -->
<todo-list :todos="todos">
<template slot-scope="{ todo }">
<span v-if="todo.isComplete">✓</span>
{{ todo.text }}
</template>
</todo-list>
4.动态组件is
1
2<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
5.基础组件的自动化全局注册
6.自定义事件
始终使用 kebab-case 的事件名
1
2
3
4
5
6
7
8<my-component @my-event="doSomething"></my-component>
Vue.component('my-component', {
props: [],
template: `
<div @click="$emit('my-event')"></div>
`
})将原生事件绑定到组件
$attrs
属性: 使用v-bind="$attrs"
, 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用$listeners属性
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<base-input label="vue啊" value='ddd' v-model='getValue'></base-input>
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function() {
var vm = this
// `Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `v-model` 的工作
input: function(event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
</label>
`
}).sync
修饰符
待续