生命周期
- beforeCreate、created 可以被setup取代掉
- onMounted onBeforeMount 都变成了函数式API onMounted(()=>{})
- onBeforeUpdate onUpdated
Vue3 Vue有些什么内容
vue3 = 【runtime-dom】+【runtime-core】+【reactivity】
- 【compiler-dom】 + 【compiler-core】
组件嵌套,每个组件都有setup如何知道 setup里面的生命周期是隶属于哪个setup的 (闭包+科礼化)
让每个组件实例收集对应的钩子,这些钩子可以收集多个。一个实例可以收集多个钩子。
javascript
runtime-core
component.ts
// 对外暴露的当前组件的实例
export let currentInstance = null;
// 设置当前组件的实例
export let setCurrentInstance = (instance) => {
currentInstance = instance;
};
// 获取当前组件的实例
export let getCurrentInstance = () => { // 在setup期中获取到当前组件的实例的句柄
return currentInstance;
}
setupStatefulComponent(instance){
// 组件初始化的时候会调用setup
// 在调用setup之前就知道当前是哪个组件把instance保留一下【组件实例】
currentInstance = instance;
const setupReult = xxxxx
// 初始化完了清空
currentInstance = null;
}
创建自己的生命周期
为生命周期创建钩子
创建apishengmingzhouqi.ts
typescript
// 定义一个enum
const enum shengming {
BEFORE_MOUNT = 'bm',
MOUNTED = 'm',
BEFORE_UPDATE='bu',
UPDATED='u'
}
// 生成这些方法
import {currentInstance} from "./component.ts"
// 上面定义的那个全局的currentInstance 这个可能不存在为啥因为有些钩子可能要在字组件执行完毕后才有,那个时候instance=null了;
// 比如onMounted 应该是拿自己的 instance因为有子组件所以就被充掉了 怎么解决用闭合包 target = instance
// 通过科礼化函数创建
export const onBeforeMount = createHook(shengming.BEFORE_MOUNT)
export const onMounted = createHook(shengming.MOUNTED)
export const onBeforeupdate = createHook(shengming.BEFORE_UPDATE)
export const onUpdated = createHook(shengming.UPDATED)
export const createHook = (type = '') => {
return (hook = () => {}, target = instance) => { // target 用来标识它是哪个实例的,哪个组件的。闭包准确的知道当前组件的实例。
// 给当前实例增加对应的生命周期
// 给type这个生命周期,注入hook这个钩子,注入到target这个对象上
injectHook(type, hook, target)
}
}
const injectHook = (hookName = '', userFunc = () => {}, target = null) => {
if(target) {
// 给当前的实例上挂上这么个钩子
// 因为可能重复写都要放到数组里面去
const funcs = target[hookName] || (target[hookName] = []);
const wrap = () => { // 为了用闭包数据
setCurrentInstance(target); // currentInstace就变成当前这个的了。每次调用钩子只用当前闭包里面的这个当前实例
// 在这里改了
userFunc.call(target); // 在这里用 getCurrentInstance 就可以拿到当前组件实例。
setCurrentInstance(null); // 调用完了在复位。
// 在components 内部执行完了setup就清空了 currentInstance
}
funcs.push(wrap);
} else {
// 抛出异常
console.warn("error.......")
}
}
// 父的
import {getCurrentInstance} = vue;
onMounted(()=>{
// 这里的这个实例是谁?
// 在这里拿到的currentInstance对不对如果有子组件就不对了被充了。这里也没有闭包。这里的是儿子。
// 为了解决这个问题需要在component.ts在提供2个方法转到上面get set
// 拿到了组件的实例
const ci = getCurrentInstance();
})
// vue的代码用科礼化用的多
javascript
// 都绑定在组件了该如何调用他们?
apishengmingzhouqi.ts
// 执行该声明周期上的所有钩子函数。
export const invokeArrayFns = (fns) => {
fns.forEach(item => {
item();
})
}
在哪里用?
scss
// renderer.ts
setupRenderEffect 中用 // 第一次渲染。
if(!instance.isMounted){
const {bm, m} = instance // 因为初始化的时候已经在setup执行了
if(bm) {
invokeArrayFns(bm);
}
patch完毕了 // 这里不能保证子组件的执行完毕
// 这里会有问题
// 啥问题?
if(m) { // mounted要求子组件都执行完毕。 这个玩意需要延迟到子组件执行完毕了。
invokeArrayFns(m);
}
} else {
const {bu, u} = instance
if(bu){
invokeArrayFns(bu);
}
patch(...)更新
// 更新也是这么个事如果更新怎么知道子组件也完成了。
if(u){
invokeArrayFns(u);
}
}
// 这里没有考虑子组件