Vue.js 學習筆記

Vue.js 是什麼?

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

Vue 更多的是一個 ViewModel。

只有当实例被创建时 data 中存在的属性才是响应式的。
使用 Object.freeze(anObject),会阻止修改现有的属性,也意味着响应系统无法再追踪变化。

Vue 实例的属性与方法:

Vue 实例暴露了一些有用的实例属性与实例方法,它们都有前缀 $,以便与用户定义的属性区分开来。

1
2
3
4
5
6
7
8
9
10
11
12
13
var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
})

- 点击查看 Vue 实例属性列表
- 点击查看 Vue 实例的数据方法列表
- 点击查看 Vue 实例的事件方法列表
- 点击查看 Vue 实例的生命周期钩子方法列表

插值

文本

数据绑定最常见的形式就是使用“Mustache”语法 (双花括号) 的文本插值:

1
<span>Message: {{ msg }}</span>

Mustache 标签将会被替代为对应数据对象上 msg 属性的值。无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:

1
<span v-once>这个将不会改变: {{ msg }}</span>

原始 HTML

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:

1
2
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

特性

Mustache 语法不能作用在 HTML 特性上,遇到这种情况应该使用 v-bind 指令:

1
<div v-bind:id="dynamicId"></div>

在布尔特性的情况下,它们的存在即暗示为 true,不存在暗示为 null、undefined 或 false

使用 JavaScript 表达式

对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。

1
2
3
4
5
6
7
{{ number + 1 }}

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

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

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

这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,语句、流控制都不会生效。

指令(Directives)

指令是带有 v- 前缀的特殊特性。
指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
响应式编程指的是 Model 和 View 的数据绑定,这样可以做到二者的变化联动。

参数

一些指令能够接收一个“参数”,在指令名称之后以冒号表示。

缩写

Vue.js 为 v-bind 和 v-on 这两个最常用的指令,提供了缩写形式。
「v-bind」可以省略;
「v-on:」可以缩写为「@」。

计算属性和侦听器

computed属性 是基于它们的依赖进行缓存的,方法没缓存。
所以,对于任何复杂逻辑,你都应当使用计算属性。
计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter
watch属性 很容易被滥用。
watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
除了 watch 选项之外,您还可以使用命令式的 vm.$watch API。

条件渲染

v-if 条件渲染块

1
2
3
4
<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>

v-if 条件渲染分组

用 key 管理可复用的元素

1
<input placeholder="Enter your username" key="username-input">

不同的 key 代表不同的元素。

v-show 条件渲染

另一个用于根据条件展示元素的选项是 v-show 指令。用法大致一样:

1
<h1 v-show="ok">Hello!</h1>

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。
v-show 不支持 <template> 元素,也不支持 v-else。

v-if vs v-show

v-if 是“真正”的条件渲染,v-show 只是简单地基于 CSS 进行切换。
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
如果需要非常频繁地切换,则使用 v-show 较好;
如果在运行时条件很少改变,则使用 v-if 较好。

v-for

在 v-for 块中,我们拥有对父作用域属性的完全访问权限。v-for 还支持一个可选的第二个参数为当前项的索引。
可以用 of 替代 in 作为分隔符。
可以用 v-for 对一个对象的属性来迭代,也可以提供第二个的参数为键名;在遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。

1
2
3
4
5
6
7
8
9
10
11
12
<div v-for="item of items"></div>
<div v-for="item in items"></div>

<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>

<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>

建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

数组更新检测

非响应性的(由于 JavaScript 的限制)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- Vue 不能检测以下变动的数组 -->
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

<!-- Vue 不能检测对象属性的添加或删除 -->
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` 现在是响应式的

vm.b = 2
// `vm.b` 不是响应式的

Vue.set 方法向嵌套对象添加响应式对象

1
2
Vue.set(vm.items, indexOfItem, newValue) // 对数组
Vue.set(vm.userProfile, key, value) // 对字典(对象属性也是字典)

数组的可变方法
  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
数组的不可变方法(返回值是一个新数组)
  • filter()
  • concat()
  • slice()

v-for with v-if

当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。

事件处理

方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

.passive 修饰符

Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符。

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

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

按键修饰符

1
2
<!-- 缩写语法 -->
<input @keyup.enter="submit">

表单输入绑定

基础用法

你可以用 v-model 指令在表单 <input><textarea>元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。

对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input 事件。

组件基础

组件示例:

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

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

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

一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
为了能在模板中使用,组件必须先注册以便 Vue 能够识别。
组件的注册类型有两种:全局注册和局部注册:
全局注册 - Vue.component(‘my-component-name’, {//options})
局部注册 -

1
2
3
4
5
6
7
8
9
10
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
然后在 components 选项中定义你想要使用的组件:
new Vue({
el: '#app'
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})

通过 Prop 向子组件传递数据

动态组件

在不同组件之间进行动态切换,可以通过 Vue 的 元素加一个特殊的 is 特性来实现:

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

待续…

參考鏈接:

1、https://cn.vuejs.org/v2/guide/