一、Vue.js 的基本认识

1、简介

渐进式 JavaScript 框架(核心 + 扩展)

作用:动态构建用户界面

2、优点

更高的运行效率:基于虚拟 dom

双向数据绑定:不操作 dom,关注业务逻辑

二、渐进式框架

简而言之,可以选择性的使用该框架的一个或一些组件,这些组件的使用也不需要将框架全部组件都应用。而且用了这些组件也不要求你的系统全部都使用该框架。

结合实际使用场景说明。

场景 1

如果你的技术团队技术选型比较保守,没有新技术的使用场景,比如让你去维护一个管理后台。管理后台,日常就是提交各种表单了,这部分现有的方案,比如 form 表单提交或者 jquery 收集信息 ajax 提交。这时候你可以把 vue 当成一个 js 库来使用,就用来收集 form 表单,和表单验证。

场景 2

在场景 1 中,你尝到了甜头。心中暗爽,还可以这么玩嘞。独乐乐不如众乐乐和大家分享之后,团队开始接受使用 vue,小规模推广起来。打怪升级该遇小 boss 啦,领导说,小伙后台做的越来越有效率了,来承担些常规业务开发,来正规军编制和其他小伙伴一起做新闻列表和新闻详情页吧。
在这个项目中,你跟大胆一点把 整个页面的 dom 用 Vue 来管理,你发现 jquery 没什么用了,列表用 v-for 来循环,把评论抽成小组件了。 评论交互比较复杂,但是你的关注点把原来 jquery dom 操作变成了关注数据的变化,用数据驱动 DOM 的变化。

场景 3

经历了场景 1 场景 2,越来越受大家信赖,领导又找你了。你看新闻项目你做的不错,移动站也得重构了,你做个移动端 m 站吧,正好微信和 App 分享出去用到。这时候,你需要在做移动端 webapp 了。 于是你由去了解 webpack vue-router,你发现前端 可以控制路由了。webpack,可以用于前端开发的工程构建。

场景 4

场景 3 之后你在技术团队大放异彩,公司越来越器重你。年末领导又来找你了,小伙砸,想不想拿年终奖啊,想的话给我做个新闻直播间吧。需求特别简单:就是滚动播报新闻,用户实时参与评论。有了场景 3 和之前的经验,发现稍微有点力不从心了,你和后端的接口沟通上越来越频繁,新闻直播间需要大量的数据在组件中共享数据,后来你发现了,vuex 处理数据在组件之间的流动得心应手。

场景 5

年终奖,拿到手了,过年回来升职加薪。带了 20 人的前端团队,你的精力开始在配合公司其他部门做用户数据增长了。发现场景 2 中你犯了个错误,虽然整个页面用 Vue 管理 开发起来很方便,但是页面白屏时间长,而且类似这样的底层页对 seo 都不好。开始考虑使用 vue2.0 的 SSR。为了保障团队高质量的输出,你开始研究如何给 vm 写单测…

场景 1-5 从最初的只因多看你一眼而用了前端 js 库,一直到最后的大型项目解决方案。

所以说 vue 是The Progressive JavaScript Framework

三、vue:虚拟 dom 的实现

Vitual DOM是一种虚拟dom技术,本质上是基于javascript实现的,相对于dom对象,javascript对象更简单,处理速度更快,dom树的结构,属性信息都可以很容易的用javascript对象来表示:

1
2
3
4
5
6
7
8
9
10
11
let element={
tagName:'ul',//节点标签名
props:{//dom的属性,用一个对象存储键值对
id:'list'
},
children:[//该节点的子节点
{tagName:'li',props:{class:'item'},children:['aa']},
{tagName:'li',props:{class:'item'},children:['bb']},
{tagName:'li',props:{class:'item'},children:['cc']}
]
}

对应的 html 写法

1
2
3
4
5
<ul id="list">
<li class="item">aa</li>
<li class="item">aa</li>
<li class="item">aa</li>
</ul>

Virtual DOM并没有完全实现DOMVirtual DOM最主要的还是保留了Element之间的层次关系和一些基本属性. 你给我一个数据,我根据这个数据生成一个全新的Virtual DOM,然后跟我上一次生成的Virtual DOMdiff,得到一个Patch,然后把这个Patch打到浏览器的DOM上去。

我们可以通过javascript对象表示的树结构来构建一棵真正的dom树,当数据状态发生变化时,可以直接修改这个javascript对象,接着对比修改后的javascript对象,记录下需要对页面做的dom操作,然后将其应用到真正的dom树,实现视图的更新,这个过程就是Virtual DOM的核心思想。

四、理解 MVVM

1、安装 Vue.js devtools

Vue 开发工具 vuejs-devtools

谷歌浏览器安装 Vue.js devtools:下载地址

浏览器 F12 找到 VUE

2、MVVM

五、Vue 应用

1、数据绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>
<!-- id标识vue作用的范围,绑定的数据必须写在这个div内部 -->
<div id="app">
<!-- {{}} 插值表达式,声明式渲染,绑定vue中的data数据 -->
{{ message }}
</div>

<script src="vue.js"></script>
<script>
// 创建一个vue对象
// Vue构造函数的参数是一个配置对象,对象中的key是一些固定的关键字
new Vue({
el: '#app', // 使用css3选择器语法,指定 element 元素
data: {
//在data中注册变量,用于视图中的数据绑定
message: 'Hello Vue!',
},
})
</script>
</body>

这就是声明式渲染:Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统

2、数据绑定指令

1
2
3
4
<!--  v-bind:value 单向数据绑定  -->
<input type="text" v-bind:value="company" />
<!-- v-model 双向数据绑定 -->
<input type="text" v-model="company" />

v-bind: 指令的简写形式

1
2
3
<!-- v-bind: 指令的简写形式 : -->
<a :href="site" target="_blank">{{company}}</a>
<input type="text" :value="company" />

3、绑定事件监听

使用 v-on 进行事件绑定,v-on:click 表示处理鼠标点击事件,事件调用的方法定义在 vue 对象声明的 methods 节点中

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
<body>
<div id="app">
<!-- v-on:click 表示处理鼠标点击事件 -->
<button v-on:click="helloWorld">输出helloWorld</button>
<!-- 也可以加上圆括号,来传自定义参数 -->
<button v-on:click="hello('Vue')">输出hello Vue</button>
<!-- 简写:使用 @ 来代替 v-on: -->
<button @click="browse">浏览器访问</button>
</div>

<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
url: 'https://www.baidu.com',
},

methods: {
helloWorld() {
alert('hello world')
},
// 接收传递参数
hello(name) {
alert('hello ' + name)
},
browse() {
alert('浏览器访问' + this.url)
},
},
})
</script>
</body>

4、计算属性

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
<body>
<script src="vue.js"></script>

<div id="app">
<!-- 实现字符串的反转 -->
<!-- split('')使用空字符串分割 -->
<!-- reverse()实现反转 -->
<!-- join()实现拼接 -->
<!-- 缺点:大量的业务逻辑写在了视图中,页面代码不简洁 -->
<p>{{message.split('').reverse().join('')}}</p>

<!-- 使用方法来实现翻转 -->
<!-- 缺点:多次翻转需要多次调用 -->
<p>方法:{{reversed()}}</p>
<p>方法:{{reversed()}}</p>
<p>方法:{{reversed()}}</p>

<!-- 使用计算属性 -->
<!-- 计算的数据会被缓存,计算属性只会执行一次 -->
<p>计算属性:{{reversedMessage}}</p>
<p>计算属性:{{reversedMessage}}</p>
<p>计算属性:{{reversedMessage}}</p>
</div>

<script>
new Vue({
el: '#app', // 使用css3选择器语法,指定 element 元素

data() {
return {
message: 'hello',
}
},

// 使用方法来实现翻转
methods: {
reversed() {
console.log('方法被调用')
return this.message.split('').reverse().join('')
},
},

// 使用计算属性,里面需要通过方法来写逻辑
// 关键字computed
computed: {
reversedMessage() {
console.log('计算属性执行')
return this.message.split('').reverse().join('')
},
},
})
</script>
</body>

5、监视

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
<body>
<div id="app">
姓: <input placeholder="First Name" v-model="firstName" /><br />
名: <input placeholder="Last Name" v-model="lastName" /><br />
姓名: <input placeholder="Full Name" v-model="fullName" /><br />
</div>

<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
firstName: 'Helen',
lastName: 'Yao',
},

watch: {
//当firstName改变时自动调用
firstName(value) {
console.log('watch firstName')
this.fullName = value + ' ' + this.lastName
console.log(this.fullName)
},

//当lastName改变时自动调用
lastName(value) {
console.log('watch lastName')
this.fullName = this.firstName + ' ' + value
},
},
})
</script>
</body>

6、条件渲染

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>
<script src="vue.js"></script>
<div id="app">
<input type="checkbox" v-model="ok" />同意许可协议
</br>

<!-- v:if条件指令:还有v-else、v-else-if 切换时开销大,耗费性能 -->
<!-- 原理:删除节点,创建节点,耗费性能,占用内存少 -->
<!-- 适用于展示内容特别多的,很少切换的,这样占用内存少 -->
<button v-if="ok">if:下一步</button>
<button v-else disabled>else:下一步</button>

<!-- v:show 条件指令 初始渲染开销大 -->
<!-- 原理:隐藏节点,显示节点,耗费内存 -->
<button v-show="ok">show:下一步</button>
<button v-show="!ok" disabled>show:下一步</button>
</div>

<script>
new Vue({
el: '#app',
data: {
ok: false, //是否同意许可协议
},
})
</script>
</body>

7、实例生命周期

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
<body>
<div id="app">
<h3 id="h3">{{ message }}</h3>
</div>

<script src="vue.js"></script>

<script>
new Vue({
el: '#app',
data: {
message: '床前明月光',
},
// 页面在内存中已经初始化完毕:
// 可以操作 data 中的数据、调用methods中的方法
// 但是数据尚未被渲染到页面中:用户看不见
created() {
console.log('created')
//可以操作 data 中的数据
console.log(this.message)
//可以调用methods中的方法
this.show()
//无法取出dom节点取数据,说明用户无法在浏览器中看见这个内容
console.log(document.getElementById('h3').innerText)
},

// 数据已经被渲染到页面中
mounted() {
// 第四个被执行的钩子方法
console.log('mounted')
//可以取出dom节点取数据,说明用户已经在浏览器中看见内容
console.log(document.getElementById('h3').innerText)
},

methods: {
show() {
console.log('show方法被调用')
},
},
})
</script>
</body>

结果