前言

本篇将记录我的Vue的学习,有些可能会较为简略

部分内容参考菜鸟教程Vue.js 入门教程 | 菜鸟教程 (runoob.com)和Vue的官方文档介绍 | Vue.js (vuejs.org),另外参考书籍梁灏,Vue.js实战[M] 北京:清华大学出版社,2017

注:由于个人能力有限,暂不会在Markdown中使用Vue相关内容

所以另外写了一个网页,作为效果参考。链接如下

https://www.226yzy.com/demos/VueDemo/

入门-Hello World

新的学习从Hello World开始🤣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
</head>
<body>
<div id="app">
<div>{{ message }}</div>
</div>
<script src="https://npm.elemecdn.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello World'
}
})
</script>
</body>
</html>

没有下载好的Vue.js,可以通过script加载CDN文件,引入最新稳定版本的Vue.js框架 。有的话,可以将路径修改为你自己下载好的Vue.js的相对路径

1
<script src="https://npm.elemecdn.com/vue/dist/vue.js"></script>

Vue实例与数据绑定

实例与数据

Vue.js应用创建是通过构造函数Vue就可以创建一个Vue的根实例并启动Vue应用

1
2
3
var app = new Vue({
// 选项
})

上面的变量app代表了这个实例

然后,一个必不可少的选项就是el

el用于指定一个页面中已存在的DOM元素来挂载Vue实例

1
2
3
4
5
6
<div id="app"></div>
<script>
new Vue({
el: '#app'
})
</script>

v-model

是 vue 的双向绑定的指令,能将页面上控件输入的值同步更新到相关绑定的data属性,也会在更新data绑定属性时候,更新页面上输入控件的值。

比如

1
2
3
4
5
6
7
8
9
10
11
12
<div id="app-0">
<input v-model="value">
{{value}}
</div>
<script>
new Vue({
el: '#app-0',
data: {
value: 100,
}
})
</script>

v-model帮我们做的事就是,为inputvalue 值设置一个动态绑定,然后在输入框的 input事件触发后实时修改动态绑定的 value 的变量值。

插值与表达式

这里HEXO渲染有点小问题

使用双大括号{{}}`是最基本的文本插值方法,它会自动将我们双向绑定的数据实时显示出来 例子见前面的HelloWorld ### v-text和v-html - `v-text`:将数据输出到元素内部,如果输出的数据有HTML代码,会作为普通文本输出 - `v-html`:将数据输出到元素内部,如果输出的数据有HTML代码,会被渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="app-0-0">
v-text: <span v-text="value"></span>
<br>
v-html: <span v-html="value"></span>
</div>
<script>
new Vue({
el: '#app-0-0',
data: {
value: '<a href="#">这是一个链接</a>',
}
})
</script>
### v-pre 如果想显示`{{}}标签而不进行替换,使用v-pre即可跳过这个元素和他的子元素的编译过程

1
2
3
4
5
6
7
8
<div id="app-0-1">
<span v-pre>{{这里的内容不会被编译}}</span>
</div>
<script>
new Vue({
el: '#app-0-1',
})
</script>

条件语句

v-if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app-1">
<p v-if="aa">我是aa</p>
<p v-if="bb">我是bb</p>
</div>

<script>
new Vue({
el: '#app-1',
data: {
aa: true,
bb: false
}
})
</script>

v-else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app-2">
<div v-if="aa>bb">
aa大于bb
</div>
<div v-else>
aa小于bb
</div>
</div>

<script>
new Vue({
el: '#app-2',
data: {
aa: 0,
bb: 1
}
})
</script>

v-else-if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="app-3">
<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>
</div>

<script>
new Vue({
el: '#app-3',
data: {
type: 'C'
}
})
</script>

v-show

功能与v-if一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app-4">
<p v-show="aa">我是aa</p>
<p v-show="bb">我是bb</p>
</div>

<script>
new Vue({
el: '#app-4',
data: {
aa: true,
bb: false
}
})
</script>

v-if与v-show 的异同

  • 相同点

都控制所在标签是否显示

用法上也是相同的

  • 不同点

v-if在值为true时,创建所在的内容并显示,否则,不创建标签

v-show在页面加载是全部创建,只有当值为true时显示,否则隐藏

梁灏,Vue.js实战[M] 北京:清华大学出版社,2017的P36-37是这样描述的:

v-if是真正的条件渲染,它会根据表达式适当地销毁或重建元素及绑定的事件或子组件。若表达式初始值为false,则一开始元素/组件并不会渲染,只有当条件第一次变为真时才开始编译。

v-show只是简单的CSS属性切换,无论条件真与否,都会被编译。

v-if与v-show 的选择

相比之下

v-if更适合条件不经常变换的场景,因为它切换开销相对比较大

v-show适用于频繁切换条件

更多参考

面试官:v-show和v-if有什么区别?使用场景分别是什么? | web前端面试 - 面试官系列 (vue3js.cn)

循环语句

循环使用 v-for 指令。

v-for指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。

v-for 可以绑定数据到数组来渲染一个列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="app-5">
<li v-for="site in sites">
{{ site.name }}
</li>
</div>

<script>
new Vue({
el: '#app-5',
data: {
sites: [{
name: 'Runoob'
},
{
name: 'Google'
},
{
name: 'Taobao'
}
]
}
})
</script>

指令与事件

指令是Vue.js模板中最常用的一项功能,它带有前缀v-,在前文中已经介绍、使用了不少指令了。指令的主要职责是当其表达式的值改变时,相应地将某些行为应用到DOM上。

v-bind

v-bind的基本用途是动态更新HTML元素上的属性,比如id、class、href、src等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app-6">
<a v-bind:href="url">我的博客首页链接</a>
<p v-bind:style="style">我是蓝控,这是蓝色的!</p>
</div>

<script>
new Vue({
el: '#app-6',
data: {
url: 'https://www.226yzy.com',
style: 'color:#49B1F5'
}
})
</script>

v-on

v-on用来绑定事件监听器

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="app-7">
<p v-if="show">这是一段可隐藏的文本</p>
<button v-on:click="show=false">点击隐藏</button>
</div>

<script>
new Vue({
el: '#app-7',
data: {
show: true
}
})
</script>

button按钮上,使用v-on:click给该元素绑定另一个点击事件

在普通元素上,v-on可以监听原生DOM事件,除click外,还有dblclickkeyupmousemove等。

methods方法

写到下文计算属性的时候发现这个还没写过,所以就在这引用Vue中文文档中的例子了🤣正好,也有涉及上面的v-on

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app-7-1">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转消息</button>
</div>

<script>
new Vue({
el: '#app-7-1',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
</script>

语法糖

语法糖是指在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发。

Vue.js中的v-bindv-on指令都提供了语法糖,也可以说是缩写

  • v-bind

    可以缩写成一个冒号

    例如

    1
    2
    3
    <a v-bind:href="url">我的博客首页链接</a>
    <!--可缩写为-->
    <a :href="url">我的博客首页链接</a>
  • v-on
    可以缩写成@

    例如

    1
    2
    3
    <button v-on:click="show=false">点击隐藏</button>
    <!--可缩写为-->
    <button @click="show=false">点击隐藏</button>

计算属性

Vue中文文档说:设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app-8">
<p>倒转前: "{{ message }}"</p>
<p>倒转后: "{{ reversedMessage }}"</p>
</div>

<script>
var vm = new Vue({
el: '#app-8',
data: {
message: 'Hello'
},
computed: {
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
});
</script>

所以,对于任何复杂逻辑,你都应当使用计算属性

计算属性缓存 vs 方法

引自https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7%E7%BC%93%E5%AD%98-vs-%E6%96%B9%E6%B3%95

我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

函数与计算属性异同

相同点

都可以进行计算

不同点

  • 受计算属性有缓存,所以计算属性效率较高于函数

  • 范围不一样。函数不仅可以用于计算,还可以用于其他场合,计算属性仅用于计算场合

  • 在基本绑定中的调用形式不同,函数方法要带(),计算属性不用

  • 计算属性可以侦听,函数不能

计算属性的 setter

引自https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7%E7%9A%84-setter

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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]
}
}
}
// ...

现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstNamevm.lastName 也会相应地被更新。

监听属性

我们可以通过 watch 来响应数据的变化。

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
<div id="app-9">
千米 : <input type="text" v-model="kilometers">
米 : <input type="text" v-model="meters">
</div>
<p id="info"></p>
<script type="text/javascript">
var app1 = new Vue({
el: '#app-9',
data: {
kilometers: 0,
meters: 0
},
watch: {
kilometers: function (val) {
this.kilometers = val;
this.meters = this.kilometers * 1000
},
meters: function (val) {
this.kilometers = val / 1000;
this.meters = val;
}
}
});
// $watch 是一个实例方法
app1.$watch('kilometers', function (newValue, oldValue) {
// 这个回调将在 app1.kilometers 改变后调用
document.getElementById("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
})
</script>

vm.$watch

上面用到了这个,我引用官方文档的内容来介绍API — Vue.js (vuejs.org)

vm.$watch( expOrFn, callback, [options] )

  • 参数

    • {string | Function} expOrFn

    • {Function | Object} callback

    • {Object} [options]
      
      • {boolean} deep
      • {boolean} immediate
  • 返回值{Function} unwatch

  • 用法

    观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。

    注意:在变更 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本。

参考文献

在线资源

菜鸟教程

Vue.js 入门教程 | 菜鸟教程 (runoob.com)

Vue官方中文文档

介绍 | Vue.js (vuejs.org)

其他博客

Vue快速入门_成都往右的博客-CSDN博客_vue入门

参考书籍

[1]梁灏,Vue.js实战[M] 北京:清华大学出版社,2017

其他

部分内容来自姚军老师的上课内容