当前位置:网站首页>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

边栏推荐
- 美国PARKER派克传感器P8S-GRFLX
- Generate confrontation network, from dcgan to stylegan, pixel2pixel, face generation and image translation.
- Property or method “approval1“ is not defined on the instance but referenced during render
- Course design for the end of the semester: product sales management system based on SSM
- Cesium-1.72 learning (eagle eye map of the earth)
- Daily question brushing record (IX)
- Design and principle of tubes responsive data system
- How can you choose to work in the county after graduation?
- 墨天轮沙龙 | 清华乔嘉林:Apache IoTDB,源于清华,建设开源生态之路
- MySQL之零碎知识点
猜你喜欢

JS from prototype chain to inheritance

Analysis on the construction scheme and necessity of constructing expressway video monitoring platform

How to write a technical proposal

Booking UI effect implemented by svg

Key to understanding the trend of spot Silver

美国PARKER派克传感器P8S-GRFLX

Canvas mouse control gravity JS effect

零基础也能做Apple大片!这款免费工具帮你渲染、做特效、丝滑展示

3D chart effectively improves the level of large data screen

New skill: accelerate node through code cache JS startup
随机推荐
[C language] explain threads - start two threads
k线图快速入门必读
Write the simplest small program in C language Hello World
理解现货白银走势的关键
svg实现的订票UI效果
墨天轮沙龙 | 清华乔嘉林:Apache IoTDB,源于清华,建设开源生态之路
Servlet运行原理_API详解_请求响应构造进阶之路(Servlet_2)
Fragmentary knowledge points of MySQL
【Proteus仿真】Arduino UNO利用74LS148扩展中断
Combination of applet container and Internet of things
知名互联网房屋租赁服务公司物联网关键业务迁移上云实践
高等数学(第七版)同济大学 总习题一 个人解答
24: Chapter 3: develop pass service: 7: user defined exceptions (to represent errors in the program); Create graceexceptionhandler to handle exceptions globally and uniformly (build JSON data of corre
商鼎雲新版來襲 | 收藏夾功能已上線,滿足個人使用需求
Ningx 1.20.2
Network: principle and practice of server network card group technology
【C语言】详解线程 — 通过 “加锁” 解决并发程序引起的共享内存问题
水平视觉错误效果js特效代码
Tubes响应性数据系统的设计与原理
4年工作经验,多线程间的5种通信方式都说不出来,你敢信?