当前位置:网站首页>Vue3 reactive database
Vue3 reactive database
2022-06-30 17:45:00 【twinkle||cll】
Please read the following code carefully , reflection vue3 How to make responsive data ?
let temp
// reactive Is to make an object a proxy
const counter = reactive({
num: 0 });
// effect The main responsibility is to start dependency collection , wait for get To complete the normal dependent storage
effect(() => (temp = counter.num));
// Trigger update
counter.num = 1;
Is there anyone here who wants to say , We are in daily development , Directly in
vueOn the template, there is arefAutomatically helped us with Turn on Rely on collection , When we call get Storage dependency . When things go out of whack, they will
stay vue In the source renderer.ts There is such a code snippet in
const mountComponent: MountComponentFn = (
initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized
) => {
// ... Omit others
// A method will be called here setupRenderEffect
setupRenderEffect(
instance,
initialVNode,
container,
anchor,
parentSuspense,
isSVG,
optimized
)
}
const setupRenderEffect: SetupRenderEffectFn = (
instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized
) => {
const componentUpdateFn = () => {
// Omit component update logic
}
// This passage means to create a ReactiveEffect To save each individual proxy,
// and effect The effect is the same
const effect = new ReactiveEffect(
componentUpdateFn,
() => queueJob(instance.update),
instance.scope // track it in component's effect scope
)
}
Sum up , We are
TemplatesUse inref,reactiveIs such as vue When rendering, it will put the whole component into ReactiveEffect Dependency collection in , Throw out arunMethod ,run Method is used to determine whether dependency collection is required , aboutrefPrepare to deal with ordinary data in another space
reactive
reactive Is used to turn an object into a proxy object ,proxy

function createReactiveObject(
target: Target,
baseHandlers: ProxyHandler<any>,
proxyMap: WeakMap<Target, any>) {
// The core is proxy
// The purpose is to listen to the user get perhaps set The action of
// If you hit it, just return directly
// Optimization points made with cache
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return existingProxy;
}
const proxy = new Proxy(target, baseHandlers);
// Create a good proxy Save it ,
proxyMap.set(target, proxy);
return proxy;
}
effect
effect The collection dependency() function is used to turn on the collection dependency , return run function

export function effect<T = any>(
fn: () => T,
options?: ReactiveEffectOptions
): ReactiveEffectRunner {
const _effect = new ReactiveEffect(fn);
// Merge options
extend(_effect, options);
// When I come in, I execute the opening run Turn on dependency collection
_effect.run();
// hold _effect.run This method returns
// Let the user choose the time to call ( call fn)
const runner: any = _effect.run.bind(_effect);
runner.effect = _effect;
return runner;
}
// stay ReactiveEffect run The content of the function is to enable dependency collection
export class ReactiveEffect {
active = true;
deps = [];
public onStop?: () => void;
constructor(public fn, public scheduler?) {
console.log(" establish ReactiveEffect object ");
}
run() {
// function run When , Can be controlled Do you want to perform the next step of collecting dependencies
// For now , Just execute fn Then the collection dependency is executed by default
// Here we need to control
// Whether to collect dependent variables
// perform fn But do not collect dependencies
if (!this.active) {
return this.fn();
}
// perform fn Collection dependency
// You can start collecting dependencies
shouldTrack = true;
// When executing, give the global activeEffect assignment
// Use global attributes to get the current effect
activeEffect = this as any;
// Execute the fn
const result = this.fn();
// Reset
shouldTrack = false;
activeEffect = undefined;
return result;
}
}
baseHandlers
baseHandlers It's used to deal with proxy Inside get and set Of , When proxy call get and set Will trigger the corresponding function
get The operation flow is as follows :

set The operation flow is as follows :

export const mutableHandlers: ProxyHandler<object> = {
get:(isReadonly = false, shallow = false) {
return function get(target, key, receiver) {
// Get right target Of key Value
const res = Reflect.get(target, key, receiver);
// problem : Why readonly When you don't do dependency collection
// readonly Words , Can not be set Of , That can't be set It means that it will not trigger trigger
// So there is no need to collect dependencies
if (!isReadonly) {
// It's triggering get To collect dependencies
track(target, "get", key);
}
// All that is inside is object All the values are in reactive The parcel , Become a responsive object
// If you say this res Value is an object , So we need to get the res It also translates into reactive
if (isObject(res)) {
// res be equal to target[key]
return isReadonly ? readonly(res) : reactive(res);
}
return res;
};
},
// set Value to trigger
set:(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
// It's triggering set Trigger dependency when
trigger(target, "set", key);
return result;
};,
};
track
stay get When , Notification for dependency collection ,
During dependency collection , Cache incoming objects :

The cache dependency step here is :
- First step : When running
counter.numIt will triggerproxyOfgetMethod - The second step : There is a big picture
targetMapIt's aweakMapTo recordcouter This objectWhether there is , alsoweakMap Of keyyes couter This object , To be is to use , Create if it does not exist ,counterOfvalueAnotherMap, It recordscounter Inside keyandcounter Object's keyIt's one-to-one - The third step : stay
mapMedium judgementkey yes numWhether there is , To be is to use , If it doesn't exist, create aSetTo save the currentReactiveEffectobject ,ReactiveEffectObjects contain run Method wait trigger Trigger
export function track(target, type, key) {
if (!isTracking()) {
return;
}
// 1. Based on target Find the corresponding dep
// If it's the first time , So you need to initialize
let depsMap = targetMap.get(target);
if (!depsMap) {
// initialization depsMap The logic of
depsMap = new Map();
targetMap.set(target, depsMap);
}
let dep = depsMap.get(key);
if (!dep) {
dep = createDep();
depsMap.set(key, dep);
}
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
(activeEffect as any).deps.push(dep);
}
}
trigger
When it comes to track Come on ,trigger What needs to be done will be much simpler
export function trigger(target, type, key) {
const depsMap = targetMap.get(target);
if (!depsMap) return;
// For the time being GET type
// get Type only needs to be taken out
const dep = depsMap.get(key);
// Omit other logic
// Trigger run function
for (const effect of dep) {
if (effect.scheduler) {
// scheduler You can let the user choose the timing of the call
// In this way, you can flexibly control the call
// stay runtime-core in , Is to use scheduler Implemented in the next ticker Logic called in
effect.scheduler();
} else {
// Trigger function
effect.run();
}
}
}
Realize it by yourself
Said so much , It is better to implement a simple responsive system by yourself

边栏推荐
- Cesium-1.72 learning (earth rotation)
- 新技能:通过代码缓存加速 Node.js 的启动
- Exch:修复丢失的系统邮箱
- Cesium-1.72 learning (camera tracking)
- Horizontal visual error effect JS special effect code
- Nodejs learning notes II
- EMQ helps Qingdao Yanbo build a smart water platform
- 4年工作经验,多线程间的5种通信方式都说不出来,你敢信?
- Six pictures show you why TCP has three handshakes?
- 万卷书 - 书单整理 [01]
猜你喜欢
![[Architecture] 1366- how to draw an excellent architecture diagram](/img/98/5dc29e08e91e751f67d910fadc6430.jpg)
[Architecture] 1366- how to draw an excellent architecture diagram

Parker variable displacement piston pump pv092r1k1t1nmmc

如何写一个技术方案

5g has been in business for three years. Where will innovation go in the future?

力士乐液控单向阀Z2S10-1-3X/

China Infrastructure Development Association: electronic contract is recommended

splitting.js密码显示隐藏js特效

Mysql8 NDB cluster installation and deployment

开发那些事儿:Linux系统中如何安装离线版本MySQL?

将 EMQX Cloud 数据通过公网桥接到 AWS IoT
随机推荐
Horizontal visual error effect JS special effect code
【C语言】详解线程 — 多线程进行协同运算
5g business is officially commercial. What are the opportunities for radio and television?
大文件处理(上传,下载)思考
水平视觉错误效果js特效代码
零基础也能做Apple大片!这款免费工具帮你渲染、做特效、丝滑展示
分享 5 大常用的特征选择方法,机器学习入门必看!!!
Six pictures show you why TCP has three handshakes?
编译生成busybox文件系统
[sword finger offer] 52 The first common node of two linked lists
中基协:推荐使用电子合同
浅析搭建高速公路视频监控平台的建设方案及必要性
Solution: STM32 failed to parse data using cjson
【架构】1366- 如何画出一张优秀的架构图
5g has been in business for three years. Where will innovation go in the future?
Generate confrontation network, from dcgan to stylegan, pixel2pixel, face generation and image translation.
Mysql8 NDB cluster installation and deployment
理解现货白银走势的关键
Acwing game 57
parker比例溢流阀RS10R35S4SN1JW