29-mini-vue element搭建更新

更新 element 流程搭建

  1. 我们初始化页面展示
js 复制代码
// index.html
<div id="root"></div>
<script type="module" src="./main.js"></script>

// App.js
import { h, ref } from "../../lib/guide-mini-vue.esm.js";

export const App = {
  name: "App",
  setup() {
    const count = ref(0); // ✅ 声明 ref 值
    const onClick = () => { count.value++; } // ✅ 对该值进行修改,引发页面更新
    return { count, onClick }
  },
  render() {
    return h("div",
      {
        id: "root"
      },
      [
        h("div", {}, "count:" + this.count), // 依赖收集
        h('button', {
          onClick: this.onClick
        },
          "click"
        )
      ]
    )
  }
}

// main.js
import { App } from './App.js'
import { createApp } from '../../lib/guide-mini-vue.esm.js'

const root = document.querySelector('#root')
createApp(App).mount(root)
  1. 实现功能
    1. 声明 ref 值
    2. 对该值进行修改,引发页面更新
  2. 我们之前已经实现了 ref 的功能, 在前面的目录中可以找到,现在我们进行导出和引入
js 复制代码
// reactivity.ts
export { ref, proxyRefs } from './ref'
// src/index.ts
import * from './reactivity'
// src/runtime-core/component.ts
import { proxyRefs } from '../reactivity'

function handleSetupResult(instance, setupResult: any) { // 将状态挂载到实例上
  if(typeof setupResult === 'object') {
    instance.setupState = proxyRefs(setupResult)
  }
  finishComponentSetup(instance)
}
  1. 进行上面的操作后,我们已经能够在页面上看到数字已经被展示出来,而且我们点击按钮实现数字 +1,不过会每点击一次,多渲染一次
  • 原因是我们每点击一次,就会在 container 里面多渲染一次,而旧的 dom 没有进行删除,所以我们需要区分初始化和更新两个阶段来处理
  1. 代码
js 复制代码
// component.ts
export function createComponentInstance(vnode, parent) {
  const component = {
    vnode,
    type: vnode.type,
    setupState: {},
    props: {},
    emit:()=>{},
    slots:{},
    provides: parent ? parent.provides : {},
    parent,
    isMounted: false, // ✅
    subTree: {}, // ✅
  }
  component.emit = emit.bind(null, component) as any 
  return component
}
// renderer.ts
function setupRenderEffect(instance, vnode, container) {
  effect(()=>{
    let { proxy } = instance
    if(!instance.isMounted) { // ✅ 初始化渲染
      const subTree = instance.subTree  = instance.render.call(proxy)
      patch(null, subTree, container, instance)
      vnode.el = subTree.el
      instance.isMounted = true
      console.log('init');  
    } else { // ✅ 更新时渲染
      console.log('update');
      const { proxy } = instance
      const subTree = instance.render.call(proxy)
      const prevSubTree = instance.subTree
      instance.subTree = subTree
      console.log(subTree,'subTree');
      console.log(prevSubTree,'prevSubTree');
      patch(prevSubTree, subTree, container, instance)
    }
  })
}
  • 除此之外,我们给 patch 的传参时,多加一个 n1,表示是旧虚拟dom,之前 vnode 参数为n2,表示新虚拟 dom
js 复制代码
// n1 老的虚拟节点
// n2 新的虚拟节点
function patch(n1, n2, container, parentComponent) {
  const { type, shapeFlag } = n2
  switch (type) {
    case Fragment:
      processFragment(n1, n2, container, parentComponent)
      break;
    case Text:
      processText(n1, n2, container)
      break;
    default:
      if (shapeFlag & shapeFlags.ELEMENT) {
        processElement(n1, n2, container, parentComponent)
      } else if (shapeFlag & shapeFlags.STATEFUL_COMPONENT) {
        processComponent(n1, n2, container, parentComponent)
      }
      break;
  }
}
  • 当 n1 为空时,说明没有旧的虚拟dom,属于初始化加载
js 复制代码
function processElement(n1, n2, container, parentComponent) {
  if(!n1) {
    mountElement(n2, container, parentComponent)
  } else {
    patchElement(n1, n2, container)
  }
}
function patchElement(n1, n2, container) {
  // 我们在这里做更新 dom 的处理
}
相关推荐
QQ1__8115175153 小时前
Spring boot名城小区物业管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
钛态3 小时前
前端微前端架构:大项目的救命稻草还是自找麻烦?
前端·vue·react·web
一粒黑子3 小时前
【实战解析】阿里开源 PageAgent:纯前端 GUI Agent,一行JS让网页支持自然语言操控
前端·javascript·开源
独角鲸网络安全实验室3 小时前
2026微信小程序抓包全解析:从实操落地到合规风控,解锁前端调试新范式
前端·微信小程序·小程序·抓包·系统代理绕过·https证书严格校验·进程隔离
紫微AI3 小时前
前端文本测量成了卡死一切创新的最后瓶颈,pretext实现突破了
前端·人工智能·typescript
GISer_Jing3 小时前
AI前端(From豆包)
前端·aigc·ai编程
IT枫斗者3 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
测试修炼手册3 小时前
[测试技术] 深入理解 JSON Web Token (JWT)
前端·json
AI老李3 小时前
2026 年 Web 前端开发的 8 个趋势!
前端
里欧跑得慢3 小时前
15. Web可访问性最佳实践:让每个用户都能平等访问
前端·css·flutter·web