vue学习笔记

虽然本人更多从事的是java后端开发,但作为一名精神小伙,本就有着架构的梦想,所以一直希望自己前后端都要有所涉猎,于是开始学习Vue框架作为拓展前端道路的试水区。

一、简介

官网https://cn.vuejs.org

1. 概念

  • Vue.js是一套构建用户界面的渐进式框架。Vue只关注视图层, 采用自底向上增量开发的设计。Vue 的目标是通过尽可能简单的 API实现响应的数据绑定和组合的视图组件。简单的理解:Vue就是和jQuery类似但更强的一个前端框架,它的中心思想就是数据驱动。而jQuery是结构驱动的,具体来说jQuery不算框架,而是js库。

  • Vue.js 是目前最火的一个前端框架,React是最流行的一个前端框架(React除了开发网站,还可以开发手机AppVue语法也是可以用于进行手机App开发的,需要借助于Weex

  • Vue.js 是前端的主流框架之一,和Angular.jsReact.js 一起,并成为前端三大主流框架!

  • Vue.js 是一套构建用户界面的框架,只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。(Vue有配套的第三方类库,可以整合起来做大型项目的开发)

2. 框架和库的区别

  • 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目,虽然有这个缺点,但是功能完善。

  • 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。比如从Jquery 切换到Zepto,又比如从 EJS 切换到 art-template

3. 为什么要学习前端框架

  • 提高开发效率。提高开发效率的发展历程:原生JS -> Jquery之类的类库 -> 前端模板引擎 -> Angular.js/ Vue.js/React.js(能够帮助我们减少不必要的DOM操作;提高渲染效率;双向数据绑定的概念【通过框架提供的指令,我们前端程序员只需要关心数据的业务逻辑,不再关心DOM是如何渲染的了】)

  • 减少少DOM操作。在Vue中,一个核心的概念,就是让用户不再操作DOM元素,解放了用户的双手,让程序员可以更多的时间去关注业务逻辑。

4. 前端的MVVM

为了维护和管理前端开发,前端开发一般还要MVVM的分层开发模式。不要理解成MVCMVC 是后端的分层开发概念。而MVVM是前端视图层的概念,主要关注于视图层分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View , VM (即ViewModel)。

mmvm

二、安装

1. <script> 标签引入vue.js文件

1
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

例如:

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>VueJS Tutorials</title>
<link href="styles.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>

</body>
</html>

2. 使用NPM工具构建

1
2
# 最新稳定版
$ npm install vue

三、 hello world

app.js

1
2
3
4
5
6
7
new Vue({  //引入vue包后,浏览器的内存中就多了一个Vue的构造函数,只需要new Vue,就能实例化出Vue对象
el: '#vue-app', //el(即elemet): 挂载点,需要绑定的vue根容器(根元素),一切的vue相关操作都在这个元素内进行。元素外不起作用。
data: { //data:数据选项,用于数据的存储,存放key/value。data就是mvvm中的model
username: 'qcmoke', //只需要在元素标签中使用表达式{{key}}或者v-text等插值表达式就能显示key对应的值,省略了麻烦的dom操作
msg: 'hello world !'
}
});

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script><!--引入vue.js-->
</head>
<body>
<div id="vue-app"> <!-- vue根容器(根元素) -->
<h1>Hey, {{ username }}</h1><!--根据data中的key使用模版语法{{}}取出值,vue将{{}}里的内容放到虚拟dom里,再通过虚拟dom将该内容放回真实dom的相关元素里-->
<h1>{{ msg }}</h1>
</div>
</body>

<script src="app.js"></script><!--引入app.js,app.js存储vue对象等相关业务代码-->
</html>

1557198901438

四、数据显示

1. 显示文本内容

1.1 插值表达式

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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<style>
[v-cloak] {
display: none;
}
</style>
</head>

<body>
<div id="vue-app">
<!-- 使用v-cloak结合css样式能够解决插值表达式闪烁的问题 -->
<h1 v-cloak>Hey, {{ username }}</h1>
<h1 v-cloak>{{ msg }}</h1>
</div>
</body>

<script>
new Vue({
el: '#vue-app',
data: {
username: 'qcmoke',
msg: 'hello world !'
}
});
</script>

</html>

解决使用插值表达式显示data数据出现闪烁的问题。步骤是,在有插值表达式内容的标签里添加v-cloak属性,然后添加如下css样式表即可解决。

1
2
3
4
5
<style>
[v-cloak]{
display: none;
}
</style>

1.2 v-text

与插值表达式功能是一样的。

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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>v-text</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<h1 v-text="username"></h1>
<h1 v-text="msg"></h1>
<!--
<h1>Hey, {{ username }}</h1>
<h1>{{ msg }}</h1>
-->

</div>
</body>
<script>
new Vue({
el: '#vue-app',
data: {
username: 'qcmoke',
msg: 'hello world !'
}
});
</script>

</html>

与插值表达式不同的是不会出现插值表达式的闪烁的问题。原因是v-text会覆盖元素中原本的内容,但是 插值表达式 只会替换自己的这个占位符,不会把 整个元素的内容清空。

如何选择插值表达式和v-text?

如果内容含有data没有的一些字符,那么建议使用插值表达式结合v-cloak属性使用。

如果内容只有data里的数据,那么建议使用v-cloak

2. 显示html元素

2.1 v-html

作用:用于输出data中的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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>v-html</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<h1 v-html="msg_el"></h1>
</div>
</body>
<script>
new Vue({
el: '#vue-app',
data: {
msg_el: '<h1 style="color: red">hello world !</h1>'
}
});
</script>

</html>

使用v-text或者插值表达式只能显示纯文本内容

1557209682585

五、属性数据绑定

1. 单向数据绑定 v-bind

  • 作用:用于给html元素的属性绑定数据
  • 缩写: :
  • 实现步骤:在原来属性的值里写vuedatakey,并在原属性前添加"v-bind:",以此来给属性绑定vue的数据。
  • 数据绑定方式:单向数据绑定,即从model自动绑定到viewview上绑定的属性数据(值)会随着model值的改变而改变,但是view中绑定的属性数据(值)的改变不会改变model中属性的数据(值)。
  • 绑定方向:model---->view
  • 作用范围:所有标签元素。
  • vue会将元素中属性绑定的key当作是js表达式返回,所以可以进行合法的运算操作。
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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>v-bind</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<!-- 在原来属性的值里写vue中data的key,并在原属性前添加"v-bind:",以此来给属性绑定vue的数据 -->
<a v-bind:href="vue_url">vue的官网链接</a>
<br />

<!-- vue会将元素中属性绑定的key当作是js表达式返回,所以可以进行合法的运算操作 -->
<a v-bind:href="vue_url+'/v2/guide/'">vue官方文档链接</a>
<!--
v-bind
作用:用于给html元素的属性绑定数据
-->

</div>
</body>
<script>
new Vue({
el: '#vue-app',
data: {
vue_url: 'https://cn.vuejs.org'
}
});
</script>

</html>

1557210726080

2. 双向数据绑定 v-model

  • 作用:用于给html元素的属性绑定数据
  • 缩写: :
  • 实现步骤:在需要表单元素里添加v-model="data找那个的key"即可实现双向数据绑定。
  • 数据绑定方式:双向数据绑定,即从modelview数据互相绑定,view上绑定的属性数据(值)会随着model值的改变而改变,并且view中绑定的属性数据(值)的改变也会改变model中属性的数据(值)。
  • 绑定方向:model<---->view
  • 双向数据绑定不可以进行表达式运算操作。
  • 作用范围:v-model只能使用在表单元素中,如input(radio, text, address, email....)select checkboxtextarea等。

测试单向数据绑定和双向数据绑定的区别

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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>v-bind</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
单向数据绑定:<input type="text" v-bind:value="key1">
<br><br>
双向数据绑定:<input type="text" v-model="key2">
</div>
</body>
<script>
var vm = new Vue({
el: '#vue-app',
data: {
key1: 'value of key1',
key2: 'value of key2'
}
});
</script>

</html>

model—>view方向数据变化情况(通过浏览器的控制台操作内存中的vue对象即可改变model中的数据)

model数据未改变时:

1557249199997

model数据改变时:

1557249327836

view—>model方向数据变化情况

input(view)不改变值时的情况:

1557248526679

input(view)改变值时的情况:

1557248693289

从以上两个方向数据的改变即可看出单向数据绑定和双向数据绑定的差异。

六、事件绑定

1. v-on

作用:事件绑定。

缩写: @

步骤:在原来的事件属性前添加“v-on:”,并给事件属性赋vuedata key。,最后在vue对象的methods属性里添加key对应的方法。

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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>v-on</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<button v-on:click="show">点击按钮</button>
<!--
v-on
作用:事件绑定。
步骤:在原来的事件属性前添加“v-on:”,并给事件属性赋vue的data key。,最后在vue对象的methods属性里添加key对应的方法。
-->
</div>
</body>
<script>
new Vue({
el: '#vue-app', //el属性定义vue的控制区域
data: { //data属性定义所有vue数据
vue_url: 'https://cn.vuejs.org'
},
methods: { //methods定义所有vue可用的方法
show: function () {
alert("hello Vue !");
}
}
});
</script>

</html>

1557212657868

2. 事件修饰符

  • .stop 阻止冒泡

    冒泡:在多个绑定有事件的元素嵌套中。当触发一个元素时,伴随着嵌套的元素也会触发事件。

  • .prevent 阻止默认事件

  • .capture 添加事件侦听器时使用事件捕获模式

  • .self 只当事件在该元素本身触发时触发回

  • .once 事件只触发一次

2.1 阻止冒泡.stop

(冒泡的情况)

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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>事件修饰符</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<div @click="divHandle">
<!-- 使用v-on缩写的方式指定vue事件绑定 -->
<button @click="buttonHandle">点击按钮</button>
</div>
</div>
</body>
<script>
new Vue({
el: '#vue-app', //el属性定义vue的控制区域
data: { //data属性定义所有vue数据
vue_url: 'https://cn.vuejs.org'
},
methods: { //methods定义所有vue可用的方法
divHandle: function () {
console.info("hello div !");
},
buttonHandle() {
console.info("hello button !");
}
}
});
</script>

</html>

1557214731016

(阻止冒泡的情况)

在需要阻止冒泡的的元素vue事件属性后添加.stop

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>

<head>
<meta charset="utf-8">
<title>事件修饰符</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<div @click="divHandler">
<!-- 使用v-on缩写的方式指定vue事件绑定
使用.stop阻止父元素事件(在当前元素发生事件后就停止了,没有继续冒泡下去)
-->
<button @click.stop="buttonHandler">点击按钮</button>
</div>
</div>
</body>
<script>
new Vue({
el: '#vue-app', //el属性定义vue的控制区域
data: { //data属性定义所有vue数据
vue_url: 'https://cn.vuejs.org'
},
methods: { //methods定义所有vue可用的方法
divHandler: function () {
console.info("hello div !");
},
buttonHandler() {
console.info("hello button !");
}
}
});
</script>

</html>

1557215907917

2.2 阻止默认事件.prevent

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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>事件修饰符</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<!-- 使用.prevent事件修饰符阻止a标签的默认跳转事件 -->
<a :href="vue_url" @click.prevent="linkHandler">点击链接</a>

</div>
</body>
<script>
new Vue({
el: '#vue-app', //el属性定义vue的控制区域
data: { //data属性定义所有vue数据
vue_url: 'https://cn.vuejs.org'
},
methods: { //methods定义所有vue可用的方法
linkHandler() {
console.info("触发链接点击事件!");
}
}
});
</script>

</html>

1557216567887

2.3 添加事件捕获 .capture

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
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>事件修饰符</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
<div id="vue-app">
<!--
事件捕获
即是给元素添加一个监听器,当元素发生冒泡时,先触发带有该修饰符的元素。若有多个该修饰符,则由外而内触发。 就是谁有该事件修饰符,就先触发谁。
在嵌套的事件元素组中,默认事件是从里往外触发的,如果希望从外往里触发,可以在外元素的vue事件后添加.capture修饰符即可完成。

-->
<div @click.capture="divHandler" style="width: 100px; height: 100px; background: gray;">
<button @click="buttonHandler">点击按钮</button>
</div>
</div>
</body>
<script>
new Vue({
el: '#vue-app', //el属性定义vue的控制区域
data: { //data属性定义所有vue数据
vue_url: 'https://cn.vuejs.org'
},
methods: { //methods定义所有vue可用的方法
divHandler: function () {
console.info("hello div !");
},
buttonHandler() {
conso