声明式渲染
1
2
3
4
5
6
7
8
9
10
11var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})指令
单向数据绑定:
v-bind:title
或{{}}
,(title为元素特性),v-bind
的缩写::
条件:
v-if
、v-else
、v-else-if
循环:
v-for
事件:
v-on:click
缩写:@
双向数据绑定:
v-model
插槽:
v-slot
缩写:#
v-html
组件,模板语言
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
34Vue.component('todo-item', {
// todo-item 组件现在接受一个
// "prop",类似于一个自定义特性。
// 这个 prop 名为 todo。
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
<div id="app-7">
<ol>
<!--
现在我们为每个 todo-item 提供 todo 对象
todo 对象是变量,即其内容可以是动态的。
我们也需要为每个组件提供一个“key”,稍后再
作详细解释。
-->
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id"
></todo-item>
</ol>
</div>
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其它什么人吃的东西' }
]
}
})Vue实例属性与方法
生命周期
事件修饰符
1
2// 触发event.preventDefault()
<form v-on:submit.prevent="onSubmit">...</form>.stop
.prevent
.capture
.self
.once
.passive
计算属性与监听器
计算属性:是基于它们的响应式依赖进行缓存的
1
2
3
4
5
6
7
8
9
10
11
12
13var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})监听器,当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的
按键修饰符
直接将
KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符。vue为了兼容,定义了常见的按键码别名:
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
系统修饰键
.ctrl
.alt
.shift
.meta
组件
一个组件的
data
选项必须是一个函数,每个实例可以维护一份被返回对象的独立的拷贝。在组件上使用v-model
1
2
3
4
5
6
7
8
9Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})1
<custom-input v-model="searchText"></custom-input>
通过插槽分发内容:
1
2
3<alert-box>
Something bad happened.
</alert-box>1
2
3
4
5
6
7
8Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})动态组件:
1
2<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>Prop
大小写
prop类型
非Prop的特性
替换/合并已有的特性
禁用特性继承,可以手动决定这些特性会被赋予哪个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})1
2
3
4
5<base-input
v-model="username"
required
placeholder="Enter your username"
></base-input>
自定义事件
自定义组件的v-model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Vue.component('base-checkbox', {
// 修改默认的value为prop,input为event
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})1
<base-checkbox v-model="lovingVue"></base-checkbox>
将原生事件绑定到组件
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
32Vue.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>
`
})现在
<base-input>
组件是一个完全透明的包裹器了,也就是说它可以完全像一个普通的input
元素一样使用了:所有跟它相同的特性和监听器的都可以工作。Props, data, computed, method加载顺序
关于子组件activated不执行的问题:需要设置keepAlive
复杂类型,数据更新检测
数组:
> Vue 不能检测以下变动的数组:
>
> 1. 当你利用索引直接设置一个项时,例如:`vm.items[indexOfItem] = newValue`
> 2. 当你修改数组的长度时,例如:`vm.items.length = newLength`
- 变异方法:splice, sort, reserve, push, pop, shift, unshfit
- 替换数组(非变异方法):例如:`filter()`, `concat()` 和 `slice()`
对象:
- `Vue.set(vm.userProfile, 'age', 27)`
- `Object.assign()`
和渲染无关的数据
vue
中data
的数据默认便会进行双向数据绑定,若是将大量的和渲染无关的数据直接放置在data
中,将会浪费双向数据绑定时所消耗的性能,将这些和渲染无关的数据进行抽离并配合Object.freeze
进行处理1
2
3
4const columnList = Object.freeze([
{ title: '姓名', key: 'name', align: 'center' },
{ title: '性别', key: 'gender', align: 'center' }
])路由组件传参,通过props解耦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})父子组件的加载、销毁顺序
1
2
3
4
5// 加载顺序
father beforeCreate -> father created -> father beforeMount -> son beforeCreate -> son created -> son beforeMount -> son mounted -> father mounted
// 卸载顺序
father beforeDestory -> son beforeDestory -> son destoryed -> father destroyed通过
@hook
监听子组件的生命周期1
<list @hook:mounted="listMounted" />