Skip to content

Vue2.x 生命周期

JavaScript
deforeCreate    // 实例初始化之前 数据观测(data,observer)
created			// 实例创建之后调用
beforeMount		// 在挂载之前调用,DOM生成之前 template解析					完成
mounted			// 挂载成功调用,可以操作DOM结构
beforeUpdate	// 更新之前调用
updated			// 更新之后调用,可以获取更新后的值
activated		// 在组件激活时调用,keep-alive
deactivated		// 在组件缓存时调用,keep-alive
beforeDestroy	// 在组件销毁之前调用,可以进行一些清理工作
destroyed		// 在组件销毁之后调用,实例、事件监听等以及清					理了
errorCaptured   // vue2.5引入,可以用来获取组件渲染的错误,					或无法使用try-catch捕获的错误。
方法作用
beforeCreate()在创建之前调用,这时候数据、方法、Dom 都未创建无法访问
created()在创建之后调用,这个时候可以访问数据、方法、计算属性等
beforeMount()挂载之前调用,dom 挂载阶段之前,此时组件的 template 已经解析完成,但还未生成真正的 DOM 节点。
mounted()挂载之后调用,这时候的 Dom 树已经构建完成,可以对 DOM 结构进行操作
beforeUpdate()在更新之前调用,可以在这里进一步改变数据。注意避免进入死循环的情况
updated()在更新之后调用,在这里可以获取到更新后的 DOM 元素的状态
beforeDestroy()在组件被销毁之前调用,此时组件实例依旧可以正常访问,可以进行一些清理工作 可以通过 v-if 进行销毁操作
destroyed()在组件销毁之后调用,组件实例已经被清理掉了,事件监听等已经被清除
activated()在组件被激活时触发,keep-alive
deactivated()在组件被缓存时触发,keep-alive
errorCaptured()【er rou--ka pu to er de】(Vue2.5 版本引入的)用来捕获子组件的渲染错误和无法被 try-catch 捕获到的错误
serverPrefetchvue 2.6 引入 , 用于服务器端渲染(SSR)场景

生命周期中请求数据

发送请求应该在哪个生命周期阶段,created 还是 mounted?

sh
1. 具体问题具体分析,需要根据项目需求来动态的选择
2. 如果子父组件的数据有依赖关系,根据依赖关系,使用created还是mounted
2. 如果需要再子组件渲染之前调用 可以在created阶段,如果是在子组件之后执行可以再mounted阶段

在 created 中如何获取 DOM

sh
1. 可以通过异步代码实现,
	例如setTimeout、this.$nextTick、等等
2. 使用vue内置的this.$nextTick,
3. 利用事件循环中异步任务需要等待同步执行完成之后执行,异步任务的执行时机是在mounted中的最后执行,此时DOM结构以及挂载完毕。

为什么不在 beforeCreate 中发送 Ajax 请求

sh
1. beforeCrate 在创建之前调用,此时属性和方法还没有创建,即使获取到了数据,也无法进行保留。
2. 一般请求的方法是封装在methods中的,在befroeCreate阶段 是拿不到请求方法的,没有进行实例化创建方法和属性,
3. 结果会因为找不到对应方法 --- 产生报错

beforeCreate 和 created 的区别

sh
1. beforeCreate阶段没有实例化数据对象($data)和DOM结构($el)
2. created阶段实例化了数据对象,但没有实例化DOM结构,可以在该阶段请求和访问数据,但没挂载DOM

生命周期执行顺序

创建阶段 父组件引入子组件的生命周期执行顺序

sh
父: beforeCreate、created、beforeMount、
子: beforeCreate、created、beforeMount、mounted .....
父: mounted、

更新阶段 父组件引入子组件的生命周期顺序

sh
父: beforeUpdate
子: beforeCreate、created、beforeMount、mounted
父: updated

更新阶段 更新父子组件

sh
父: beforeUpdate
子: beforeUpdate、updated
父: updated

子组件更新

sh
父:
子: beforeUpdate、updated
父:

生命周期中异步任务的执行

异步任务在生命周期中执行是事件顺序

sh
1. 在created中定义的 Promise、setTimeout、nextTice
2. promise在beforeMount中第一时间执行,.the在mounted执行
3. setTimeout在mounted阶段执行了 this.$nextTick之后执行的
4. nextTick在mounted阶段执行

keep-alive

keep-alive 是用来缓存当前组件的

加入 keep-alive 会新增两个生命周期函数,

!!! 触发的是被切换子组件内部的 keep-alive,不是写 keep-alive 的父页面

sh
1. 相关生命周期
activated 		在组件被激活时触发
deactivated 	在组件被缓存时触发

keep-alive 的使用场景

sh
1. 场景一  列表数据的详情页
	1. 我们可以记录 请求的id 缓存
	2. 再次退出和进入详情页时 相同的id不再进行请求

常用到的生命周期

sh
1. 需要根据不同的业务场景,去动态的进行选择使用
2. created 		可以在子组件之前请求数据
3. methods 		可以在子组件之后请求数据
4. activated 	使用keep-alive的时候可以用到
5. destoryed

组件通信

父子通信

sh
父传给后端
1. <Child v-bind:str='String'></Child>
子组件通过Props进行接收
props:{
	str:{
		type:String
		default:''
	}
}
父组件通过 v-bind将数据绑定到子组件标签上,子组件通过prpse接收

子父通信

sh
子传给父
1. <Child @getName='getName'></Child>
子组件通过$emit
this.$emit('getName','明楼')

跨层级通信 ===>注入 provide

sh
1. 通过 provide/inject ===> 依赖注入
父:
	provide:{
		msg:"属性"
		Func:()=>{
			console.log("方法")
		}
	}
 || 孙:
	inject:["msg",'Func']

2. 缺点是不太好找到是谁传递的(不知道是父亲还是祖先传递的)

兄弟组件通信

sh
1. 通过全局事件总线 eventBus
	1. 在通用文件中创建eventBus
	2. const eventBus = new Vue() 创建一个空的Vue示例
	3. 使用的组件import调用该文件
	3. 通过this.$emit('注册的事件名',"传递的数据")
	4. EventBus.$on('注册的事件名',(传递的数据)=>{})
	5. 通过EventBus.$off("关闭注册的事件名")

2. 通过父组件进行通信
	1. 将共同的父组件作为中转站,实现兄弟组件的通信

3. Vuex
	1. 见下文

Vuex

sh
1. 五个核心模块: state、getters、mutations、actions、modules
2. state:作用类似data 存储状态
3. getters:作用类似于computed,能缓存数据
4. mutations:执行同步方法,修改state的唯一方式
5. actions: 执行异步代码
6. modules:可以将复杂应用拆分为多个state,每个state都有自己的上述四项。相互独立,

父组件直接修改子组件的值

sh
1. <Child ref="Child"></Child>
2. this.$refs.Child.xxx = "xxxx"

子组件如何直接使用和修改父组件的值

sh
子组件可以使用:this.$parent.$data.name.xxx去使用和修改

如何找到父组件

sh
this.$parent

如何找到跟组件

sh
this.$root

keep-alive原理

nextTick原理

作用

sh
nextTick的作用是获取更新后的DOM

原理

sh
1. nextTick在Vue中的具体实现分为两部分: 一是判断当前环境能使用的异步API并保存异步函数, 二是调用异步函数执行回调
2. nextTick核心是利用了Promuise.then,MutationObserver、setImmediate、setTimeout。通过判断进行进行降级操作,根据当前环境支持什么方法调用哪个,
3.在nextTick源码中,
	- nextTick收一个回调函数和一个执行上下文作为参数,		- nextTick会将传入的回调放到一个叫callbacks数组中,等待执行。 
	- 若当前没有正在pending的任务,调用 timerFunc 函数根据当前环境决定使用哪种异步任务机制来安排 flushCallbacks 函数的执行,
	- timerFunc会根据当前环境,对Promuise.then,MutationObserver、setImmediate、setTimeout异步方法。进行降级操作当前环境支持什么方法调用哪个
	- flushCallbacks 函数负责实际执行 callbacks 数组中的回调函数。在执行前先复制一份回调数组并清空原始数组,这样可以确保在执行回调的过程中如果有新的 nextTick 调用会被添加到下一轮任务队列中
	- 如果没有传入回调函数但环境支持Promise,nextTick会返回一个Promise实例,待DOM更新后异步resolve

keep-alive原理

作用

sh
1. keep-alive 是vue中的一个全局组件
2. keep-alive 最重要的功能就是缓存组件

原理

sh
1. keep-alive 组件内部维护了一个对象 cache 保存以及加载过的组件。每个缓存的组件都有一个对应的key作为唯一标识符。
2. 当组件进出 keep-alive 包裹区域时,不是简单地销毁和重新创建,而是依据 activated deactivated 生命周期钩子进行状态激活和停用。对于不再需要缓存的组件,通过 pruneCache 函数移除其在缓存中的记录,并调用组件实例的 $destroy 方法释放资源。
3. keep-alive 组件接受 include exclude 属性作为过滤条件,这两个属性可以是字符串、正则表达式或数组,用于确定哪些组件需要缓存或排除缓存。matches 函数根据这些规则判断组件名称是否满足缓存条件。
4. 当设置了最大缓存数(max 属性)时,keep-alive 实现了类似LRU(Least Recently Used,最近最少使用)缓存淘汰策略,即当缓存满时,最久未访问的组件实例将被淘汰。
5. 在组件的生命周期钩子中,keep-alive 监听 include exclude 属性的变化,并据此调整缓存。在组件挂载和更新时,它会检查当前激活的组件是否符合缓存条件,并决定是否将其加入缓存或者从缓存中读取。
6.在渲染阶段,keep-alive 会对获取到的子组件VNode进行检查,判断是否符合缓存条件。符合条件的组件,其实例会被缓存起来,并在后续进入时从缓存中读取,同时标记该组件实例的 keepAlive 属性为 true,表明它处于缓存状态。

Vuex原理

sh
1. Vuex 的核心是一个名为 store 的对象,它集中包含了整个应用的状态树。状态树中的状态都是响应式的,当状态发生变化时,依赖这些状态的 Vue 组件会自动更新。
2. Vuex 中的状态是整个应用共享的数据源,所有的组件都可以通过 store.state 访问到。为了保证状态的可控性,Vuex 禁止直接修改状态,必须通过特定的 mutation 函数来更改状态。
3. 变更状态的唯一方式是提交 mutation。每个 mutation 都是一个纯函数,它描述了状态如何改变。提交 mutation 时需要通过 store.commit 方法,并附带上对应的 mutation 名称和要变更的数据。
4. Actions 用于处理异步逻辑和包含多个 mutation 的事务,它们可以调用 mutation 函数进而改变状态,也可以通过 dispatch 方法触发其他 action。Actions 通常与外部 API 交互,完成请求后再触发相应的 mutation 更新状态。
5. Getters 类似于 Vue 的计算属性,用于从 store 中派生状态,可以认为是对 state 的包装和计算。Getters 可以用于优化和组织状态的读取,使得在多处使用相同状态计算逻辑时无需重复编写。
6.  Vuex 允许我们将状态管理划分为多个模块,每个模块都包含自己的 state、mutations、actions getters,这样可以更好地组织大规模项目的状态。
7. uex 利用了 Vue.js 的响应式系统来监听和追踪 state 的变化,当 state 发生变化时,Vue.js 会自动触发相关的组件更新,保证视图与状态的一致性。同时,Vuex 也运用了发布-订阅模式来分发和处理 action mutation,确保状态修改的有序性和可追踪性。

Vue-Router

作用

sh
Vue Router Vue.js 官方推荐的路由管理器,用于构建单页面应用程序(SPA),它通过监听 URL 变化来更新视图。

原理

sh
1. Vue Router 的原理基本上可以分为两个部分:路由的注册和路由的匹配。
2. 在匹配路由时,Vue Router 采用了深度优先遍历算法,将路由表中的路径表示成一棵树形结构,然后依次匹配每一个节点。在这个过程中,Vue Router 使用了多种匹配技术,如精确匹配、模糊匹配等,以便根据 URL 变化来正确地渲染视图。
3. Vue Router 的原理是基于路由的注册和路由的匹配实现的,利用了 Vue 的响应式系统和浏览器的 History API,实现了对视图的动态更新和路由导航控制,从而提高了应用程序的可维护性和可用性。
4. URL 发生变化时,Vue Router 通过监听浏览器的 popstate 事件,并根据 URL 的变化来调度不同的组件进行渲染,实现了路由与组件之间的绑定。同时,Vue Router 也提供了多种路由的导航控制方法,如 push、replace、go、back、forward 等,以方便开发者控制应用程序的导航流程。

靠谱点的

sh
router的原理

Hash模式
	hash模式是vue-router的默认路由模式,它的标志是在域名之后带有一个#
	可以通过window.location.hash获取到当前url的hash:。hash模式下,不会重新加载页面。当URL中的哈希值发生变化时,浏览器会触发hashchange事件,Vue监听这个事件进行路由切换,Vue路由会根据URL中的哈希值匹配路由配置,找到相应组件进行染。单页面应用必备。
	Hash模式的特点:
		i.兼容性好,支持低版本浏览器
		ii.hash变化会在浏览器的history中增加一条记录,可以实现浏览器的前进和后退功能。
		iii.Hash模式的缺点:由于会在后边加一个#,影响美观。

History模式
	History模式是基于html5的history对象,兼容性差,不支持低版本浏览器。
	通过location.pathname获取到当前url的路由地址:
	history模式下,通过pushState和replaceState方法改变浏览器地址栏的URL,同时不刷新页面,当URL发生变化时,浏览器会触发popstate事件,然后Vue监听该事件进行相应的路由切换,Vue路由会根据URL匹配路由配置,找到对应的组件进行渲染。
	History模式特点:
		i.方便,可读性强
		ii.更加美观
		iii.History模式缺点:用户刷新或直接输入地址会向服务器发送请求;需要服务器端支持。

实现步骤:
	a.安装并使用插件
	b.创建router实例
	c.在根组件上添加实例
	d.添加路由视图
	e.导航 使用router-link

router-view 组件与路由渲染:
	a.通过Vue.observable在router实例上创建一个保存当前路由的监控对象current.
	b.当浏览器地址发生变化时,修改监控对象current
	c.在router-view组件中监听监控对象current的变化当current变化后,获取用户注册的相应component,并利用h函数将component渲染成vnodes,进而更新页面视图。

Router-link 组件与路由跳转
	Router-link组件通过参数to设置目标路由,tag参数负责组件在页面上染的标签,默认为a标,replace参数则负责控制在路由跳转时是否使用replace方法。

常用的表单修饰符

目录

sh
1. 表单修饰符
2. 事件修饰符
3. 鼠标按键修饰符
4. 键值修饰符
5. v-bind修饰符

表单修饰符

sh
**应用与V-model**
1. lazy: <input type="text" v-model.lazy="value">
	"当光标离开时,才会将值赋予给value,也就是Chagne事件之后"
2. trim: <input type="text" v-model.trim="value">
	"自动过滤用户输入的空格字符"
3. number: <input v-model.number="age" type="number">
	"会将用户的值转化为数值类型,如果无法被 parseFloat 解析,则会返回原来的值"

事件修饰符

sh
1. stop: <button @click.stop="shout(1)">ok</button>
	"阻止事件冒泡,相当于调用了event.stopPropagation
	【stop Pro pe gei shen】"
2. prevent:<form v-on:submit.prevent="onSubmit"></form>
	"阻止事件的默认行为相当于调用了event.preventDefault方法"
3. self:<div v-on:click.self="doThat">...</div>
	"当前元素自身时触发处理函数,"
4. once: <button @click.once="shout(1)">ok</button>
	"只会触发一次,第二次就不会触发了"
5. native : <my-component v-on:click.native="doSomething"></my-component>
	"在自定义标签中默认只能监听自定义事件,监听原生事件,需要通过native"
6. passive: <div v-on:scroll.passive="onScroll">...</div>
7. capture:
	"使事件触发从包含这个元素的顶层开始往下触发"

鼠标按钮修饰符

sh
1. left  	左键点击 <button @click.left="shout(1)">ok</button>
2. right 	右键点击 <button @click.right="shout(1)">ok</button>
3. middle 	中间点击 <button @click.middle="shot(1)">ok</button>

键盘修饰符

sh
1. 普通键(enter、tab、delete、space、esc)
2. 系统修饰键(Ctrl、alt、shift...)

v-bind 修饰符

sh
1. sync
	能对props进行一个双向绑定
    //父组件
    <comp :myMessage.sync="bar"></comp>
    //子组件
    this.$emit('update:myMessage',params);
    "子组件传递的事件名格式必须为update:value,其中value必须与子组件中props中声明的名称完全一致"
2. prop
	<input id="uid" title="title1" value="1" :index.prop="index">
	设置自定义标签属性,避免暴露数据,防止污染HTML结构
3. camel
		将命名变为驼峰命名法,如将view-Box属性名转换为 viewBox
		<svg :viewBox="viewBox"></svg>

应用场景

sh
1. stop:阻止事件冒泡
2. native:绑定原生事件
3. once:只执行一次
4. self:将事件绑定在自身身上,相当于阻止事件冒泡
5. prevent:阻止默认事件
6. caption:用于事件捕获
7. KeyCode:监听特定按键按下
8. right:右键

Vue2和vue3的区别

sh
1. 双向数据绑定原理不同
	-	vue2:Object.defineProperty,数据劫持结合发布订阅模式,缺点是只能对属性进行监听,对对象类型需要进行递归转化,重写了7个数组方法
	-	vue3:使用ES6的proxy代理模式,为数据对象包裹一层拦截,对外界的访问进行处理。proxy对对象类型更加友好,可以直接处理对象类型,不需要对数组方法进行重写
2. vue3支持碎片化,
	-	vue3可以有多个根节点,vue2只能有一个根节点
3. API不同
	-	vue2是选项式API:我们在固定区域内定义属性和方法,
	-	Vue3是组合式API:
4. 生命周期不同
	-	vue3中setup替代了beforeCreate,created
	-  	销毁阶段的beforedestroy、destroyed变为了onbeforeUmMount,onUmmounted

vue3自定义hooks

sh
1. vue3自定义hooks本质就是函数封装
2. use开头
3. 需要明确的参数类型和返回值
4. 进行逻辑功能的抽取,实现功能复用。

5. 封装hooks

V2 与 V3---V-Model 的区别

sh
1. Vue2的v-model本质是一个语法糖,Vue3的v-moel是一个全局指令
2. 通过V-Model进行组件传值时,
3. Vue2绑定多个值的时候需要手动指定绑定的prop的值和event
Vue3中,v-model可以直接绑定多个值

V2与V3 --- Watch的区别

sh
1. vue2中watch作为一个选项式API,vue3中watch作为一个单独的函数使用
2.

虚拟 DOM

什么是虚拟 DOM

sh
虚拟DOM是对真实DOM的抽象,以JavaScript对象作为对象的属性来描述节点,最终将其映射到真实环境上。

知识点:
	1. 虚拟DOM不会提升效率

为什么 Vue 和 React 需要虚拟 DOM

sh
1. 框架设计的理念是基于数据驱动的,
 	- 如果不使用虚拟DOM每次数据变化时,都会触发页面的重新渲染,浪费性能。
 	- 而虚拟DOM是对真实DOM的一种抽象,使用JavaScript对象来模拟真实DOM,框架可以更轻松地跟踪和管理页面的状态

2. 跨平台性的需要,虚拟DOM是对真实DOM用JavaScript对象的一种抽象

虚拟 DOM 的好处

sh
1. diff算法,减少JavaScript操作真实DOM带来的性能消耗.
2. 虚拟DOM的最大优势在于,抽象了渲染过程.实现了跨平台性.

Vue2 的响应式原理

sh
1. Vue 2 的响应式系统是通过数据劫持结合发布订阅者模式实现的。
2. Vue 中的响应式系统分为三个部分:Observer、Watcher 和Dep(dependency) 
3. 组件初始化时,Observer会对data中的每个数据对象使用 Object.defineProperty() 来劫持其中的各个属性,进行递归转换,使其成为响应式的Observer对象。在每个属性上设置 getter setter。当读取属性时触发 getter,当给属性赋值时触发 setter。
4. 在视图解析环节,Vue会为每一个使用响应式数据的区域,创建一个订阅者Watcher
5. Dep对象用来管理Watcher,进行Wather依赖的收集,通知wather执行更新回调
6. 在组件渲染过程中,当通过 getter 读取属性时,Dep会进行依赖收集,将触发了 getter Watcher 收集到对应依赖列表中。
7. 当响应式数据属性变化时,会触发对应的 setter,进行派发更新,Dep通知所有依赖于该属性的 Watcher 执行更新操作,从而更新视图。

扩充:
8. Observer对对象进行劫持时,会为对象的每个属性创建getter和setter
9. 对数组也进行了类似的操作,对数组的方法和属性添加了getter和setter,重写了7个数组方法,push,pop、shift、unshift、sort、reverse、splice

data

Vue3 响应式原理

sh
1. vue3的响应式是基于ES6的Proxy结合Reflect实现的
2. Proxy对目标对象设置了一层拦截,外界访问该对象的时候,都必须通过这层拦截,对外界的访问,进行过滤和改写。
3. Proxy接收两个参数 target handler
	- target: 代理的目标对象(可以是任何类型的对象,像是原生数组啊,函数,甚至是另一个proxy代理对象)
	- handler:接收一个函数作为属性的对象,执行各种代理操作,get、set、deleteProperty
4. get可以拦截访问请求
5. set可以拦截响应请求
6. delete可以拦截删除的请求

使用track trigger 进行依赖收集和派发更新

Vue3 Vue2 响应式原理

sh
1. vue2采用的是ES5的Object.defineProperty,Vue3采用的是Proxy API进行的代理。
2. Vue2使用的Object.defineProperty,对对象进行劫持只能劫持预先定义好的数据,需要使用Vue.Set. 数组只能操作七钟方法,

Vue 模版的实现

sh

Vue-Router

sh
1. 前端路由有两种模式:hash模式和history模式

hash模式

sh
1. hash模式是一种把前端路由的路径用"#"号拼接在真实的URL后面的模式,
当井号后面的路径发生变化的时候,浏览器不会发起请求,而是会触发hashchange事件

2. 优点
	- 浏览器兼容性比较好,支持IE8
3. 缺点
	- 路径在井号后面,不是很雅观

history模式

sh
1. history API 是H5提供的新特性,允许开发者直接更改前端路由,即更新浏览器URL地址而不重新发起请求

2. 具有back、forward和go方法

优点:
	- 路径比较正规
	- 兼容性不如hash,且需要服务端的支持,否则一刷新页面就404了

Pinia

Vue3 自定义 Hooks 的使用和应用场景

React 自定义 hooks

Vue3, ref reactive 如何实现

React Redux 的实现

React Hooks 的实现

React 性能优化 组件缓存

Vue 数据响应式的原理

repos,js hodelais

项目流程

第一个 第二个

优化,基于用户体验

图片懒加载,

预加载,

什么是 Vue 的响应式

Vue 响应式设计的初衷是为了实现数据和函数的联动

在具体的 vue 开发中,数据和组件的 render 函数关联在一起,从而实现了 自动运行的 render

项目优化

sh
 keep-alive
1.案例一   activated 的使用
	keep-alive 列表数据的详情页
	1. 第一次会发起请求,并记录请求的id
    2. 再次进入相同页面如果id相同,不再进行请求数据

    类似这样来来进行实现
    activated() {
        console.log(this.stop);
        if (this.stop) {
            this.age++
            this.stop = false
        }
    },

2. 案例二
	注册和登录组件页面的切换
	通过keep-alive 缓存input框中输入的内容,提升体验