Handwritten a mini Vue framework

The main function of the responsive mechanism is that it can encapsulate common JavaScript objects into responsive objects, intercept data acquisition and modification operations, and realize automatic data-dependent updates.

In the simplest responsive model, we can use reactive or ref functions to wrap data into responsive objects, and register callback functions through effect functions, and then notify effect to execute callback functions responsively after data modification.

Vue's responsiveness can be used independently on other platforms. For example, you can create a new test.js and use the following code to use Vue response in the node environment. Taking reactive as an example, after we use reactive to wrap the JavaScript object, every time we modify the reactive object counter, the function registered inside the effect will be executed:


const {
    
    effect, reactive} = require('@vue/reactivity')

let dummy
const counter = reactive({
    
     num1: 1, num2: 2 })
effect(() => {
    
    
  dummy = counter.num1 + counter.num2
  console.log(dummy)// 每次counter.num1修改都会打印日志
})
setInterval(()=>{
    
    
  counter.num1++
},1000)

import {
    
     effect } from '../effect'
import {
    
     reactive } from '../reactive'

describe('测试响应式', () => {
    
    
  test('reactive基本使用', () => {
    
    
    const ret = reactive({
    
     num: 0 })
    let val
    effect(() => {
    
    
      val = ret.num
    })
    expect(val).toBe(0)
    ret.num++
    expect(val).toBe(1)
    ret.num = 10
    expect(val).toBe(10)
  })
})

export function reactive(target) {
    
    
  if (typeof target!=='object') {
    
    
    console.warn(`reactive  ${
      
      target} 必须是一个对象`);
    return target
  }

  return new Proxy(target, mutableHandlers);
}

const get = createGetter();
const set = createSetter();

function createGetter(shallow = false) {
    
    
  return function get(target, key, receiver) {
    
    
    const res = Reflect.get(target, key, receiver)
    track(target, "get", key)
    if (isObject(res)) {
    
    
      // 值也是对象的话,需要嵌套调用reactive
      // res就是target[key]
      // 浅层代理,不需要嵌套
      return shallow ? res : reactive(res)
    }
    return res
  }
}

function createSetter() {
    
    
  return function set(target, key, value, receiver) {
    
    
    const result = Reflect.set(target, key, value, receiver)
    // 在触发 set 的时候进行触发依赖
    trigger(target, "set", key)
    return result
  }
}
export const mutableHandles = {
    
    
  get,
  set,
};

const targetMap = new WeakMap()

export function track(target, type, key) {
    
    

  // console.log(`触发 track -> target: ${target} type:${type} key:${key}`)

  // 1. 先基于 target 找到对应的 dep
  // 如果是第一次的话,那么就需要初始化
  // {
    
    
  //   target1: {//depsmap
  //     key:[effect1,effect2]
  //   }
  // }
  let depsMap = targetMap.get(target)
  if (!depsMap) {
    
    
    // 初始化 depsMap 的逻辑
    // depsMap = new Map()
    // targetMap.set(target, depsMap)
    // 上面两行可以简写成下面的
    targetMap.set(target, (depsMap = new Map()))
  }
  let deps = depsMap.get(key)
  if (!deps) {
    
    
    deps = new Set()
  }
  if (!deps.has(activeEffect) && activeEffect) {
    
    
    // 防止重复注册
    deps.add(activeEffect)
  }
  depsMap.set(key, deps)
}

The main function of responsiveness is to encapsulate ordinary JavaScript objects into responsive objects, collect function dependencies through track when reading data, and store the dependencies of the entire object and effect registration functions in a dependency graph .

In daily project development, you can also learn from the idea of ​​responsive processing, use the notification mechanism to call the operation and update logic of specific data, and flexibly use functions such as effect, ref, and reactive to turn all common operations into responsive data processing. It will greatly improve our development experience and efficiency.

It's late at night, I haven't finished writing, if you have any questions, please private message me...

Guess you like

Origin blog.csdn.net/weixin_44659309/article/details/130469248