请详细说一下你对vue生命周期的理解,vue生命周期详解简书
本文主要通过一篇文章介绍如何带你走过Vue的生命周期。文章结合案例更容易理解,对你的学习或工作有一定的参考价值。有需要的朋友可以参考一下。
目录
1.vue生命周期1.0_ Humans-Lifecycle 1.1_ Hook函数1.2_初始化阶段1.3_挂载阶段1.4_更新阶段1.5_销毁阶段2.axios2.0_axios基本使用2.1_axios基本使用-获取数据2.2_axios基本使用-Pass引用2.3_axios S基本使用-全局配置3 .Nexttick和refs的知识3.0$refs- get DOM3.1$refs- get组件对象3.2$nextTick用法3.3$nextTick用法场景3.4组件名称属性用法4。案例-购物车4.0案例-购物车-项目初始化4.1案例-购物车-表头定制4.2案例-购物车-请求数据4.3案例-购物车-数据渲染4.4案例-购物车-商品选择4.5案例-购物车-数量控制4.6案例-购物车-全选功能4.7案例-购物车-总数量4.8案例-购物车-总价面试问题1。Vue的nextTick是什么原理?(高薪频问)2。vue的生命周期有几个阶段?(必须)3。页面第一次加载时会触发哪些钩子函数?写在最后。
1. vue生命周期
1.0_人的-生命周期
一个组件从创建到销毁的整个过程就是生命周期。
Vue_生命周期
1.1_钩子函数
目标:Vue框架内置函数,会随着组件的生命周期自动执行。
功能:在特定的时间点执行特定的操作。
场景:创建组件后,可以在创建的生命周期函数中发起Ajax请求来初始化数据data。
分类:4个阶段,8种方法
初始化挂载更新销毁阶段方法名方法名初始化beforeCreatecreated挂载before Mount更新beforeUpdateupdated Destroy销毁官网文档
下图显示了实例的生命周期。你不需要一下子了解所有的东西,但是随着你不断的学习和使用,它的参考价值会越来越高。
1.2_初始化阶段
目的:掌握两个钩子函数在初始化阶段的作用和执行时机。
解释:
1.new Vue()vue的实例化(该组件也是vue的一个小实例)
2.初始化事件生命周期初始化事件和生命周期函数
3.创建前执行生命周期挂钩功能
4.初始进样反应性数据和方法被添加到Vue中。
5.已创建执行生命周期挂钩功能并创建实例。
6.接下来是编译模板的阶段——开始分析
7.有el选项吗?是否有el选项检查悬挂位置
不。调用$mount()方法
是,继续检查模板选项。
components/life . vue-创建一个文件
脚本
导出默认值{
data(){
返回{
消息:“你好,Vue”
}
},
//一、初始化
//new vue()之后,一些属性和方法被添加到vue内部的实例对象中,数据和方法在“之前”被初始化
创建之前(){
Console.log(创建前-执行);
console . log(this . msg);//未定义
},
//初始化数据和方法后
//场景:网络请求,注册全局事件
已创建(){
Console.log(created - execute )。
console . log(this . msg);//你好,Vue
this.timer=setInterval(()={
Console.log(哈哈哈);
}, 1000)
}
}
/脚本
app . vue-介绍和使用
模板
差异
H11。生命周期/h1
生活/生活
/div
/模板
脚本
从导入生命。/组件/寿命
导出默认值{
组件:{
生活
}
}
/脚本
1.3_挂载阶段
目的:掌握挂载阶段两个钩子函数的作用和执行时机。
解释:
1 .模板选项检查
是-编译模板以返回render渲染函数。
none将对应于el选项的标签编译为模板(要渲染的模板)
2.在虚拟DOM装入真实DOM之前
3.挂载前执行生命周期挂钩功能
4.create…将虚拟DOM和渲染数据挂在真实DOM上。
5.真正的DOM是挂载的。
6.已安装执行生命周期挂钩功能。
components/life . vue-创建一个文件
模板
差异
p学习生命周期-参见控制台打印/p
p id=myP{{ msg }}/p
/div
/模板
脚本
导出默认值{
//.省略其他代码。
//二。增加
//在挂载真正的DOM之前
//场景:预处理数据不会触发更新的钩子函数
beforeMount(){
Console.log(安装前-执行);
console . log(document . getelementbyid( myP ));//null
This.msg=重新赋值
},
//在真正的DOM挂载之后
//场景:挂载后的真实DOM
已安装(){
console . log( mounted-execute );
console . log(document . getelementbyid( myP ));//p
}
}
/脚本
1.4_更新阶段
目的:掌握更新阶段两个钩子函数的作用和执行时机。
解释:
1.当数据中的数据发生变化时,在更新DOM之前
2.更新前执行生命周期挂钩功能。
3.虚拟DOM…虚拟DOM被重新渲染并修补为真实DOM。
4.更新执行生命周期挂钩功能。
5.当数据改变时,重复这个循环。
components/life . vue-创建一个文件
准备ul li周期,按下按钮添加元素,触发数据更改-导致更新周期的开始。
模板
差异
p学习生命周期-参见控制台打印/p
p id=myP{{ msg }}/p
ul id=myUL
li v-for=(val,index) in arr :key=index
{{ val }}
/李
/ul
Button @click=arr.push(1000)单击末尾的添加值/button
/div
/模板
脚本
导出默认值{
data(){
返回{
消息:“你好,Vue”,
arr: [5,8,2,1]
}
},
//.省略其他代码。
//三。更新
//前提:数据只有在数据发生变化时才执行。
//更新前
更新之前(){
Console.log(更新前-执行);
console . log(document . query selectorall( # myULli )[4]);//未定义
},
//更新后
//场景:获取更新后的真实DOM
已更新(){
Console.log(更新-执行);
console . log(document . query selectorall( # myULli )[4]);//李
}
}
/脚本
1.5_销毁阶段
目的:掌握两个钩子函数在销毁阶段的作用和执行时机。
解释:
1.当调用$destroy()时——例如,组件DOM被删除(例如v-if)
2.销毁前执行生命周期挂钩功能。
3.拆卸数据监视器、子组件和事件监听器。
4.实例销毁后,最后触发一个钩子函数。
5.销毁执行生命周期挂钩功能。
components/life . vue-准备生命周期方法(生命周期组件即将删除)
脚本
导出默认值{
//.省略其他代码。
//四。破坏
//前提:v-if=false 销毁Vue实例
//场景:移除全局事件,移除当前组件,定时器,计时器,eventBus移除事件$off方法
销毁前(){
//console.log(销毁前-执行);
clearInterval(this.timer)
},
销毁(){
//console . log( destroyed-execute );
}
}
/脚本
main:app . vue——点击按钮从DOM中移除生命组件——使生命组件进入销毁阶段。
生活v-if=显示/生活
Button @click=show=false 销毁组件/按钮
脚本
data(){
返回{
显示:真实
}
},
/脚本
2. axios
2.0_axios基本使用
Axios文档
特性
支持客户端发送Ajax请求,支持server Node.js发送请求,支持Promise相关用法,支持请求和响应的拦截器功能,自动转换jsON数据,无论axios是底层实现还是原生js,内部基本使用Promise封装的axios。
axios({
方法:“请求方法”,//获取post
Url:“请求地址”,
数据:{//拼接到请求体的参数和post请求的参数
xxx: xxx,
},
Params: {//拼接到请求行的参数,get请求的参数
xxx: xxx
}
}).然后(res={
Console.log(res.data) //后台返回的结果
}).catch(错误={
Console.log(err) //后台返回错误
})
2.1_axios基本使用-获取数据
目的:调用_获取文档末尾所有图书信息的接口。
功能:点击调用后台界面,获取所有数据-打印到控制台。
接口:参见preview . MD接口文档。
导入:下载axios,导入后才能使用。
效果:
例子如下:
components/UseAxios.vue
模板
差异
P1。获取所有图书信息/p
button @ Click= get all fn Click-view控制台/button
/div
/模板
脚本
//目标1:获取所有图书信息
//1.下载axios
//2.axios简介
//3.启动axios请求
从“axios”导入axios;
导出默认值{
方法:{
getAllFn() {
axios({
网址: http://123 . 57 . 109 . 30:3006/API/getbooks ,
方法: GET ,//默认是GET模式的请求,可以省略不写。
}).然后((res)={
console . log(RES);
});
//axios()-获取Promise对象
},
}
};
/脚本
2.2_axios基本使用-传参
目的:调用接口——获取一本书的信息。
功能:点击调用后台界面,查询用户想要的图书信息——打印到控制台。
接口:参见preview . MD接口文档。
效果:
例子如下:
components/UseAxios.vue
模板
差异
P2。查询一本书/p
Input= text placeholder=请输入书名 v-model=bName/
Button @click=findFn 查询/button
/div
/模板
脚本
从“axios”导入axios;
导出默认值{
data() {
返回{
bName:“”
};
},
方法:{
//.省略所有要查询的代码。
findFn() {
axios({
URL:“/API/getbooks”,
方法:“GET”,
Params: {//Metropolis axios最终拼接到url?背部
书名:this.bName
}
}).然后(res={
console . log(RES);
})
}
},
};
/脚本
2.3_axios基本使用-发布书籍
目标:完成出书的功能。
功能:点击添加按钮,将用户输入的图书信息转移到后台——在控制台上打印结果。
接口:参见preview . MD接口文档。
效果:
例子如下:
components/UseAxios.vue
模板
差异
P3。新书信息/p
差异
type= text placeholder= book title v-model= book obj . bookname
/div
差异
type= text placeholder= author v-model= book obj . author
/div
差异
type= text placeholder= publishing house v-model= book obj . publisher
/div
button @ click= sendFn publish/button
/div
/模板
脚本
从“axios”导入axios;
导出默认值{
data() {
返回{
bName: ,
BookObj: {//参数名提前匹配后台的参数名——发送请求时不需要再次对接。
书名: ,
作者: ,
发布者:“”
}
};
},
方法:{
//.其他代码省略。
sendFn(){
axios({
URL:“/API/addbook”,
方法: POST ,
数据:{
appkey: 7250 D3 EB-18e 1-41bc-8bb 2-11483665535 a ,
.this.bookObj
//相当于以下内容
//bookname:this . book obj . bookname,
//作者:this.bookObj.author,
//publisher:this . book obj . publisher
}
})
}
},
};
/脚本
2.4_axios基本使用-全局配置
目标:避免前缀基址,在逻辑页面中暴露,统一设置。
axios . defaults . baseurl= http://123 . 57 . 109 . 30:3006
//所有请求的url前缀都可以去掉。请求时,axios会自动拼接前面的baseURL的地址。
getAllFn() {
axios({
URL:“/API/getbooks”,
方法: GET ,//默认是GET模式的请求,可以省略不写。
}).然后((res)={
console . log(RES);
});
//axios()-获取Promise对象
},
3. nextTick和refs知识
3.0 $refs-获取DOM
目标:ref和$refs可用于获取dom元素
组件/更多. vue
模板
差异
P1。获取本机DOM元素/p
H1= h ref= myh 我是一个孤独的,可怜的,可食用的h1/h1
/div
/模板
脚本
//Target:获取组件对象
//1.创建组件/导入组件/注册组件/使用组件。
//2.别名元件参考
//3.在正确的时间获取组件对象。
导出默认值{
已安装(){
console . log(document . getelementbyid( h ));//h1
console.log(这个。$ refs . myh);//h1
}
}
/脚本
风格
/风格
总结:通过id/ref,可以获得原生DOM标签。
3.1 $refs-获取组件对象
目标:获取组件对象,调用组件中的方法。
组件/子组件/演示组件
模板
差异
p我是演示组件/p
/div
/模板
脚本
导出默认值{
方法:{
fn(){
Console.log(“调用了演示组件中的方法”);
}
}
}
/脚本
More.vue-get组件对象-调用组件方法
模板
差异
P1。获取本机DOM元素/p
H1= h ref= myh 我是一个孤独的,可怜的,可食用的h1/h1
P2。获取组件对象——组件中的所有内容都可以被调用/p
演示ref= de /演示
/div
/模板
脚本
//Target:获取组件对象
//1.创建组件/导入组件/注册组件/使用组件。
//2.别名元件参考
//3.在正确的时间获取组件对象。
从导入演示。/子/演示
导出默认值{
已安装(){
console . log(document . getelementbyid( h ));//h1
console.log(这个。$ refs . myh);//h1
让demoObj=这个。$ refs.de
demoObj.fn()
},
组件:{
演示
}
}
/脚本
总结:ref定义值,组件对象可以通过$refs获取。值,以便可以连续调用组件中的变量。
3.2 $nextTick使用
Vue更新DOM-异步
目标:点击count立即通过 native DOM 获取标签内容,但无法获取新值。
components/move . vue-继续添加第三组代码。
模板
差异
P1。获取本机DOM元素/p
H1= h ref= myh 我是一个孤独的,可怜的,可食用的h1/h1
P2。获取组件对象——组件中的所有内容都可以被调用/p
演示ref= de /演示
P3。vue异步更新DOM
p ref=myP{{ count }}/p
Button @click=btn Click count 1立即提取p标签/button的内容
/div
/模板
脚本
//Target:获取组件对象
//1.创建组件/导入组件/注册组件/使用组件。
//2.别名元件参考
//3.在正确的时间获取组件对象。
从导入演示。/子/演示
导出默认值{
已安装(){
console . log(document . getelementbyid( h ));//h1
console.log(这个。$ refs . myh);//h1
让demoObj=这个。$ refs.de
demoObj.fn()
},
组件:{
演示
},
data(){
返回{
计数:0
}
},
方法:{
btn(){
this.count//vue监控数据更新并打开一个DOM更新队列(异步任务)
console.log(这个。$ refs . myp . innerhtml);//0
//原因:Vue异步更新DOM。
//解决方法:这个。$nextTick()
//Process:DOM更新后,$nextTick中的函数体会被逐个触发。
这个。$nextTick(()={
console.log(这个。$ refs . myp . innerhtml);//1
})
}
}
}
/脚本
摘要:因为DOM更新是异步的
3.3 $nextTick使用场景
目标:点击搜索按钮,弹出焦点输入框,按钮消失。
![n e x t T i c k已启用] (images/nextTick使用。gif)
组件/Tick.vue
模板
差异
input= myinp type= text placeholder=这是输入框 v-if=isShow
按钮v-else @click=btn 单击我进行搜索/按钮
/div
/模板
脚本
//Target: dot按钮(消失)-输入框出现并获得焦点。
//1.获取输入框。
//2.输入框调用事件方法focus()来实现聚焦行为。
导出默认值{
data(){
返回{
isShow: false
}
},
方法:{
异步btn(){
this.isShow=true
//这个。$refs.myInp.focus()
//原因:数据变化异步更新DOM。
//输入框还没有安装在真正的DOM上
//求解:
//这个。$nextTick(()={
//这个。$refs.myInp.focus()
//})
//扩展:await替换回调函数。
//$nextTick()就地返回Promise对象
等待这个。$nextTick()
这个。$refs.myInp.focus()
}
}
}
/脚本
3.4 组件name属性使用
Target:您可以用组件的name属性值注册组件名。
问题:组件名不能随便写?
答:我们打包的组件——你可以自己定义名称属性组件名称——让用户有统一的前缀样式。
components/Com.vue
模板
差异
p我是一个Com组件/p
/div
/模板
脚本
导出默认值{
姓名: ComNameHaHa //注册时可以定义自己的名字
}
/脚本
App.vue -注册和使用
模板
差异
h11 .生命周期/h1
生活v-if=显示/生活
button @click=show=false 销毁组件/按钮
整点
h12 .爱可信使用/h1
乌塞克斯/乌塞克斯
整点
h13 .$参考文献的使用/h1
更多/更多
整点
h14 .$nextTick使用场景/h1
滴答/滴答
整点
h15 .组件对象里名字属性/h1
ComNameHaHa/ComNameHaHa
/div
/模板
脚本
从导入生命。/组件/寿命
从导入使用说明./组件/用途
从导入更多。/组件/更多
从导入打勾./组件/刻度
从导入Com ./components/Com
导出默认值{
data(){
返回{
显示:真实
}
},
组件:{
生活,
UseAxios,
更多,
滴答,
[Com.name]: Com //对象里的键是变量的话[]属性名表达式
//ComNameHaHa: Com
}
}
/脚本
4. 案例 - 购物车
4.0 案例-购物车-项目初始化
目标:初始化新项目,清空不要的东西,下载引导程序库,下载较少的模块
某视频剪辑软件创建商店汽车
纱线添加引导
5.0.0 -D时纱线添加量较少
图示:
按照需求,把项目页面拆分成几个组件,在成分下创建
我的标题组件MyFooter组件我的商品组件-商品我的帐户组件然后引入到App.vue上注册
在主页。射流研究…中引入引导程序库
import bootstrap/dist/CSS/bootstrap。CSS //引入第三方包里的某个钢性铸铁文件
MyHeader.vue
模板
div class=my-header 购物车案例/div
/模板
脚本
导出默认值{
}
/脚本
style lang=less 范围。我的标题{
高度:45像素
行高:45像素
文本对齐:居中;
背景色:# 1d 7 BFF
颜色:# fff
位置:固定;
top:0;
左:0;
宽度:100%;
z指数:2;
}
/风格
MyGoods.vue
模板
div class=我的商品项目
div class=left
div class=自定义控件自定义复选框
输入类型=复选框 class=自定义控件-输入id=输入
"输入"的标签class="自定义控件标签"
img src= http://fuss 10。eleme cdn。com/e/5d/4a 731 a 90594 a4 af 544 c0c 25941171 JPEG。JPEG alt=
/标签
/div
/div
div class=右
div class=top 商品名字/div
div class=bottom
span class=price 100/span
跨度
数量组件
/span
/div
/div
/div
/模板
脚本
导出默认值{
}
/脚本
style lang=less 范围。我的商品项目{
显示器:flex
填充:10px
边框-底部:1px纯色# ccc。左侧{
img {
宽度:120像素
高度:120像素
右边距:8px
边框半径:10px
}。自定义控件标签:之前,自定义控件标签:在{
顶配:50px
}
}。右{
flex:1;
显示器:flex
伸缩方向:列;
justify-content:space-between;顶部{
字体大小:14px
字体粗细:700;
}。底部{
显示器:flex
justify-content:space-between;
填充:5px 0;
对齐-项目:居中;价格{
颜色:红色;
字体粗细:粗体;
}
}
}
}
/风格
目标:完成商品组件右下角商品组件的开发
components/MyCount.vue
模板
div class="我的计数器"
按钮类型= button class= BTN BTN灯-/button
输入类型=数字类=表单控制输入
按钮类型=巴顿 class= BTNBTN-莱特/按钮
/div
/模板
脚本
导出默认值{
}
/脚本
style lang=less 范围。我的计数器{
显示器:flex。inp {
宽度:45像素
文本对齐:居中;
边距:0 10px
}。btn,1000 .inp{
变换:缩放(0.9);
}
}
/风格
components/MyFooter.vue
模板
!-底部-
div class=我的页脚
!-全选-
div class=自定义控件自定义复选框
输入类型= checkbox class= custom-control-input id=页脚检查
用于="页脚检查"的label class="自定义控件标签"全选/标签
/div
!-合计-
差异
跨度合计:/span
span class=price 0/span
/div
!-按钮-
按钮类型=按钮 class=页脚-BTN BTN BTN-小学结算(0)/按钮
/div
/模板
脚本
导出默认值{
}
/脚本
style lang=less 范围。我的页脚{
位置:固定;
z指数:2;
底部:0;
宽度:100%;
高度:50px
border-top:1px solid # CCC;
显示器:flex
justify-content:space-between;
对齐-项目:居中;
填充:0 10px
背景:# fff。价格{
颜色:红色;
字体粗细:粗体;
字号:15px
}。页脚-btn {
最小宽度:80px
高度:30px
行高:30px
边框半径:25px
填充:0;
}
}
/风格
4.1 案例-购物车-头部自定义
目的:头部的标题,颜色,背景色可以随便修改,道具类型的校验
思路
在MyHeader.vue中准备小道具里变量,然后使用在使用MyHeader.vue组件时,传入相应的值(颜色和backgroundColor)MyHeader.vue
模板
div class= my-header :style= { background color:background,color}{{ title }}/div
/模板
脚本
//目标:让页眉组件支持不同的项目-自定义
//1.分析哪些可以自定义(背景色,文字颜色,文字内容)
//2.(新)可以对小道具的变量的值进行校验
//3.内部使用小道具变量的值
//4.外部使用时,遵守变量名作为属性名,值的类型遵守
导出默认值{
道具:{
背景:字符串,//外部插入此变量的值,必须是字符串类型,否则报错
颜色:{
类型:字符串,//约束颜色值的类型
默认值: #fff //color变量默认值(外部不给我颜色传值,使用默认值)
},
标题:{
类型:字符串,
必选:true //必须传入此变量的值
}
}
}
/脚本
style lang=less 范围。我的标题{
高度:45像素
行高:45像素
文本对齐:居中;
背景色:# 1d 7 BFF
颜色:# fff
位置:固定;
top:0;
左:0;
宽度:100%;
z指数:2;
}
& ampl
t;/style>
App.vue传入相应自定义的值
<MyHeader title="购物车案例"></MyHeader>
总结:
props: [] - 只能声明变量和接收, 不能类型校验
props: {} - 声明变量和校验类型规则 - 外部传入值不对则报错
4.2 案例-购物车-请求数据
目标: 使用axios把数据请求回来
数据地址: https://www.escook.cn/api/cart (get方式)
下载axios
yarn add axios
main.js - 原型上挂载
// 目标: 请求数据 - 打印
// 1. 下载axios库, main.js - 全局绑定属性 (确保任意.vue文件可以都访问到这个axios方法)
import axios from axios
// 2. 基础地址
axios.defaults.baseURL = "https://www.escook.cn"
// 3. axios方法添加到Vue的原型上
Vue.prototype.$axios = axios
new Vue({
render: h => h(App),
}).$mount(#app)
App.vue请求使用
<script>
export default {
data(){
return {
list: [] // 商品所有数据
}
},
created(){
// 不必在自己引入axios变量, 而是直接使用全局属性$axios
this.$axios({
url: "/api/cart"
}).then(res => {
console.log(res);
this.list = res.data.list
})
}
}
</script>
总结: 利用axios, 调用接口, 把数据请求回来
4.3 案例-购物车-数据渲染
目标: 把上面请求的数据, 铺设到页面上
App.vue
<MyGoods v-for="obj in list"
:key="obj.id"
:gObj="obj"
></MyGoods>
MyGoods.vue
<template>
<div class="my-goods-item">
<div class="left">
<div class="custom-control custom-checkbox">
<!-- *重要:
每个对象和组件都是独立的
对象里的goods_state关联自己对应商品的复选框
-->
<!-- bug:
循环的所有label的for都是input, id也都是input - 默认只有第一个生效
解决: 每次对象里的id值(1, 2), 分别给id和for使用即可区分
-->
<input type="checkbox" class="custom-control-input" :id="gObj.id"
v-model="gObj.goods_state"
>
<label class="custom-control-label" :for="gObj.id">
<img :src="gObj.goods_img" alt="">
</label>
</div>
</div>
<div class="right">
<div class="top">{{ gObj.goods_name }}</div>
<div class="bottom">
<span class="price">¥ {{ gObj.goods_price }}</span>
<span>
<MyCount :obj="gObj"></MyCount>
</span>
</div>
</div>
</div>
</template>
<script>
import MyCount from ./MyCount
export default {
props: {
gObj: Object
},
components: {
MyCount
}
}
</script>
MyCount.vue
<template>
<div class="my-counter">
<button type="button" class="btn btn-light" >-</button>
<input type="number" class="form-control inp" v-model.number="obj.goods_count">
<button type="button" class="btn btn-light" >+</button>
</div>
</template>
<script>
export default {
props: {
obj: Object // 商品对象
}
}
</script>
总结: 把各个组件关联起来, 把数据都铺设到页面上
4.4 案例-购物车-商品选中
问题: 点击发现总是第一个被选中
原来id和for都是"input"
但是id是唯一的啊, 所以用数据的id来作为标签的id, 分别独立, 为了兼容label点击图片也能选中的效果
<input type="checkbox" class="custom-control-input" :id="gObj.id"
v-model="gObj.goods_state"
>
<label class="custom-control-label" :for="gObj.id">
<img :src="gObj.goods_img" alt="">
</label>
总结: lable的for值对应input的id, 点击label就能让对应input处于激活
4.5 案例-购物车-数量控制
目标: 点击+和-或者直接修改输入框的值影响商品购买的数量
<template>
<div class="my-counter">
<button type="button" class="btn btn-light" :disabled="obj.goods_count === 1" @click="obj.goods_count > 1 && obj.goods_count--">-</button>
<input type="number" class="form-control inp" v-model.number="obj.goods_count">
<button type="button" class="btn btn-light" @click="obj.goods_count++">+</button>
</div>
</template>
<script>
// 目标: 商品数量 - 控制
// 1. 外部传入数据对象
// 2. v-model关联对象的goods_count属性和输入框 (双向绑定)
// 3. 商品按钮 +和-, 商品数量最少1件
// 4. 侦听数量改变, 小于1, 直接强制覆盖1
export default {
props: {
obj: Object // 商品对象
},
// 因为数量控制要通过对象"互相引用的关系"来影响外面对象里的数量值, 所以最好传 对象进来
watch: {
obj: {
deep: true,
handler(){ // 拿到商品数量, 判断小于1, 强制修改成1
if (this.obj.goods_count < 1) {
this.obj.goods_count = 1
}
}
}
}
}
</script>
4.6 案例-购物车-全选功能
目标: 在底部组件上, 完成全选功能
思路:
点击获取它的选中状态同步给上面每个小选框 - 而小选框的选中状态又在数组里把数组传给MyFooter, 然后更新即可 - 因为对象都是引用关系的
MyFooter.vue
<template>
<!-- 底部 -->
<div class="my-footer">
<!-- 全选 -->
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="footerCheck" v-model="isAll">
<label class="custom-control-label" for="footerCheck">全选</label>
</div>
<!-- 合计 -->
<div>
<span>合计:</span>
<span class="price">¥ {{ allPrice }}</span>
</div>
<!-- 按钮 -->
<button type="button" class="footer-btn btn btn-primary">结算 ( {{ allCount }} )</button>
</div>
</template>
<script>
// 目标: 全选
// 1. v-model关联全选-复选框(v-model后变量计算属性)
// 2. 页面(视频层)v(true) -> 数据层(变量-) 计算属性(完整写法)
// 3. 把全选 true/false同步给所有小选框选中状态上
// 小选 -> 全选
// App.vue里list数组 -> MyFooter.vue
// isAll的get方法里, 统计状态影响全选框
// 目标: 总数量统计
// 1. allCount计算属性用 数组reduce+判断统计数量并返回
// 目标: 总价
// allPrice计算属性, 数组reduce+单价*数量, 判断选中, 才累加后返回
export default {
props: {
arr: Array
},
computed: {
isAll: {
set(val){ // val就是关联表单的值(true/false)
this.$emit(changeAll, val)
},
get(){
// 查找小选框关联的属性有没有不符合勾选的条件
// 直接原地false
return this.arr.every(obj => obj.goods_state === true)
}
},
}
}
</script>
App.vue
<MyFooter @changeAll="allFn" :arr="list"></MyFooter>
<script>
methods: {
allFn(bool){
this.list.forEach(obj => obj.goods_state = bool)
// 把MyFooter内的全选状态true/false同步给所有小选框的关联属性上
}
}
</script>
总结: 全选的v-model的值, 使用计算属性完整写法
4.7 案例-购物车-总数量
目标: 完成底部组件, 显示选中的商品的总数量
MyFooter.vue
allCount(){
return this.arr.reduce((sum, obj) => {
if (obj.goods_state === true) { // 选中商品才累加数量
sum += obj.goods_count;
}
return sum;
}, 0)
},
总结: 对象之间是引用关系, 对象值改变, 所有用到的地方都跟着改变
4.8 案例-购物车-总价
目标: 完成选中商品计算价格
components/MyFooter.vue
allPrice(){
return this.arr.reduce((sum, obj) => {
if (obj.goods_state){
sum += obj.goods_count * obj.goods_price
}
return sum;
}, 0)
}
总结: 把数组传给了MyFooter组件, 统计总价
面试题
1、Vue 的 nextTick 的原理是什么? (高薪常问)
\1. 为什么需要 nextTick ,Vue 是异步修改 DOM 的并且不鼓励开发者直接接触 DOM,但有时候业务需要必须对数据更改–刷新后的 DOM 做相应的处理,这时候就可以使用 Vue.nextTick(callback)这个 api 了。
\2. 理解原理前的准备 首先需要知道事件循环中宏任务和微任务这两个概念,常见的宏任务有 script, setTimeout, setInterval, setImmediate, I/O, UI rendering 常见的微任务有 process.nextTick(Nodejs),Promise.then(), MutationObserver;
\3. 理解 nextTick 的原理正是 vue 通过异步队列控制 DOM 更新和 nextTick 回调函数先后执行的方式。如果大家看过这部分的源码,会发现其中做了很多 isNative()的判断,因为这里还存在兼容性优雅降级的问题。可见 Vue 开发团队的深思熟虑,对性能的良苦用心。
2、vue生命周期总共分为几个阶段?(必会)
Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
1**)beforeCreate**
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
2**)created**
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer), 属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
3**)beforeMount**
在挂载开始之前被调用:相关的 render 函数首次被调用。
4**)mounted**
el 被新创建的 vm. e l 替 换 , 并 挂 载 到 实 例 上 去 之 后 调 用 该 钩 子 。 如 果 r o o t 实 例 挂 载 了 一 个 文 档 内 元 素 , 当 m o u n t e d 被 调 用 时 v m . el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm. el替换,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内元素,当mounted被调用时vm.el 也在文档内。
5**)beforeUpdate**
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。
6**)updated**
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
7**)activated**
keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用。
8**)deactivated**
keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用。
9**)beforeDestroy**
实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。
10**)destroyed**
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
11**)errorCaptured(2.5.0+ 新增)**
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
3、第一次加载页面会触发哪几个钩子函数?(必会)
当页面第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子函数
写在最后
到此这篇关于一篇文章带你吃透Vue生命周期的文章就介绍到这了,更多相关Vue生命周期内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。