0


基于Vue3从0到1实现 mini-vue【reactive】

基于Vue3实现最简单的 mini-vue

✨代码已上传至CSDN文库,如需要请点击下载min-vue,私信也可免费提供代码。
✨运行顺序 npm install ==>npm run build ==>npm run dev
✨Github mini-vue

项目目录结构

在这里插入图片描述

项目配置

webpack.config.js

const path =require('path');

module.exports ={mode:'development',devtool:false,// devtool: 'inline-cheap-source-map',entry:'./src/index.js',//入口文件output:{filename:'mini-vue.js',path: path.resolve(__dirname,'dist'),clean:true,// library: 'MiniVue',// libraryTarget: 'umd'},devServer:{contentBase:'./src/examples',//项目启动html页面publicPath:'/dist',watchContentBase:true,//在文件改变时会进行页面刷新,默认情况下该配置是禁止的。},};

入口 html

examples/index.html

<!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>Expamels</title><script src="../dist/mini-vue.js"></script></head><body></body></html>

入口文件依赖 js

src/index.js

import{ reactive }from'./reactive/reactive';import{ effect }from'./reactive/effect';//监听countconst observed =(window.observed =reactive({count:0,}));effect(()=>{
  console.log('observed.count is ==>', observed.count);});//监听数组// const observed = (window.observed = reactive([1,2,3]));// effect(()=>{//     console.log('index 4 is ==>',observed[4]);// })// effect(()=>{//     console.log('length is ==>',observed.length);// })//监听effect嵌套// const observed = (window.observed = reactive({//   count1: 0,//   count2: 0,// }));// effect(() => {//   effect(() => {//     console.log('count2 is ==>', observed.count2);//   });//   console.log('count1 is ==>', observed.count1);// });

reactive对象代理

reactive/reactive.js

import{ hasChanged, isArray, isObject }from'../untils';import{ track, trigger }from'./effect';const proxyMap =newWeakMap();exportfunctionreactive(target){//不是对象if(!isObject(target)){return target;}//是否被代理过if(isReactive(target)){return target;}if(proxyMap.has(target)){return proxyMap.get(target);}const proxy =newProxy(target,{get(target, key, receiver){if(key ==='_isReactive'){returntrue;}const res = Reflect.get(target, key, receiver);//收集依赖track(target, key);// return res;//Vue2中初始化data时会递归遍历代理所有深层次对象//Vue3处理深层次代理依赖returnisObject(res)?reactive(res): res;},set(target, key, value, receiver){let oldLength = target.length;//拿到旧值,比较是否发生改变countconst oldValue = target[key];const res = Reflect.set(target, key, value, receiver);if(hasChanged(oldValue, value)){//发生改变--触发依赖trigger(target, key);//处理代理数组if(isArray(target)&&hasChanged(oldLength, target.length)){trigger(target,'length');//传参target key}}return res;},});
  proxyMap.set(target, proxy);return proxy;}//Reflect:https://www.jb51.net/article/257679.htm//不管执行几次代理,只代理一次//是否被代理过exportfunctionisReactive(target){//_isReactive私有属性判断是否是响应式对象;//返回布尔类型return!!(target && target._isReactive);}

effect副作用函数

reactive/effect.js

const effectStack =[];//处理effect嵌套effectlet activeEffect;//记录当前正在执行的副作用函数exportfunctioneffect(fn){consteffectFn=()=>{try{
      activeEffect = effectFn;
      effectStack.push(activeEffect);returnfn();}finally{//执行完成后还原
      effectStack.pop();//activeEffect = undefined;
      activeEffect = effectStack[effectStack.length -1];}};effectFn();return effectFn;}const targetMap =newWeakMap();//模块类全局变量exportfunctiontrack(target, key){if(!activeEffect){return;}let depsMap = targetMap.get(target);if(!depsMap){
    targetMap.set(target,(depsMap =newMap()));}let deps = depsMap.get(key);if(!deps){
    depsMap.set(key,(deps =newSet()));}
  deps.add(activeEffect);}//trck的逆运算exportfunctiontrigger(target, key){const depsMap = targetMap.get(target);if(!depsMap){return;}const deps = depsMap.get(key);if(!deps){return;}
  deps.forEach((effectFn)=>{effectFn();});}

项目公用方法

untils/index.js

exportfunctionisObject(target){returntypeof target ==='object'&& target !==null;}exportfunctionhasChanged(oldValue, value){//旧值和新值不能相等,且同时不能为NaN//Number.isNaN http://t.csdn.cn/PnJX6// console.log(oldValue!==value && (Number.isNaN(oldValue) && Number.isNaN(value)));return oldValue !== value &&!(Number.isNaN(oldValue)&& Number.isNaN(value));}exportfunctionisArray(target){return Array.isArray(target);}

初始化项目依赖

package.json

{"name":"mini-vue3","version":"1.0.0","description":"","main":"src/index.js","scripts":{"test":"jest","build":"webpack","dev":"webpack serve --open","format":"prettier --write ."},"author":"","license":"ISC","devDependencies":{"@babel/core":"^7.13.8","@babel/preset-env":"^7.13.8","@babel/preset-typescript":"^7.13.0","@types/jest":"^26.0.23","babel-jest":"^26.6.3","eslint":"^7.31.0","html-webpack-plugin":"^5.3.2","jest":"^27.0.5","prettier":"2.3.2","webpack":"^5.40.0","webpack-cli":"^4.7.2","webpack-dev-server":"^3.11.2"},"dependencies":{}}

实现效果

监听count

在这里插入图片描述

监听数组

在这里插入图片描述

监听嵌套effect

在这里插入图片描述

在这里插入图片描述


本文转载自: https://blog.csdn.net/gentleman_hua/article/details/127177542
版权归原作者 小灵儿呐 所有, 如有侵权,请联系我们删除。

“基于Vue3从0到1实现 mini-vue【reactive】”的评论:

还没有评论