vue整体实现思想及mini-vue的实现

vue整体实现思想及mini-vue的实现一、三大核心系统二、实现Mini-Vue1、描述2、渲染系统实现一、三大核心系统Compiler模块:编译模板系统主要用来将template模板转换为render渲染函数Runtime模块:也可以称之为Renderer模块,真正渲染的模块主要用来将虚拟DOM转变为真实DOM,并且渲染到浏览器页面上主要的实现原理是利用了snabbdom的思想,具体可以看我的另一篇转载文章,点下方虚拟DOM原理Reactivity模块:响应式系统主要用来当dom发生
摘要由CSDN通过智能技术生成

一、三大核心系统

  • Compiler模块:编译模板系统
    主要用来将template模板转换为render渲染函数
  • Runtime模块:也可以称之为Renderer模块,真正渲染的模块
    主要用来将虚拟DOM转变为真实DOM,并且渲染到浏览器页面上
    主要的实现原理是利用了snabbdom的思想,具体可以看我的另一篇转载文章,点下方
    虚拟DOM原理
  • Reactivity模块:响应式系统
    主要用来当dom发生变化的时候,通过diff算法进行更新或者替换,然后再通过渲染系统渲染到浏览器页面上

对应源码位置
在这里插入图片描述
那么三个系统之间如何协同工作呢?
这里借用一张coderwey老师的制图
在这里插入图片描述

二、实现Mini-Vue

1、描述

这里我们实现一个简洁版的Mini-Vue框架,该Vue包括三个模块

  • 渲染系统模块
  • 可响应式系统模块
  • 应用程序入口模块

2、渲染系统实现

  • 功能一:h函数,用于返回一个VNode对象
  • 功能二:mount函数,用于将VNode挂载到DOM上
  • 功能三:patch函数,用于对两个VNode进行对比,决定如何处理新的VNode

h函数 – 生成VNode
h函数的实现:

  • 直接返回一个VNode对象即可
    在这里插入图片描述
    Mount函数 – 挂载VNode
  • mount函数的实现:
  • 第一步:根据tag,创建HTML元素,并且存储到vnode的el中;
  • 第二步:处理props属性
  • 如果以on开头,那么监听事件;
  • 普通属性直接通过 setAttribute 添加即可;
  • 第三步:处理子节点
  • 如果是字符串节点,那么直接设置textContent;
  • 如果是数组节点,那么遍历调用 mount 函数;
    在这里插入图片描述
    Patch函数 – 对比两个VNode
  • patch函数的实现,分为两种情况
  • 1、n1和n2是不同类型的节点:
  • 找到n1的el父节点,删除原来的n1节点的el;
  • 挂载n2节点到n1的el父节点上;
  • 2、n1和n2节点是相同的节点:
  • 处理props的情况
  • 先将新节点的props全部挂载到el上;
  • 判断旧节点的props是否不需要在新节点上,如果不需要,那么删除对应的属性;
  • 处理children的情况
  • 如果新节点是一个字符串类型,那么直接调用 el.textContent = newChildren;
  • 如果新节点不同一个字符串类型:
  • 旧节点是一个字符串类型
  • 将el的textContent设置为空字符串;
  • 旧节点是一个字符串类型,那么直接遍历新节点,挂载到el上;
  • 旧节点也是一个数组类型
  • 取出数组的最小长度;
  • 遍历所有的节点,新节点和旧节点进行path操作;
  • 如果新节点的length更长,那么剩余的新节点进行挂载操作;
  • 如果旧节点的length更长,那么剩余的旧节点进行卸载操作;
    在这里插入图片描述
    在这里插入图片描述

3、响应式系统实现

1、依赖收集系统的实现

思想:通过集合收集依赖,首先通过某个函数将依赖添加到集合中,然后当数据发生改变的时候,调用某个函数,重新遍历集合中的每一个函数,实现更新
在这里插入图片描述
从上面的代码,我们可以看出,存在很多弊端,需要我们手动调用addEffect函数才能将依赖添加进去,然后数据发生改变时,需要手动调用notify函数实现更新。

那么如何让它自动添加呢?

2、响应式系统Vue2的实现

class Dep {
   
  constructor() {
    
    this.subscribers = new Set();  //添加一个集合
  }

  depend() {
                   //这个函数用来做依赖收集
    if (activeEffect) {
   
      this.subscribers.add(activeEffect);
    }
  }

  notify() {
                   //这个函数用来做通知更新
    this.subscribers.forEach(effect => {
   
      effect();
    })
  }
}

let activeEffect = null;   //根据这个变量是否为null来决定是否收集到依赖系统中
function watchEffect(effect) {
     
  activeEffect = effect;
  effect();              //初始的时候执行一次
  activeEffect = null;  //收集完依赖之后再次置为空,方便添加下一个依赖
}


// Map({key: value}): key是一个字符串
// WeakMap({key(对象): value}): key是一个对象, 弱引用
const targetMap = new WeakMap();
function getDep(target, key) {
      //工具函数,根据target和key获取到对应的map
  // 1.根据对象(target)取出对应的Map对象
  let depsMap = targetMap.get(target);
  if (!depsMap) {
   
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }

  // 2.取出具体的dep对象
  let dep = depsMap.get(key)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值