视频地址:【尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通】 https://www.bilibili.com/video/BV1Zy4y1K7SH/?p=13&share_source=copy_web&vd_source=b1cb921b73fe3808550eaf2224d1c155
目录
1、Vue核心
1.1 Vue简介
Vue基础
Vue-cli 做工程开发
Vue-router 在Vue中实现前端入门
Vuex 保管数据
element-ui ui组件库
1.1.1 Vue简介
1.1.1.1 Vue是什么?
- Vue是一套用于构建用户界面的渐进式JavaScript框架
- 构建用户界面:提供数据,前端需要通过界面展示出来
- 渐进式:Vue可以自底向上逐层应用
- 简单应用:只需一个轻量小巧的核心库
- 复杂应用:可以引入各式各样的Vue插件
1.1.1.2 谁开发的?
后起之秀:创作者参考了react框架做出了Vue框架。
1.1.1.3 Vue的特点
- 采用组件化模式,提高代码复用率、且让代码更好维护
- 声明式编码,无需直接操作DOM,提高开发效率
- 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
虚拟DOM就是内存里的一组数据。
Diff算法:新的虚拟DOM与旧的虚拟DOM比较,此为Diff比较,如果新的虚拟DOM中有一部分与旧的虚拟DOM相同,那么相同的部分就会复用。只需要处理后来放进来的虚拟DOM。
1.1.1.4 学习Vue之前要掌握的JS基础知识
- ES6语法规范
- 解构赋值、模板字符串、箭头函数
- ES6模板化
- 默认baolu、分别baolu、统一baolu、import、isport
- 包管理器(会一个就行)
- npm、yarn、cnpm
- 原型、原型链
- 重点,一定要懂
- 数组常用方法
- 过滤数据,加工数组,筛选最值
- axios
- promise
1.1.2 Vue官网使用指南
vue3:简介 | Vue.js
教程和API是重要内容。
API:Vue字典。
风格指南:如何写出优雅的Vue代码
学习Vue的时候,在html页面中,引入vue.js,然后编写vue代码。以后在公司里干活,用高端平台-脚手架Vue-cli.
1.1.3 搭建Vue开发环境
1.1.3.1 引入Vue(引入开发版本Vue)
引入Vue后,多了一个Vue函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>初识Vue</title>
<!-- 引入vue -->
<script type="text/javascript" src="../js/vue.js"></script>
<!-- 多了vue函数 -->
</head>
<body></body>
</html>
1.1.3.2 安装Vue开发者调试工具
谷歌插件。 Vue Devtools。
1.1.3.3 关闭生产开发环境提示
<body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示
</script>
</body>
1.2 初识Vue
首先要准备好一个容器,为什么,因为使用Vue是用来构建界面的,对于Vue构建出来的界面,要摆在什么位置呢,所以得准备一个容器。
强制刷新:shift + 刷新
小常识。
1.2.1 Hello小案例
<body>
<!-- 初识Vue
1. 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象(这里的就是el和data
2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法({{name}})
3. root容器里的代码被称为【Vue模板】 -->
<div id="root">
<h1>hello, {{name}}!</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
// 创建vue实例
const x = new Vue({
el: "#root", // el用于指定当前Vue为哪个容器服务,值通常为css选择器字符串
// 如果是类选择器,那么即为【el:'.root'】
// 多组key-value之间使用逗号分隔
data: {
// data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象
name: "word",
},
});
</script>
</body>
总结
- 初识Vue
- 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象(这里的就是el和data
- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法({{name}})
- root容器里的代码被称为【Vue模板】
1.2.2. 分析Hello案例
注意区分 js表达式 和 js代码(语句)
1、表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
(1) a
(2) a+b
(3) demo(1)
(4) x===y?'a':'b' 三元表达式
js表达式:拿一个变量const x = 在左侧接,都能接到一个值。
2、js语句(代码)不生成值,只控制代码的走向
(1) if(){}
(2) for(){}
(3)
js表达式是一种特殊的js代码,或者是一种特殊的js语句
继续总结
- 初识Vue
- 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象(这里的就是el和data
- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法({{name}})
- root容器里的代码被称为【Vue模板】
- Vue实例和容器是一一对应的
- 真实开发中只有一个Vue实例,并且会配合着组件一起使用
- {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到 data中的所有属性
- 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新。
1.3 模板语法
模板的概念:root容器里的代码被称为【Vue模板】
有了模板也就要有模板语法。
目前只学了{{xxx}} 插值语法
- 模板语法
- 插值语法
- 功能:用于解析标签体内容
- 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
- 指令语法
- 功能:用于解析标签(包括标签属性、标签体内容、绑定事件) 功能强大
- 举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写 js表达式,且可以直接读取到data中的所有属性
- v-bind可以给标签里的任何属性去动态地绑定值
- 备注:vue中有很多的指令,且形式都是:v-????,vue里的指令都是v-开头,v-if,v-model
- 插值语法
何时使用插值语法,何时使用指令语法
- 插值语法往往用于指定【标签体】内容
- 指令语法管理【标签属性】
实践
1、首先引入vue
<title>模板语法</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
2、其次准备容器
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h1>插值语法</h1>
<h3>你好,{{name}}</h3>
<hr />
<h1>指令语法</h1>
<a v-bind:href="url">点我去百度</a>
<!-- v-bind:bind 绑定,v-bind就是vue里的指令 -->
<!-- 加上v-bind,那么"url"就会当做js表达式去执行 -->
<a :href="url2">点我去尚硅谷</a>
</div>
</body>
3、写vue部分的代码
<script type="text/javascript">
Vue.config.productionTip = false; // 阻止Vue在启动时生成生产提示
new Vue({
el: "#root",
data: {
name: "jack",
url: "http://www.baidu.com",
url2: "http://www.atguigu.com",
},
});
</script>
1.4 数据绑定
1.4.1 单向数据绑定
v-bind:单向数据绑定。数据只能从data流向页面。即数据变化,页面上的数据也随之变化。但是页面的数据改变了,vue函数里的对象data中的数据却不随之改变。
1.4.2 双向数据绑定
v-model:双向数据绑定。数据不仅能从data流向页面,还可以从页面流向data。即数据变化,页面上的数据也随之变化。页面的数据改变,data中的数据也随之改变。
不是所有的数据都适合v-model。
v-model只能应用在表单类元素(输入元素)上,h2等元素是不能用的。
输入类元素:input 单选框 多选框,select,多行输入等表单元素,共同点就是都有value属性。
v-model: value可以简写为v-model,因为v-model默认收集的就是value值。
代码实现:
单向数据绑定:<input type="text" v-bind:value="name">
双向数据绑定:<input type="text" v-model:value="name">
简写为
单向数据绑定:<input type="text" :value="name">
双向数据绑定:<input type="text" v-model="name">
1.5 el和data的两种写法
- el
- 写法1: 在new Vue的时候就指定el
- 写法2:之后指定
-
const v = new Vue ({ el:'#root', //第一种写法 data:{ name:'尚硅谷' } }) console.log(v) v.$mount('#root') //第二种写法
mount挂载
将容器里写的模板交给vue实例进行解析,解析之后将解析完的内容重新放到页面的指定位置,放官方叫挂载。mount就有挂载的意思。
- data的两种写法
- 写法1:对象式
- 写法2:函数式
- 使用:
data:{ // 对象式 name:'尚硅谷' } //函数式,函数必须返回一个对象 data: function () { return { name:'尚硅谷' } }
以后使用到组件,就必须使用data的函数式写法。
- 注意,data的函数式写法,普通函数,那么函数内部的this就是Vue实例对象
-
data: function () { console.log(this) // 此处的this为Vue实例对象 }
结果
-
- 而函数写为箭头函数,那么this就是window对象
- 代码
data: ()=> { console.log(this) // 此处的this为Vue实例对象 return { name: '尚硅谷' } }
- 结果
- 代码
另外,在一个对象里写函数,一般就删掉function和冒号,简化为
data() {
console.log(this) // 此处的this为Vue实例对象
return {
name: '尚硅谷'
}
}
总结:
- el
- new Vue时候配置el属性
- 创建Vue实例后,再通过v.$mount('#root')指定el的值
- data
- 对象式
- 函数式(学到组件后必须使用函数式,否则报错)
- 函数式普通函数的this是Vue实例对象
- 一个重要的原则:由Vue管理的函数,一定不要写为箭头函数,一旦写了箭头函数,this就不再是Vue实例了
- Vue管理的函数,data的函数式写法的函数,就是Vue管理的函数之一。
- 函数式普通函数可以简化掉function和冒号
1.6 MVVM模型 架构模型
Vue的设计者在最初设计Vue时,就参考了这个模型。
1.6.1 MVVM模型
- M: 模型 model 对应data中的数据
- V:视图View 模版
- VM:视图模型ViewModel,Vue实例对象
- 上图里的Data Bindlings,数据绑定,将数据放到指定的框里;
- DOM Listeners,DOM监听器,页面上的改变映射到数据上的改变。得时时刻刻监听页面有没有变化,并且将改变后的值传给数据。
MVVM模型在一堆数据和一堆DOM结构中间做了连接,它起到中间桥梁纽带作用。其实前端主流框架都是这个思想,数据放在要求的位置,然后写出模板代码,具体数据如何插入到模板中,就需要学习框架的语法,什么指令啊插值语法啊。然后框架开始工作,就可以将数据和模板建立起来连接。
ViewModel简称vm,vm是Vue实例对象。
因此以后用vm去接收Vue实例。
const vm = new Vue({
el: '#root', //第一种写法
data:{ // 对象式
name:'尚硅谷'
}
})
1.6.2 $emit
- vm本身有的属性,可以在模板中使用。
- 这里$开头的,包括name,以及下划线_开头的,都是vm的属性。
- 其实$emit是vm原型(object)的属性,vm也是可以使用的。
1.5.3 总结
- MVVM模型
- M: 模型 model 对应data中的数据
- V:视图View 模版
- VM:视图模型ViewModel,Vue实例对象
- vm属性
- data中所有的属性,都出现在了vm身上
- vm身上所有的属性,以及Vue原型上所有属性,在Vue模板中都可以直接使用
1.7 数据代理
1.7.1 Object.defineProperty()
1.7.1.1 函数定义
Object.defineProperty() 给对象定义属性(ES6)
举例
<script type="text/javascript">
let person = {
name: '张三',
gender: '男'
}
Object.defineProperty(person, 'age', {
value:18
})
console.log(person)
</script>
与下面的区别在哪呢
let person = {
name: '张三',
gender: '男',
age:'18'
}
注意,使用Object.defineProperty()添加的属性,是不可以被枚举(遍历)的。
Object.keys(对象名)以数组的形式返回对象所有属性的属性名,
1.使用创建对象的时候添加属性,其属性为
2.使用Object.defineProperty()添加属性,遍历不到Object.defineProperty()添加的age属性
此即为不可枚举(说白了就是不能遍历)。
当然使用for-in也可以证明Object.defineProperty() 添加的属性不可枚举
// 遍历person对象的所有属性值
for(let key in person) {
console.log(person[key],',')
}
1.7.1.2 枚举/修改/删除 的配置项
1.7.1.2.1 基本配置项
- 配置项
- enumerable:控制属性是否可以枚举,默认是false
- writable:控制属性是否可以被修改,默认是false
- configurable:控制属性是否可以被删除,默认是false
Object.defineProperty(person, 'age', {
value:18,
enumerable:true,
writable:true,
configurable:true
})
1.7.1.2.2 高级配置项
- 设置属性值为某个变量的值。
- 当读取age属性时,get函数(getter)就会被调用,且返回值就是age的值。
- 每一次访问age,都会触发getter的调用
let number = 19
Object.defineProperty(person, 'age', {
// 当读取age属性时,get就会被调用,且返回值就是age的值
get:function () {
return number
}
})
- 运行结果: 这里age是(...),提示invoke property getter,即调用函数getter。
- 这里get是属性名,属性值为一个函数,两个合在一起就是getter
同时还有set函数,当修改age属性时,set函数(setter)就会被调用,且参数是修改的值。
let number = 19
Object.defineProperty(person, 'age', {
// 当读取age属性时,get就会被调用,且返回值就是age的值
get:function () {
return number
}
set(value) {
number = value
}
})
1.7.2:数据代理
- 数据代理
- 通过一个对象 代理 对另一个对象中属性的操作(读/写)
- 例如,一个对象obj,其属性为x,读取x就是obj.x,修改就是obj.x = xxx;然后还有一个对象是obj2,想让obj2也访问到x,且能修改x。这就是通过一个对象obj2 代理 对另一个对象obj中属性x的读写操作。
- 代码实现,通过Object.deifneProperty()
- getter:return obj.x,以后有人通过obj2访问x的时候,其实是obj的x
- setter:如果以后setter被调用,即有人想修改obj2的x,那setter里就是要修改obj的x为value
-
let obj = {x:100} let obj2 = {y:1000} // 通过obj2读写obj的x Object.defineProperties(obj2, 'x', { // get() { return obj.x }, set(value) { obj.x = value } })
-
具体操作
- 通过一个对象 代理 对另一个对象中属性的操作(读/写)
1.7.3:Vue中的数据代理
案例
<div id="root">
<h2>学校名称: {{name}}</h2>
<h2>学校地址: {{address}}</h2>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:"尚硅谷",
address:"宏福科技园"
}
})
console.log(vm)
</script>
结果
可以看出,vm有对name和address的一组getter和setter。此即为数据代理。
通过vm读写name和address,就是读写data中的name和address,示意图如下。
数据代理图示
vm数据代理,方便编码。
- 总结
- Vue中的数据代理
- 通过vm对象来代理data对象中属性的操作(读/写)
- Vue中数据代理的好处
- 方便操作data中的数据
- 基本原理
- 通过Object.defineProperty()将data对象中所有属性添加到vm上
- 为每一个添加到vm上的属性,都指定一个getter/setter
- 在getter/setter内部去操作(读/写)data中对应的属性
- Vue中的数据代理
1.8 事件处理
<!-- 准备好一个容器 -->
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<button>点我提示信息</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue ({
el:'#root',
data:{
name:'尚硅谷'
}
})
</script>
1.8.1 事件的基本使用
- 要求:点击按钮,出现弹窗,“同学你好”
- 实现:
- 1 对按钮绑定点击事件,实现:在Vue中对元素绑定事件,用到指令,一定是v-xxx,该指令是v-on:click,意思是当元素被点击的时候,然后去执行一个回调函数
- 具体实现
<!-- 当点击button的时候,就去找名为showInfo的函数调用 --> <button v-on:click="showInfo">点我提示信息</button>
- 具体实现
- 2 实现showInfo函数
- 1 对按钮绑定点击事件,实现:在Vue中对元素绑定事件,用到指令,一定是v-xxx,该指令是v-on:click,意思是当元素被点击的时候,然后去执行一个回调函数
- 注意问题
- 问题1:showInfo可以有参数吗
- 可以,参数就是event,即事件对象。有target属性。
-
showInfo(event) { console.log(event.target.innerText) //点我提示信息 // alert("同学你好") }
- 问题2:showInfo()里的this是什么
- Vue实例对象,即vm。
- 注意:如果showInfo()写为箭头函数,此时函数内的this是window对象
- 建议:所有Vue管理的函数都写为普通函数
- 问题3:简写形式
- v-on:click="showInfo"→@click="showInfo"
- 问题4:函数传值
- div里
- Vue
showInfo2(number,event) { console.log(number) //点我提示信息 // alert("同学你好") }
- 问题1:showInfo可以有参数吗
总结:
- 使用v-on:xxx 或 @xxx 绑定事件,其实xxx是事件名
- 事件的回调需要配置在methods对象中,最终会在vm上;
- methods中配置的函数,不要用箭头函数,否则函数内的this就不是vm;
- methods中配置的函数,都是被Vue所管理的函数,this的执行是vm或组件实例对象;
- @click="demo" 和@click="demo($event)"效果一致,但后者可以传参。
1.8.2 事件修饰符
案例
<a href="http://www.atguigu.com" @click="showInfo">点我提示信息</a>
showInfo函数
methods: {
showInfo(e) {
e.preventDefault()
alert("同学你好")
}
}
因为点击的是a标签,在弹出弹框点击确定后,会跳转到href网址,因此在showInfo里添加e.preventDefault()可以阻止跳转。
方案2
也可以阻止这个默认事件。
此处@click后面的prevent就是事件修饰符。
- 总结
- 1 prevent:阻止默认事件(常用);
- 2 stop:阻止事件冒泡(常用);
- 3 once:事件只触发一次(常用);
- 4 capture:使用事件的捕获模式;
- 5 self:只有event.target是当前操作的元素时才触发事件;
- 6 passive:事件的默认行为立即执行,无需等待事件回调执行完毕。
p15 后面的没怎么听
1.8.3 键盘事件
- keydown,按下按键,不用抬起来就可以触发事件
- keyup,按下按键松手后触发事件,常用
案例
一个input框
<input type="text" placeholder="按下回车提示输入" @keyup="showInfo">
showInfo事件
showInfo(e) {
// 按下回车才打印输入的值,回车的keyCode是13
if(e.keyCode !== 13) return
console.log(e.target.value)
}
效果
只有按下回车才在控制台打印输入值,if(e.keyCode !== 13) return。
然后只需要在键盘事件后加一个修饰,就代表回车了。
- 总结:Vue常用的按键别名
- 回车 enter
- 删除 delete (捕获“退格” 和“删除”键)
- 退出 esc
- 空格 space
- 换行 tab
- 特殊,必须配合keydown
- 上 up
- 下 down
- 左 left
- 右 right
- Vue未提供别名的按键,可以使用按键原始的key值去绑定,但要注意要转为kebab-case(短横线命名)
- 键盘上的按键都有自己的名字和编码,比如回车,名字:Enter,编码:13
- 切换大小写的键,CabsLock,转为短横线为cabs-lock
- 系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)
- 配合keyup使用(@keyup-ctrl):按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发(即按下 ctrl后再按下随便一个y键,然后释放y键,此时事件才会被触发);
- 配合keydown使用:正常触发事件。
- 也可以使用keyCode去触发事件(不建议使用)
- Vue.config.keyCodes,自定义键名 = 编码,可以去定制按键名(不建议,一般提供的就够用了)。
1.8.4 事件总结
- 需要既阻止冒泡,又阻止默认行为,即需要两个修饰符
- @click.stop.prevent=“xxx”——先阻止冒泡,后阻止默认行为
- @click.prevent.stop=“xxx”——先阻止默认行为,后阻止冒泡
- 注意:上面两个的结果其实是一样的
- 1.6.3里说到ctrl必须和一个键连用,这里我要求必须是ctri+y,那么就写为@keyup.ctrl.y
1.9 计算属性与监视
1.9.1 姓名案例
1.9.1.1 插值语法实现
<!-- 准备一个容器 -->
<div id="root">
<span>姓<input type="text" v-model="firstName"></span>
<br/>
<br/>
<span>名<input type="text" v-model="lastName"></span>
<br/>
<br/>
<span>全名:{{firstName.slice(0,3)}}-{{lastName}}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data: {
firstName: '张',
lastName:'三'
}
})
</script>
效果
但是,这里对于firstName的截取,在{{}}内有点复杂了,下面用methods实现。
1.9.1.2 methods实现
data中的数据发生改变,那么Vue就会重新解析模板。
接下来就是计算属性,见1.7.2。
1.9.2 计算属性
- 计算属性
- 对data中已有的属性进行加工,得到的就是计算属性。
- 计算属性是vm的属性,所以可以写在{{}}内,使用插值语法读fullName。
- get什么时候被调用
- 1 初次读取fullName时
- 2 所依赖的数据发生变化时。例如,firstName发生变化,get就会被调用。
- 计算属性相比较methods而言,所依赖的数据不变化,多次访问只执行一次get,而methods是执行几次就调用几次methods。
计算属性的setter,可以不写,如果计算属性以后会被修改,那么加上setter
set(value) {
const arr=value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
计算属性总结:
- 定义:要用的属性不存在,要通过已有属性计算得来;
- 原理:底层借助了Object.defineProperty()提供的getter和setter。
- get函数什么时候被执行
- 1 初次读取时会被执行一次
- 当计算属性依赖的数据发生改变时会被再次调用
- 优势:与methods实现相比,计算属性内部有缓存机制(复用),效率更高,调试方便
- 备注
- 计算属性最终会出现在vm上,直接读取使用即可
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生变化。
1.9.3 计算属性_简写
- 什么时候可以简写
- 确定计算属性只有getter没有setter时。
完整形式
computed:{
// 完整形式
fullName:{
get(){
return this.firstName + '-' + this.lastName
},
set(value) {
const arr=value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
简写
如图所示,绿色其实就是getter。红色就是计算属性的名。
1.9.4 天气案例
代码
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changWeather">切换天气</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data: {
isHot: true
},
computed:{
info(){
return this.isHot?'炎热':'凉爽'
}
},
methods: {
changWeather() {
this.isHot = !this.isHot
}
}
})
</script>
结果
点击按钮,切换天气。
进一步简化代码,不用methods的函数了,直接在模板里面实现逻辑。因为切换天气,功能很单一,所以可以这样写。
1.9.5 监视属性 官网改名叫侦听属性
- 监视属性
- 监视某个属性的变化
- 写在watch里
- 当要监视的属性发生变化的时候,handler()就会被调用
- immediate为true,初始化时让handler调用一下
- 代码
watch: { isHot: { immediate: false, handler (newValue, oldValue) { } } }
- 是否可以监视计算属性呢?
- 可以,直接将isHot改为计算属性,比如info
- 配置的另外一种方法
- 创建完Vue实例以后,另外对vm设置监视
- 代码
vm.$watch('isHot', { handler (newValue, oldValue) { } })
- 监视属性总结
- 当被监视的属性变化时,回调函数(handler())自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视!
- 监视的两种写法
- 1 new Vue()时传入watch配置
- 2 通过vm.$watch监视
1.9.6 深度监视
跳过 p23
1.9.7 监视的简写形式
当watch配置项里只有handler()时才可以简写。
完整形式
watch: {
isHot: {
handler (newValue, oldValue) {
}
}
}
或者写法2
vm.$watch('isHot', {
handler (newValue, oldValue) {
}
})
简写形式
watch: {
isHot(newValue, oldValue) {
}
}
或者
vm.$watch('isHot', function (newValue, oldValue) {
})
- Vue管理的函数总结
- 配置在methods里的函数
- 计算属性里的getter和setter,包括简写形式的函数
- 监视属性里的handler(),以及简写形式的handler()
1.9.8 watch对比computed
p25 跳过。
将前面的姓名案例,用监视属性实现。
监视姓和名。
看了一半,没有记笔记。
1.10 class与style绑定
1.10.1 绑定class样式
- 绑定class样式
- 字符串写法
- 适用于样式的类名不确定,需要动态指定
- 字符串写法
<!-- 准备好一个容器 -->
<div id="root">
<!-- 加上冒号,那么a就会被解析,去Vue里找a的值 -->
<div class="basic" :class="mood" @click="changeMood">
{{name}}
</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data: {
name:'尚硅谷',
mood:'normal'
},
methods:{
changeMood() {
this.mood = 'happy'
}
}
})
</script>
解读
从上向下就是123
1 代码就是动态地指定class,class的值需要读取mood,mood在Vue里。点击事件触发后,mood的值会变为happy,即class会变为happy。
案例升级——mood随机
changeMood() {
// this.mood = 'happy'
const arr = ['happy', 'sad', 'normal']
const index = Math.floor(Math.random()) //生成[0,1)的随机数
this.mood = arr[index]
}
案例继续升级——添加多个类名
- 绑定class样式
- 数组写法
- 适用于要绑定的样式个数不确定,名字也不确定
- 数组写法
<div class="basic" :class="classArr" @click="changeMood">
{{name}}
</div>
new Vue({
el:'#root',
data: {
name:'尚硅谷',
mood:'normal',
classArr:['atguigu1', 'atguigu2','atguigu3']
},
案例继续升级——要添加的类名个数确定
- 绑定class样式
- 对象写法
- 适用于要绑定的样式个数确定,名字也确定,但要动态决定要不要某个样式
- 对象写法
<div class="basic" :class="classObj" @click="changeMood">
{{name}}
</div>
new Vue({
el:'#root',
data: {
name:'尚硅谷',
mood:'normal',
classObj: {
atguigu1: false,
atguigu2: true
}
},
1.10.2 绑定style样式
样式的绑定除了用class,还可以用style内联样式。
- 绑定style样式
- 对象写法
代码
注意:style里的字体大小是font-size,在Vue里要写成fontSize,即驼峰式
<div class="basic" :style="styleObj">{{name}}</div>
new Vue({
el:'#root',
data: {
name:'尚硅谷',
mood:'normal',
styleObj: {
fontSize:'40px'
},
}
}
像color等style,在Vue直接写color,但是像短横线的,就要改成驼峰式的。
- 绑定style样式
- 数组写法
<div class="basic" :style="styleArr">{{name}}</div>
el:'#root',
data: {
name:'尚硅谷',
mood:'normal',
styleArr: [
{
fontSize:'40px'
},
{
color:'40px'
}
],
数组里面放的就是样式的对象。
- 绑定样式总结
- 1 class 样式
- 写法是:class ="xxx",xxx可以是字符串,对象,数组
- 字符串写法适用于:类名不确定,要动态获取
- 数组写法适用于:要绑定多个样式,个数不确定,名字也不确定
- 对象写法适用于:要绑定多个样式,个数确定,名字确定,但不确定用不用
- 写法是:class ="xxx",xxx可以是字符串,对象,数组
- 2 style样式
- 写法是:style="{fontSize:xxx}",其中xxx是动态值
- :style="[a,b]",其中a和b是样式对象。
- 1 class 样式
- 最常用的还是class样式。
1.11 条件渲染
顾名思义:符合了某些条件,然后给你渲染某些东西。主要就是几个指令的使用。
1.11.1 使用v-show做条件渲染
要div时而显示时而隐藏。
如果用原生去实现,可以display:none或者透明度为0或者visibility为hidden。
但是Vue中指令v-show,底层实现就是调整display属性。
代码
<h2 v-show="true">欢迎来到{{name}}</h2>
v-show里是个表达式也可以,比如v-show=" 1=== 3".
1.11.2 v-if
v-if为false,这个节点本身也就不存在,这是与v-show的不同之处。v-show只是控制节点不显示,本质还是存在的。
<h2 v-if="false">欢迎来到{{name}}</h2>
如果切换频率高,建议使用v-show。v-if涉及到在DOM添加/删除节点,因此不适用于切换频率高的操作。
1.11.3 v-else-if
比三个if效率要高一些。
<h2 v-if="n === 1">欢迎来到{{name}}</h2>
<h2 v-else-if="n === 2">欢迎来到{{name}}</h2>
<h2 v-else-if="n === 3">欢迎来到{{name}}</h2>
1.11.4 v-else
v-else就是最后if elseif else里的else作用。
<h2 v-if="n === 1">欢迎来到{{name}}</h2>
<h2 v-else-if="n === 2">欢迎来到{{name}}</h2>
<h2 v-else-if="n === 3">欢迎来到{{name}}</h2>
<h2 v-else>欢迎来到{{name}}</h2>
v-if v-else-if v-else中间不允许被打断,也就是不允许被插入其他语句。
1.11.5 v-if与template标签配合使用
<div v-if="true">
<h2>欢迎来到{{name}}</h2>
<h2>欢迎来到{{name}}</h2>
<h2>欢迎来到{{name}}</h2>
<h2>欢迎来到{{name}}</h2>
</div>
本来只是四个h2,但是为了将他们包在一起,所以多了个div。
更好的办法,使用template,模板,最大的特点是hi不影响结构。最终渲染的时候,红色框里的东西会消掉。
注意: template只能配合v-if使用,不能与v-show使用。
下面的xxx是表达式
- 条件渲染总结
- v-if
- 写法
- v-if="xxx"
- v-else-if="xxx"
- v-else="xxx"
- 适用于切换频率较低的场景
- 特点:不展示的DOM元素直接被移除
- 注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被打断
- 写法
- v-show
- 写法
- v-show=“xxx”
- 适用于切换频率较高的场景
- 特点:不展示的DOM元素未被移除,仅仅是display样式设为none
- 写法
- 备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到。
- v-if为false,导致元素不存在,所以可能存在无法获取到的情况。
- v-if
1.12 列表渲染 ***重要
1.12.1 列表渲染
基本的列表渲染
使用v-for指令,完成列表渲染。for-in
<!-- 准备好一个容器 -->
<div id="root">
<ul>
<li v-for="p in persons">{{p.name}}-{{p.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
persons: [
{id:'001',name:'张三',age:'18'},
{id:'002',name:'张四',age:'19'},
{id:'003',name:'张五',age:'20'}
]
}
})
</script>
- 细节
- 1 标签属性key
- key用于接收id
-
<li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}</li>
- 2 两个形参
- p是item,即遍历的每一项,b是index,即索引.
- 上面的key在这里也可以是index
-
<li v-for="(p, index) in persons" :key="p.id">{{p.name}}-{{p.age}}</li>
- 3 遍历对象
- 这里v-for里面的参数就是value和key(参考key-value键值对思想)
-
<li v-for="(value, key) in car" :key="key">{{key}}-{{value}}</li> car: { name:'奥迪A8', price:'70w', color:'black' }
- 4 遍历字符串
- 这里参数就是char和对应的index
-
<li v-for="(char, index) in str" :key="index">{{index}}-{{char}}</li> str: 'hello'
- 5 遍历指定次数
- number从1开始到5,index从0到4
-
<li v-for="(number, index) in 5" :key="index">{{index}}-{{number}}</li>
- 结果
- 1 标签属性key
- 列表渲染总结
- v-for指令
- 可以用于展示列表数据
- 语法:v-for="(item,index) in xxx" :key="yyy"
- 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
- v-for指令
1.12.2 key作用与原理
详细探讨使用v-for渲染列表时,所传递的key的作用和原理。
key是Vue在用的,Vue用完之后弄成真实DOM以后就将key去掉了。
这part听明白就好了。
面试题:react、vue中的key有什么作用?(key的内部原理)
- 1. 虚拟DOM中key的作用:
- key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
- 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
- 2.对比规则:
- (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
- ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
- ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
- (2).旧虚拟DOM中未找到与新虚拟DOM相同的key
- 创建新的真实DOM,随后渲染到到页面。
- (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
- 3. 用index作为key可能会引发的问题:
- 1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
- 2. 如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。
- 4. 开发中如何选择key?:
- 1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
- 2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
1.12.3 列表过滤
- 列表过滤
- 步骤1:拿到用户的输入
- 步骤2:列表过滤,展示结果
注意str.indexof(' ')返回值为0,不是-1(-1表示字符串内不包含某个字符串值)
vscode折叠代码,//#region 和 //#endregion
【watch实现】
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyword">
<ul>
<li v-for="(p, index) in filPersons" :key="index">{{p.name}}-{{p.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyword:'',
persons: [
{id:'001',name:'马冬梅',age:'18'},
{id:'002',name:'周冬雨',age:'19'},
{id:'003',name:'周杰伦',age:'20'},
{id:'004',name:'温兆伦',age:'22'}
],
filPersons: []
},
watch: {
keyword:{
// immediate为true时会在开始时执行一下handler()
immediate:true,
handler(val) {
// console.log('key被改了')
this.filPersons = this.persons.filter( (p) =>{
return p.name.indexof(val) != -1
})
}
}
}
})
</script>
解读
结果
运行
【computed实现】
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyword">
<ul>
<li v-for="(p, index) in filPersons" :key="index">{{p.name}}-{{p.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyword:'',
persons: [
{id:'001',name:'马冬梅',age:'18'},
{id:'002',name:'周冬雨',age:'19'},
{id:'003',name:'周杰伦',age:'20'},
{id:'004',name:'温兆伦',age:'22'}
],
},
computed: {
filPersons() {
return this.persons.filter( (p) =>{
return p.name.indexOf(this.keyword) != -1
})
}
}
})
计算属性computed不需要监视keyword,因为当他依赖的数据keyword发生变化时,整个filPersons会重新执行,这样就会拿到一个新的值。
当computed和watch都能实现的时候,我们优先使用computed。
1.12.4 列表排序
p32跳过。用到再看。
1.12.5 更新时的一个问题
p33 Vue如何实现数据监视的。
1.12.6 Vue监测数据的原理-对象
p34跳过。
1.12.7 Vue.set()
p35跳过。
1.12.9 Vue检测数据的原理-数组
p36跳过。
1.12.10 总结Vue监视数据
p37跳过。
1.13 收集表单数据
简单功能。
form的action属性用于提交表单提交的地址。
小tips
1
<form >
<label for="demo">账号:</label>
<input type="text" id="demo">
</form>
点击账号文字的时候,光标也跳到input文本框里。
2 性别选择的时候,只能二选一,可以在男女两个input框上添加同一个name属性,这样就是二选一,而不是可以同时都选了。
男:<input type="radio" name="gender">
女:<input type="radio" name="gender"><br/><br/>
代码实现上面的表单form
<div id="root">
<form >
账号:<input type="text"> <br/><br/>
密码:<input type="password"><br/><br/>
姓名:
男:<input type="radio" name="gender">
女:<input type="radio" name="gender"><br/><br/>
爱好:
学习:<input type="checkbox">
打游戏:<input type="checkbox">
吃饭:<input type="checkbox"><br/><br/>
所属校区:
<select>
<option value="">请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shenzhen">深圳</option>
</select><br/><br/>
其他信息:
<textarea></textarea><br/><br/>
<input type="checkbox">阅读并接受<a href="http://www.baidu.com">《用户协议》</a><br/><br/>
<button>提交</button>
</form>
</div>
上面这些都要接受Vue的管理,下面开始Vue代码。
账号和密码这类用 v-model收集就行。
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
userInfo: {account:'',
password:'',
gender:'female',
hobby:[],
city:'beijing',
other:'',
agree:'',}
},
methods:{
demo(){
console.log(JSON.stringify(this.userInfo))
}
}
})
</script>
一些小问题。
1 this._data就是包含account、password等所有数据。但是不要直接去访问下划线变量,一般就是放在一个对象里。但是此时v-model的右边加上对象.
2 只能输入数字:
3 文本框不需要实时收集,在失去焦点的瞬间收集。
4自动去掉空格。
- 收集表单数据总结
- 若 <input type="text">,则v-model收集的是value值,用户输入的就是value值
- 若 <input type="radio">(单选框),则v-model收集的事value值,且要给标签配置value。
- 若 <input type="checkbox">
- 1 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
- 2 配置input的value属性
- v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
- v-model的初始值是数组,那么收集的就是value组成的数组
- 备注:v-model的三个修饰符 (v-model.修饰符名)
- lazy:失去焦点后再收集数据
- number:输入字符串转为有效数字(与类型为number的input连用)
- trim:输入首尾空格过滤
1.14 过滤器
p39跳过。
1.15 内置指令与自定义指令
内置指令:Vue作者定义好的指令,比如v-on,v-bind等,之前学的都是内置指令。
自定义指令就是自己设计的指令。
学过的指令:
v-bind:单向绑定解析表达式,可简写为:xxx
v-model: 双向数据绑定
v-for:遍历数组/字符串/对象
v-on: 绑定事件监听。可简写为@
v-if:条件渲染(动态控制节点是否存在)
v-else:条件渲染(动态控制节点是否存在)
v-show: 条件渲染(动态控制节点是否显示)
1.15.1 v-text
- v-text
- 功能:向其所在的标签插入文本。
代码
<div id="root">
<div>{{name}}</div>
<div v-text="name">
</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
name:'尚硅谷',
}
})
</script>
其实还是推荐插值语法,插值语法更灵活。
v-text会拿到name的值替换到整个div内的值。且不能解析标签,案例如下。
- v-text指令总结
- 作用:向其所在的节点中渲染文本内容
- 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}不会。
1.15.2 v-html
- v-html区别于v-text
- v-html可以解析标签,v-text不支持。
v-html存在安全问题。p41 18:25之后不看了。
cookie的概念
cookie的格式类似json格式的字符串,key-value组成。
cookie存在本地的浏览器中。
1.15.3 v-cloak
页面闪现问题,出现{{xxx}}。v-cloak结合css可以解决。
style里[v-cloak] 是指选中所有标签里含有v-cloak属性的元素。
- 页面闪现问题解决
- 1 div先跑到页面上,因为vue需要等待5s才能被解析
- 2 但是div里含v-cloak,而v-cloak已经被display:none了,因此也不显示
- 3 等到vue被解析成功后,v-cloak就自动移除,这样div就会正常显示了。
v-cloak作用就是当网速过慢,可以不让未经解析的模板显示在页面上,不然会很丑。
- v-cloak总结
- 本身没有值
- 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
- 使用css配合v-cloak可以解决网速过慢时页面展示出{{xxx}}的问题(页面闪现问题)。
1.15.4 v-once
需求:让Vue保存一个数值n,随后呈现到页面上
<div id="root">
<div v-once>初始化的n值:{{n}}</div>
<div>当前的n值是:{{n}}</div>
<button @click="n++">点我n+1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
n:1,
}
})
</script>
结果
初始化的n值只读了一次n值,也就是n为1,之后不再读取n值。
- v-once总结
- v-once所在节点在初次动态渲染后,就视为静态内容了
- 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
1.15.5 v-pre
- v-pre总结
- 跳过其所在节点的编译过程
- 可利用它跳过没有使用指令语法、没有使用插值语法的节点,加快编译。
1.15.6 自定义指令-函数式
p45跳过
1.15.7 自定义指令-对象式
p46跳过
1.15.8 自定义指令-总结
p47跳过
1.16 Vue实例生命周期
1.16.1 引出生命周期
案例:通过透明度变化的例子引出生命周期。
实现1:通过外部的定时器实现透明度变化(不推荐)
中间实现涉及的小知识点:只要数据发生改变,Vue就会重新解析模板。
实现2:通过mounted()实现
<div id="root">
<h2 :style="{opacity}">欢迎学习vue生命周期</h2>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
opacity:1,
},
methods: { },
mounted() {
setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) {
this.opacity = 1
}
}, 16);
}
})
</script>
mounted 挂载,在Vue完成模板解析并把初始真实的DOM放入页面后(挂载完毕)调用mounted()
mounted()就是一个普通函数,只是在Vue某个关键时候被调用。与mounted类似的函数还有三个,这些都是Vue的生命周期函数。Vue的生命周期,又名Vue的一生。
- 生命周期总结
- 1 又名:生命周期函数、生命周期回调函数、生命周期钩子
- 2 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
- 3 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
- 4 生命周期函数中的this指向是vm 或 组件实例对象
1.16.2 挂载流程
红色圈里的是完整的挂载流程。
debugger;用来打断点的。
用了Vue就尽可能减少自己操作DOM
Init Events & Lifecycle(是个环节,不是生命周期),用来制定规则,生命周期函数的个数,名字,何时调用,以及事件修饰符处理,但数据代理还没开始,此时vm还没有_data。
生命周期本质就是函数,等待Vue调用。
Init Events & Lifecycle之后马上调用了beforeCreate(),此为第一个生命周期函数。此时无法通过vm访问_data中的数据和methods中的方法。
Init injections & reactivity,数据监测(Vue如何监测对象和数组变化,为对象的属性匹配getter和setter,对操作数组的方法进行二次包装)和数据代理。
beforeCreate(),在数据监测和数据代理创建之前。
created(),在数据监测和数据代理创建完毕后,此时可以通过vm访问到data中的数据和methods中的方法。
created()之后,黄色菱形框,问:是否有el配置项,即在创建Vue的时候传没传el配置项?
传了。走yes那条线。
下一步,还是一个黄色菱形框,问:有没有template这个配置项(template与data和methods同等位置),
没传,那就走No那条线。
编译el的outerHtml作为template。
解释:这里,如果是innerHtml,那么就是下面红色区域的内容是模板;而如果是outerHtml,那么就是下面绿色区域的内容是模板。
直接写el:"#root",那么整个绿色的部分都是模板(即包括最外面一层的div)。
模板是肯定要有的,如果不写template,那么el指定谁是模板谁就是template。
右边注释,此时Vue开始解析模板,此时代码里的插值语法,@click,计算属性等等都开始被解析了。
然后生成虚拟DOM,注意是在内存中,此时页面还不能显示解析好的内容。因为此时还没有转成真实DOM。
beforeMount(),挂载之前,页面呈现的是未经Vue编译的DOM,此时Vue已经解析完了DOM,但是没有来得及往页面上放。此时所有对DOM的操作,最终都不奏效。如果在这里修改DOM,到了下一步,仍然是将虚拟DOM转成真实DOM,往vm.$el上存了一份,然后往页面一放。刚才不管是对DOM进行什么操作,最终都是将虚拟DOM转为真实DOM然后插入页面了。
意思是:不要在beforeMount()里操作DOM,不过操作了也是白费功夫。
Create vm.$el and replace 'el' with it。用 vm.$el替换掉整个el里的东西,也就是容器里的东西。在此步,Vue将内存中的虚拟DOM转成真实DOM,转成真实DOM后,往vm.$el上存了一份。
为什么要存一份呢?Vue在进行新虚拟DOM和旧虚拟DOM比较,万一有的元素节点可以复用,那么得有之前的节点或元素才能复用。所以说存真实的DOM节点无可厚非。
Mounted(),此时页面呈现的是经过Vue编译的DOM。
此时对DOM的操作均有效,但是尽可能避免,因为用了Vue就尽量不要直接操作DOM。
此时,Vue先去忙,忙完了,将真实DOM挂载到页面上了。
至此初始化过程结束。一般在此进行开启定时器、发送网络请求、订阅消息、绑定自定义事件等操作。
回头说一下前面的两条线,没有el和有template的两条线。
没有el:如果不写el,Vue就不知道他为哪个容器服务。
这里跳过了。P49 25:00
1.16.3 更新流程
蓝色框里就是更新流程。
When data changes,只要data对象的数据发生改变,那么Vue立马调用beforeUpdate()。
beforeUpdate(),数据是新的,页面是旧的。此时页面和数据尚未保持同步。
Virtual DOM re-render and patch,虚拟DOM重新渲染以及,新旧虚拟DOM比较。
根据新数据,生成新的虚拟DOM,随后与旧的虚拟DOM进行比较,最终完成页面更新,即:完成了Model→View的更新。
MVVM模型
model:模型,即数据,View:即数据。此处就是完成了从model到view的步骤。这里挂载的时候就完成过一次了,只是那次叫初次渲染,这次叫更新。
Updated(),数据是新的,页面也是新的,数据和页面保持同步。
其实常用的生命周期也就那两三个。
1.16.4 销毁流程
销毁流程之前,经历 when vm.$destroy() is called,vm开始进行自我毁灭。
这里是在methods里面重新写一个方法,调用this.$destroy()。位置跟mounted()还是不大一样的。
调用vm.$destroy()后,vm被销毁。但是vm临死前的工作成果还是在的,只是没有人去管理了。且借助Vue的开发者工具,啥也看不到了。
官网介绍,调用vm.$destroy()就会完全销毁一个Vue实例,即vm。清理他与其他实例(组件实例对象,一个应用只能有一个vm,但是一个vm会管理一堆的组件实例对象。由于组件实例对象与vm十分相似,因此也称组件实例对象为微型vm)的连接,解绑vm上的全部指令以及事件监听器(自定义事件,而不是原生的DOM事件。原生的DOM事件绑定后就不能撤销,即便是vm被销毁了,也不会被撤销。)。
beforeDestroy(),销毁之前,也就是还没有被销毁。此时,vm的data、methods、指令等等,都处于可用状态。马上要执行销毁过程,一般在此阶段:关闭定时器,取消订阅消息,解绑自定义事件等收尾操作。但是所有对数据的更改不会再触发更新了。
Teardown watchers child components and event listeners。移除监听器,子组件和事件监听器(自定义事件)。只留下原生的事件。
destroyed(),这里数据改变也是不再触发更新了。react里没有这个钩子。这个钩子什么也不干,是存在感最低的钩子。
1.16.5 总结
8个生命周期钩子,4对
beforeCreate() 和created(),数据监测和数据代理创建之前和之后,
beforeMounted()和mounted(),mounted(),做点初始化的事,开启定时器,发送网络请求,订阅消息,绑定自定义事件等等。
beforeUpdate()和updated()
beforeDestroy()和destroy(),beforeDestroy()做一点收尾性的工作,关闭定时器,取消订阅消息,
人的出生和将要离开——重要
挂载和将要销毁——重要
初始化的工作——mounted()
收尾性的工作——beforeDestroy()
1.16.5.1 案例重现
温柔地取消透明度变化的显示。
<div id="root">
<h2 :style="{opacity}">欢迎学习vue生命周期</h2>
<button @click="stop">点我停止变换</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
opacity:1,
},
methods: {
stop() {
clearInterval(this.timer)
}
},
mounted() {
// 往vm的timer属性上存了一个定时器id
this.timer = setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) {
this.opacity = 1
}
}, 16);
}
})
</script>
老师要求别的方法。
要求暴力停止,把vm也给清了。
stop里面调用this.$destroy()
methods: {
stop() {
this.$destroy()
}
},
但是此时定时器还没关闭。关闭定时器在beforeDestroy里完成
beforeDestroy() {
clearInterval(this.timer);
}
干掉vm,走销毁流程,那么beforeDestroy就会被调用,那么定时器就会被clear。
1.16.5.2 总结
- 常用的生命周期钩子
- mounted()
- 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
- beforeDestroy()
- 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
- mounted()
- 关于销毁Vue实例
- 1 销毁后借助Vue开发者工具看不到任何信息
- 2 销毁后自定义事件会失效,但原生DOM事件仍然有效
- 3 一般不会在beforeDestroy()中操作数据,因为即便操作数据也不会再触发更新流程了。