首页 > 其他分享 >响应式原理(Vue3、Vue2)

响应式原理(Vue3、Vue2)

时间:2024-04-28 11:11:18浏览次数:29  
标签:const target depsMap effect 响应 Vue2 key Vue3 new

1.Vue3

副作用函数(onMounted、watchEffect)

帮助管理组件中的副作用逻辑,并自动追踪其依赖关系,以确保在数据变化时能够自动触发副作用函数的更新。

会自动追踪被其内部函数引用的响应式数据。当这些数据发生变化时,Vue 3 会自动重新运行副作用函数,确保副作用与数据的状态保持同步。

let activeEffect
// 副作用函数
export const effect = (fn) => {
    const _effect = function () {
        activeEffect = _effect
        fn()
    }
    _effect()
}

 

收集依赖

通过proxy里的调用收集依赖

 

 

// 收集依赖
const targetMap = new WeakMap()
export const track = (target, key) => {
    // WeakMap 
  // key为对象, 即target
  // value 为一个new Map()
    // {
    //   key:{
    //     name: "名字",
    //     age: 18
    //   },
    //   value: {
    //     name: new Map(),
    //     age: new Map()
    //   }
    // }
    let depsMap = targetMap.get(target)
    if (!depsMap) {
        depsMap = new Map()
        targetMap.set(target, depsMap)
    }
    // 现在添加new Map()
  // key为属性名称, 即key
  // value为一个new Set()
    let deps = depsMap.get(key)
    if (!deps) {
        deps = new Set()
        depsMap.set(key, deps)
    }
  // 现在添加Set()
  // 给Set添加副作用函数
    deps.add(activeEffect)
}

 

更新依赖

// 更新依赖
export const trigger = (target, key) => {
  // 根据组件的响应式组件对象,拿到对应的map
    const depsMap = targetMap.get(target)
  // 通过具体key, 拿到对应副作用函数
    const deps = depsMap.get(key)
  // 执行
    deps.forEach((effect) => effect())
}

 

完整代码(effect.js)

let activeEffect
// 副作用函数
export const effect = (fn) => {
    const _effect = function () {
        activeEffect = _effect
        fn()
    }
    _effect()
}
// 收集依赖
const targetMap = new WeakMap()
export const track = (target, key) => {
    // WeakMap 
  // key为对象, 即target
  // value 为一个new Map()
    // {
    //   key:{
    //     name: "名字",
    //     age: 18
    //   },
    //   value: {
    //     name: new Map(),
    //     age: new Map()
    //   }
    // }
    let depsMap = targetMap.get(target)
    if (!depsMap) {
        depsMap = new Map()
        targetMap.set(target, depsMap)
    }
    // 现在添加new Map()
  // key为属性名称, 即key
  // value为一个new Set()
    let deps = depsMap.get(key)
    if (!deps) {
        deps = new Set()
        depsMap.set(key, deps)
    }
  // 现在添加Set()
  // 给Set添加副作用函数
    deps.add(activeEffect)
}

// 更新依赖
export const trigger = (target, key) => {
  // 根据组件的响应式组件对象,拿到对应的map
    const depsMap = targetMap.get(target)
  // 通过具体key, 拿到对应副作用函数
    const deps = depsMap.get(key)
  // 执行
    deps.forEach((effect) => effect())
}

 

reactive实现(reactive.js)

import { track, trigger } from './effect.js'
const isObject = (target) => target != null && typeof target == 'object'
export const reactive = (target) => {
    return new Proxy(target, {
        get(target, key, receiver) {
            const res = Reflect.get(target, key, receiver)
      // 收集依赖
            track(target, key)
      // 递归对象
            if (isObject(res)) {
                return reactive(res)
            }
            return res
        },
        set(target, key, value, receiver) {
            const res = Reflect.set(target, key, value, receiver)
      // 更新依赖
            trigger(target, key)
            return res
        },
    })
}

 

调用

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <div id="app">

  </div>

  <script type="module">
    import { reactive } from './reactive.js'
    import { effect } from './effect.js'
    const user = reactive({
      name: "名字",
      age: 18,
      foo: {
        bar: {
          sss: 123
        }
      }
    })
    effect(() => {
      document.querySelector('#app').innerText = `${user.name} - ${user.age}-${user.foo.bar.sss}`
    })

    setTimeout(() => {
      user.name = '名字666'
      setTimeout(() => {
        user.age = '23'
        setTimeout(() => {
          user.foo.bar.sss = 66666666
        }, 3000)
      }, 2000)
    }, 1000)

  </script>
</body>

</html>

 

2.Vue2

待完成....

 

标签:const,target,depsMap,effect,响应,Vue2,key,Vue3,new
From: https://www.cnblogs.com/ssszjh/p/18163321

相关文章

  • Linux应急响应小结
    目录用户排查历史命令网络排查进程排查文件排查持久化排查日志分析通过系统运行状态、安全设备告警,主机异常现象来发现可疑现象通常的可疑现象有:资源占用、异常登录、异常文件、异常连接、异常进程等。用户排查如果发现异常用户活动,例如尝试多次登录失败、执行不正常的命令等,应......
  • 一个通用的SpringBoot项目响应实体类Response
    packagecom.luky.vo;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importlombok.ToString;importorg.springframework.http.HttpStatus;@Data@ToString@AllArgsConstructor@NoArgsConstructorpublicclassResponse&......
  • vue3 快速入门系列 —— 状态管理 pinia
    其他章节请看:vue3快速入门系列Piniavue3状态管理这里选择pinia。虽然vuex4已支持Vue3的CompositionAPI,但是vue3官网推荐新的应用使用pinia——vue3pinia集中式状态管理redux、mobx、vuex、pinia都是集中式状态管理工具。与之对应的就是分布式。Pinia符......
  • 响应结果写入日志文件
    方法一:使用查看结果树直接写入(不推荐,工具自带效果不理想)◆AsXML:保存为xml格式◆ElapsedTime:请求的消耗时间,从请求发送到接收完毕全程耗时(经常用)◆Responsemessage:默认值:ok◆Success:成功标识,true/false◆SentByteCount:发送数据量的总和◆ResponseFilename:响应......
  • vue3打包js内存溢出
     第一步:npminstall-gincrease-memory-limit第二步:npminstallincrease-memory-limit—save-dev第三步:package.json文件中修改   "build:win32":"cross-envLIMIT=2048increase-memory-limitBUILD_TARGET=win32node.electron-vue/build.js",//添加这个......
  • Vue3.0
    Vue2中的optionsAPI和Vue3.0中compositionAPIoptionsAPI示例compositionAPI是一组基于函数的API,可以更灵活的组织组件的逻辑createAPP函数的第一个参数即compositionAPI对象用于创建应用实例createApp({setup(){ constcount=ref(0)return{......
  • python2 http响应中文显示unicode \uXXX的问题
    python2编码解码会以unicode作为中间码,要用decode和encode解码后再编码其中decode解码,是把bytes以给定的编码格式解码成unicodeencode是以给定的编码格式将unicode编码为bytes数据是以bytes形式传递和存储的,程序需要用正确的编码来将bytes解码显示decode:FrombytesToUnic......
  • vue3+vite+js 引用public文件夹中js文件
    vue的public的资源在打包时不会被编译,只会copy所以在在src路径下引入public文件夹下的图片、视频、音频,编译不会改变其路径,但是在src下引入public文件夹下的js、json,在打包时都会被编译,所以直接引入会丢失路径(因为打包时,当前页面引入的路径被hash打包,而public文件夹下只是被cop......
  • 【vue3入门】-【13】class绑定
    class绑定数据绑定的一个常见需求场景是操纵元素的CSSclass列表,因为class是Attribute,我们可以和其他Attribute一样使用v-bind将它们动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,vue专门为class和v-bind用法提供了特殊的功能增强。除......
  • 【vue3入门】-【15】侦听器
    侦听器我们可以使用watch选项在每次响应式属性发生变化时触发一个函数<template><h3>侦听器</h3><!--不可以被监听,是固定的数据--><p>{{message}}</p><!--可以被监听,只能监听响应式数据(变化的数据)--><button@click="updateHandle">修改数据</button>&l......