学习前端系列-vue.js

Vue.js

Vue是一套用户构建用户界面的渐进式框架,其核心是允许采用简洁的模板语法来声明式的将数据渲染进DOM。

基础

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

// <div id="app">
// {{ message}}
// </div>

var app = new Vue({
el: '#app',
data: {
message: 'hello, world'
}
})

v- 表示Vue提供的特殊特性
v-once // 一次性插值
v-html // 原始html
v-bind // 响应式更新html
v-if // if
v-for // for
v-on // 监听DOM事件
v-on:submit.prevent="onSubmit" // 修饰符
v-model // 在表单元素上创建双向数据绑定

// 定义组件
Vue.component('todo-item', {
template: '<li>这是一个代办项</li>'
})

// 创建Vue实例
var data = {a: 1, message: 'hello'}
var vm = new Vue({
data: data
})
// 只有data中的数据是响应式的
Object.freeze(data) // 会阻止修改现有的属性

vm.a = data.a // 数据属性
// 实例属性和方法
vm.$el = document.getElementById('expmple')
vm.$data = data
vm.$watch('a', function (newValue, oldValue)) {
// 这个回调将在a改变后调动
}

var vm = new Vue({
el: '#expmple',
data: data,
created: function () {
// 钩子函数,在实例被创建时执行
},
methods: { // 方法, 没有缓存
reverseMessage: function () {
return this.message.split('').reverse().join()
}
},
computed: { // 计算属性, 只有当message改变时, 才会重新求值, 有缓存
reverseMessage: function () {
return this.message.split('').reverse().join()
},
fullNmae: {
// getter
get: function () {
return this.fistName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[name.length - 1]
}
}
},
watch: { // 侦听属性
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
}
}
})

// 模板语法
<span>Message: {{ msg }}</span> 文本插值,不能在html上
<span v-once>这个不会改变: {{ msg }}</span>
v-html 使用html
<button v-bind:disabled="isButtonDisabled">Button</button> 数据使用在html上
<p v-if="seen">现在看到我了</p>
<a v-bind:href="url"></a>
<a v-on:click="doSomething"></a>
<from v-on:submit.prevent="onSubmit"></from>

<a v-bind:href="url"></a> 缩写 <a :href="url"></a>
<a v-on:click="doSomething"></a> 缩写 <a @click="doSomething"></a>

// 绑定html class
<div v-bind:class="{ active: isActive }"></div>
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px'}"></div>

// 条件
<div v-if="type === 'A'"></div>
<div v-else_if="type === 'B'"></div>
<div v-else="type === 'C'"></div>

<h1 v-show="ok"></h1>

// 列表渲染
<li v-for="item in items">
{{ item.message }}
</li>

<li v-for="(item, index) in items">
<div v-for="item of items"></div> // 迭代器

var explame = new Vue({
el: '#explame',
data: {
items: [
{ message: 'Foo'},
{ message: 'Bar'}
]
}
})

动态添加,触发响应更新
Vue.set(vm.items, indexOfItem, newValue) // 或
vm.$set(vm.items, indexOfItem, newVaule)

// 监听事件
v-on
事件修饰符
v-on:click.stop // 阻止单机事件继续
v-on:submit.prevent="onSubmit" // 提交事件不再重载页面
v-on:click.capture // 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理
v-on:click.self // 即事件不是从内部元素触发的
v-on:click.once // 只会触发一次
v-on:scroll.passive="onScroll" // 滚动事件的默认行为 (即滚动行为) 将会立即触发

按键修饰符
<input v-on:keyup.enter="submit"> // 只有按enter时,才执行

// 表单输入绑定
v-model 对<input> <textarea> <select> 有效

修饰符
v-model.lazy // 在change时更新
v-model.number // 自动输入值转为数值类型
v-model.trim // 过滤用户输入的首尾空白字符

// 组件
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () { // data 必须是一个函数
return {
count: 0
}
},
props: ['title'],
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

<div id="components-demo">
<button-counter title="hello"></button-counter>
</div>

new Vue({ el: '#components-demo' })

通过props向子组件传递数据
通过$emit向父组件发送消息
v-on:click="$emit('enlarge-text', 0.1)"

在组件中使用v-model
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
<custom-input v-model="searchText"></custom-input>

组件

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
57
58
59
60
61
62
63
64
65
66
Vue.component('my-component-name', { // 全局
// pass
})

new Vue ({ el: '#app'})

<div id="app">
<my-component-name></my-component-name>
</div>

var ComponentA = {} // 局部
new Vue ({
el: '#app',
components: {
'component-a': ComponentA
}
})

基础组件全局注册要在根Vue实例创建之前发生

// Prop
props 用短横写法
props: {
title: String, // 可以定义类型
likes: Number
}

Vue.component('blog-post', {
props: ['post-title'],
template: '<h3>{{ post-title }}</h3>'
})

<blog-post v-bind:post-title="post.post-title"></blog-post>

props 可以类型检查
inheritAttrs: false // 禁用特性继承

// 插槽内容
<slot name="header"></slot>

// 动态组件
<keep-alive> // 会缓存失活的组件
component v-bind:is="currentTabComponent"></component> // 切换组件
</keep-alive>

Vue.component( // 异步组件
'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component')
)

new Vue({
data: {
foo: 1
}
})

this.$root.foo // 获取根实例
this.$parent.map // 获取父级组件实例
this.$refs.usernameInput // 访问子组件实例
provide: function () { // 依赖注入
return {
getMap: this.getMap
}
}
inject: ['getMap']

过渡

1
2


----------本文完,感谢您的阅读----------