L3F.WIN

Github及Hexo的使用

0%

vue.js 权威指南(读书笔记)

Vue.js 权威指南

第1章 遇见Vue.js

MVVM

M 模型(Model), V 显示(View), V 显示模型(ViewModel) 实现了ViewModel 自动同步到 View

Vue.js是什么

Vue.js是一个构建数据驱动的Web界面的库

Vue.js特性

  1. 轻量
  2. 数据绑定
  3. 指令
  4. 插件化

Vue.js的Hello World

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue Hello Word</title>
<!-- vue的CDN地址 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="didi-navigator">
<ul>
<!-- 指令 -->
<li v-for="tab in tabs">
{{tab.text}}
</li>
</ul>
</div>

<script>
new Vue({
el: '#didi-navigator',
data: {
tabs: [
{text: '巴士'},
{text: '快车'},
{text: '专车'},
{text: '顺风车'},
{text: '出租车'},
{text: '代驾'}
]
}
})
</script>
</body>
</html>

第2章 数据绑定

语法

插值

使用双大括号

1
{{}}

插入HTML片段

1
{{{}}}

表达式

双大括号中可以插入表达式

1
2
3
4
5
{{cents/100}}
{{true? 1: 0}}
{{example.split(",")}}
{{example | toUpperCase}} #为表达式添加过滤
{{example | filterA a b}} #添加参数

指令

1
2
3
v-if="show"
v-bind:href="url"
v-on:click="action"

分隔符

可以在Vue.config中配置绑定的语法

  1. delimiters

    1
    Vue.config.delimiters = ["<%","%>"] 将默认的{{}} 改为<%%>
  2. unsafeDelimiters

    1
    Vue.config.unsafeDelimiters = ["<%","%>"] 将默认的HTML插值改为<%%>

第3章 指令

内部指令

v-if

判断语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="didi-navigator">
<ul v-if="ok">
<li v-for="tab in tabs">
{{tab.text}}
</li>
</ul>
</div>

<script>
new Vue({
el: '#didi-navigator',
data: {
tabs: [
{text: '巴士'},
{text: '快车'},
{text: '专车'},
{text: '顺风车'},
{text: '出租车'},
{text: '代驾'}
],
ok: false
}
})
</script>

v-show

是否显示,不显示的时候,使用样式表 display:none,这里和v-if的显示不同。

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
<body>
<div id="didi-navigator">
<ul v-show="ok">
<li v-for="tab in tabs">
{{tab.text}}
</li>
</ul>
</div>

<script>
new Vue({
el: '#didi-navigator',
data: {
tabs: [
{text: '巴士'},
{text: '快车'},
{text: '专车'},
{text: '顺风车'},
{text: '出租车'},
{text: '代驾'}
],
ok: false
}
})
</script>
</body>

v-else

必须同 v-ifv-show一起使用充当else功能

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
<body>
<div id="didi-navigator">
<ul v-show="ok">
<li v-for="tab in tabs">
{{tab.text}}
</li>
</ul>
<p v-if="ok">我是对的</p>
<p v-else="ok">我错了</p>
</div>

<script>
new Vue({
el: '#didi-navigator',
data: {
tabs: [
{text: '巴士'},
{text: '快车'},
{text: '专车'},
{text: '顺风车'},
{text: '出租车'},
{text: '代驾'}
],
ok: false
}
})
</script>
</body>

v-model

v-model 绑定input, select, text, checkbox, radio等表单控件的双向数据

** v-model参数 **

  1. number 将用户的输入自动转换为Number类型

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

    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
    <body>
    <div id="didi-navigator">
    <ul v-show="ok">
    <li v-for="tab in tabs">
    {{tab.text}}
    </li>
    </ul>
    <p v-if="ok">我是对的</p>
    <p v-else="ok">我错了</p>

    <input v-model.lazy="msg"><br>
    {{msg}}
    </div>

    <script>
    new Vue({
    el: '#didi-navigator',
    data: {
    tabs: [
    {text: '巴士'},
    {text: '快车'},
    {text: '专车'},
    {text: '顺风车'},
    {text: '出租车'},
    {text: '代驾'}
    ],
    ok: false,
    msg: "内容是在change事件后才改变的"
    }
    })
    </script>
    </body>
  3. trim 如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符

v-for

for循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body>
<div id="example">
<ul id="demo">
<!--$index,$key两个隐性变量在新的vue版本中被移除-->
<li v-for="(item, index) in items" class="item-{{index}}">
{{index}} - {{parentMessage}} {{item.msg}}
</li>
</ul>
</div>

<script>
var demo = new Vue({
el: '#demo',
data: {
parentMessage: '滴滴',
items: [
{msg: '顺风车'},
{msg: '专车'}
]
}
})
</script>
</body>

Vue.js 1.0.17及以后版本都支持of分割符 item in/of items

v-text

使用v-text可以使用Mustache语法轻松的操控元素中的纯文本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<div id="example">
<span v-text="'姓名:' + name"></span>
</div>

<script>
var demo = new Vue({
el: '#example',
data: {
name: 'Winbug'
}
})
</script>
</body>

v-html

使用v-html可以使用Mustache语法轻松的操控元素中的HTML片段(不推荐使用,容易导致XSS攻击)

v-bind

v-bind将一个或多个attribute动态绑定到表达式, v-bind: 可以缩写为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<div id="example">
<span :class="className"></span>
</div>

<script>
var demo = new Vue({
el: '#example',
data: {
className: 'Winbug'
}
})
</script>
</body>

v-on

v-on 用于绑定事件监听器。v-on: 可以缩写为 @

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div id="example">
<span :class="className" @click="myName">Click Me</span>
</div>

<script>
var demo = new Vue({
el: '#example',
data: {
className: 'Winbug'
},
methods: {
myName: function(){
alert(this.className);
}
}
})
</script>
</body>

相关事件修饰符

  • .stop 阻止冒泡
  • .prevent 阻止默认行为
  • .capture 添加事件侦听器时使用capture模式
  • .self 绑定元素本身时触发回调
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 阻止单击事件继续传播 -->
<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>

v-el 和 v-ref被 ref所替换

为DOM元素注册一个索引,方便通过所属势力的$els访问这个元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<div id="example">
<div id="app">
<input type="text" ref="input1"/>
<button @click="add">添加</button>
</div>
</div>

<script>
var demo = new Vue({
el: '#example',
data: {
},
methods: {
add: function(){
this.$refs.input1.value="22"
}
}
})
</script>
</body>

v-pre 可以用来显示原始Mustahce标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<div id="example">
<div id="app">
<span v-pre>{{ this will not be compiled }}</span>
</div>
</div>

<script>
var demo = new Vue({
el: '#example',
data: {
},
methods: {
}
})
</script>
</body>

v-cloak 这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。

v-cloak 在CSS样式表中添加

自定义指令

基础

一、钩子函数

+ bind 只调用一次,指令第一次绑定到元素上时调用
+ update 在bind之后立即以初始值为参数第一次调用,之后每当绑定值变化时调用。
+ unbind 只调用一次,在指令从元素上解绑时调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Vue.directive('my-directive', {
bind: function(){
//准备工作
//例如,添加事件处理器或只需要运行一次的高耗任务
},

update: function(newValue, oldValue){
//值更新时的工作
//也会以初始值为参数调用一次
},

unbind: function(){
//清理工作
//例如,删除bind()添加的事件监听器
}
})
+ 注册之后,在Vue.js模板中添加前缀 `v-` 使用 如 `<div v-my-directive="someValue">`

二、指令实例属性(2.x更新了此属性)

属性 说明
el 指令绑定的元素
vnode Vue 编译生成的虚拟节点。
oldVnode 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
binding 一个对象,包含以下属性
expression 指令的表达式,不包括参数和过滤器
arg 指令的参数
value 指令的绑定值,例如:v-my-directive=”1 + 1” 中,绑定值为 2。
oldValue 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
name 指令的名字,不包含前缀
modifiers 一个对象,包含指令的修饰符
以上属性视为只读
不同于 Vue 1.x,所有的挂载元素会被 Vue 生成的 DOM 替换。因此不推荐挂载root实例到 `<html>` 或者 `<body>` 上。

**Vue去掉警告 You are running Vue in development mode**
这样解决:  

`Vue.config.productionTip = false`

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
<body>
<div id="example" @click='up' style="height: 500px; width: 100%; background: #CC0000">
<div id="demo" v-demo:hello.a.b="message"></div>
</div>
<script>
Vue.config.productionTip = false;
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})

new Vue({
el: '#example',
data: {
message: 'hello!'
}
})
</script>
</body>

三、对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法类型的 JavaScript 表达式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="demo" v-demo="{color: 'write', text: 'Hello!'}" ></div>
<script>
//此处Vue.js v2.0进行了修改使用binding
Vue.directive('demo', function(el, binding){
console.log(binding.value);
console.log(binding.value.color); //=>write
console.log(binding.value.text); //=>Hello!
})

var demo = new Vue({
el: '#demo'
})

</script>

四、字面修饰符
当指令使用了字面修饰符时,他的值将按普通字符串处理并传递给update方法。update方法将只调用一次,因为普通字符串不能相应数据变化。

五、元素指令(Vue.js V2.0已移除)
有时我们想以自定义元素的形式使用指令,而不是以属性的形式。

高级选项

Vue.js允许注册自定义指令。

params

自定义指令可以接受一个params数组,制定一个特性列表,Vue编辑器将自动提取绑定元素的这些特性。(之后补充例子)

deep

自定义指令使用在一个对象上,当对象内部属性变化时要触发update,则在指令定义对象中指定deep: true
注意监听数组的变动不需要这么做。(之后补充例子)

第4章 计算属性

什么是计算属性

当其依赖属性的值发生变化时,这个属性的值会自动更新,与之相关的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
<body>
<div id="example">
<input type="text" v-model="didi" />
<input type="text" v-model="family" />
<br>
didi = {{didi}}, family = {{family}}, didiFamily = {{didiFamily}}
</div>
<script>
var vm = new Vue({
el: '#example',
data:{
didi: "Didi",
family: "Family"
},
computed:{
//一个计算属性的getter
didiFamily: function(){
//this 指向vm实例
return this.didi + this.family;
}
}
})
</script>
</body>

计算属性缓存