自己创建一个mini-vue

简介: mini-vue本章在之前的章节的基础中实现了一个简单的vue框架,其中响应式的函数有略微变化不过大致原理相同。致谢Vue Mastery非常好的课程,可以转载,但请声明源链接:文章源链接justin3go.com(有些latex公式某些平台不能渲染可查看这个网站)
published: true
date: 2022-2-3
tags: '前端框架 Vue'


mini-vue

本章在之前的章节的基础中实现了一个简单的vue框架,其中响应式的函数有略微变化不过大致原理相同。

致谢Vue Mastery非常好的课程,可以转载,但请声明源链接:文章源链接justin3go.com(有些latex公式某些平台不能渲染可查看这个网站)

<div id="app"></div>
<script>
//vdom部分
function h(tag, props, children) {
  return {
    tag,
    props,
    children,
  };
}
function mount(vnode, container) {
  const { tag, props, children } = vnode;
  const el = (vnode.el = document.createElement(tag));
  if (props) {
    for (let key in props) {
      const value = props[key];
      if (key.startsWith("on")) {
        el.addEventListener(key.slice(2).toLowerCase(), value);
      } else {
        el.setAttribute(key, value);
      }
    }
  }
  if (children) {
    if (Array.isArray(children)) {
      children.forEach((child) => {
        if (typeof child === "string") {
          el.append(child);
        } else if (typeof child === "object") {
          mount(child, el);
        }
      });
    } else {
      el.append(children);
    }
  }
  container.append(el);
}
function patch(n1, n2) {
  if (n1.tag === n2.tag) {
    const el = (n2.el = n1.el);
    //diff props
    const oldProps = n1.props || {};
    const newProps = n2.props || {};
    //添加新的属性或更改原来已有但变化了的属性
    for (let key in newProps) {
      const oldValue = oldProps[key];
      const newValue = newProps[key];
      if (newValue !== oldValue) {
        el.setAttribute(key, newValue);
      }
    }
    //移除新属性中没有的属性
    for (let key in oldProps) {
      if (!(key in newProps)) {
        el.removeAttribute(key);
      }
    }
    //diff children
    const oldChildren = n1.children;
    const newChildren = n2.children;
    if (typeof newChildren === "string") {
      if (typeof oldChildren === "string") {
        if (oldChildren !== newChildren) {
          el.innerHTML = newChildren;
        }
      }
    } else if (typeof oldChildren === "string" && Array.isArray(newChildren)) {
      el.innerHTML = "";
      newChildren.forEach((child) => mount(child, el));
    } else if (Array.isArray(oldChildren) && Array.isArray(newChildren)) {
      const minLength = Math.min(oldChildren.length, newChildren.length);
      for (let i = 0; i < minLength; i++) {
        patch(oldChildren[i], newChildren[i]);
      }
      if (oldChildren.length === minLength) {
        for (let i = minLength; i < newChildren.length; i++) {
          mount(newChildren[i], el);
        }
      } else {
        for (let i = minLength; i < oldChildren.length; i++) {
          el.removeChild(oldChildren[i].el);
        }
      }
    }
  } else {
    //replace
  }
}
//reactivity部分
let activeEffect = null;
class Dep {
  subs = new Set();
  depend() {
    if (activeEffect) {
      this.subs.add(activeEffect);
    }
  }
  notify() {
    this.subs.forEach((sub) => sub());
  }
}
function watchEffect(effect) {
  activeEffect = effect;
  effect();
  activeEffect = null;
}
const targetMap = new WeakMap();
function getDep(target, key) {
  if (!targetMap.has(target)) {
    targetMap.set(target, new Map());
  }
  const depMap = targetMap.get(target);
  if (!depMap.has(key)) {
    depMap.set(key, new Dep());
  }
  return depMap.get(key);
}
const reactiveHandlers = {
  get(target, key, receiver) {
    // dep
    const dep = getDep(target, key);
    dep.depend();
    return Reflect.get(target, key, receiver);
  },
  set(target, key, value, receiver) {
    const dep = getDep(target, key);
    const ret = Reflect.set(target, key, value, receiver);
    dep.notify();
    return ret;
  },
};
function reactive(raw) {
  return new Proxy(raw, reactiveHandlers);
}
//component组件实例
//container要挂载的dom元素
function mountApp(component, container) {
  let isMounted = false;
  let oldVdom;
  watchEffect(() => {
    if (!isMounted) {
      //第一次挂载
      oldVdom = component.render();
      mount(oldVdom, container);
      isMounted = true;
    } else {
      //数据变化,要进行更新
      const newVdom = component.render();
      patch(oldVdom, newVdom);
      oldVdom = newVdom;
    }
  });
}
const App = {
  data: reactive({
    count: 0,
  }),
  render() {
    return h("div", null, [
      h(
        "div",
        {
          onClick: () => App.data.count++,
        },
        String(this.data.count)
      ),
    ]);
  },
};
//一个点击自增的计数器
mountApp(App, document.getElementById("app"));
</script>



目录
相关文章
|
网络协议 物联网 芯片
三张图带你入门蓝牙规范
蓝牙自从2001年发布以来,从经典蓝牙发展到了BLE蓝牙,又于2017年引入了蓝牙mesh技术,核心规范版本就于2019年年底升级到了最新的5.2版本,很多同学对蓝牙很有兴趣,但也被会被蓝牙技术里繁多的概念搞迷糊,希望通过这篇文章带大家对蓝牙技术规范有一个基本的了解。本文的面向读者是对网络技术有一定了解但对蓝牙技术不熟悉的同学。
三张图带你入门蓝牙规范
|
5月前
|
存储 人工智能 自然语言处理
2026零基础保姆级阿里云部署OpenClaw(Clawdbot)教程:从入门到上手,零代码也能搞定
2026年,OpenClaw(原Clawdbot、Moltbot)凭借“自然语言交互+自动化任务执行+插件化扩展”的核心优势,成为开源AI智能体赛道的“现象级”项目,GitHub星标数快速突破18万+。它并非传统聊天机器人,而是能自主完成文件处理、网页抓取、跨平台交互、代码调试的“全能数字助理”,既能帮普通人解放重复办公负担,也能为开发者节省大量调试时间。
655 2
|
8月前
|
JSON 前端开发 开发工具
基于Tauri2.9+Vite7.2+Vue3+Pinia3+ArcoDesign+Echarts桌面版OS管理后台模板
基于最新跨平台框架tauri2.9+vite7.2.2+vue3 setup+pinia3+arco-design+echarts搭建桌面端OS管理后台模板。
436 4
|
API 开发工具 开发者
HarmonyOS NEXT实战:滑动条
本节介绍HarmonyOS Next中Slider滑动条组件的使用,涵盖横向与竖向滑动条实现。通过实战演示如何调节音量、亮度等场景,讲解Slider参数配置及样式设置,帮助开发者快速掌握滑动条应用开发技巧。
278 1
|
11月前
|
API 数据安全/隐私保护 Python
拼多多批量上架软件, 电商一键上货发布工具,python电商框架分享
多线程批量上传架构,支持并发处理商品数据 完整的拼多多API签名和token管理机制
|
存储 缓存 Oracle
崖山数据库YashanDB的共享集群机制初探
YashanDB共享集群是崖山数据库系统的核心特性,支持单库多实例并发读写,确保强一致性与高可用性。基于Shared-Disk架构和Cohesive Memory技术,实现数据页协同访问及资源控制。其核心组件包括YCK、YCS和YFS,提供金融级RPO=0、RTO&lt;10秒的高可用能力。通过自研“七种武器”(如页内锁、去中心化事务管理等),优化性能并解决读写冲突。相比Oracle RAC,YashanDB在TPC-C测试中性能高出30%,适用于金融、电信等关键领域,推动国产化替代进程。
崖山数据库YashanDB的共享集群机制初探
|
传感器 数据采集 人工智能
AI是如何收集体育数据的?从摄像头到算法,揭秘赛场背后的“数字间谍网“!
⚽ 你是否好奇:AI如何知道哈兰德每秒跑多快?教练的平板为何比裁判还清楚谁偷懒?本文揭秘AI收集体育数据的“黑科技”:视觉追踪、传感器网络、数据清洗与高阶分析。从高速摄像机捕捉梅西肌肉抖动,到GPS背心记录姆巴佩冲刺速度;从表情识别判断装伤,到量子计算模拟战术可能,AI正让体育更透明、精准。未来已来,2030年世界杯或将实现AI替代球探、裁判甚至教练!你认为AI数据收集算侵犯隐私吗?最想统计哪些奇葩指标?留言互动吧!
|
机器学习/深度学习 人工智能 算法
《片上网络,如何让硬件加速系统通信“快人一步”》
片上网络(NoC)作为提升硬件加速系统通信效率的核心技术,正逐渐成为科技领域的焦点。它借鉴计算机网络概念,在芯片内构建复杂高效的通信网络,确保各组件间信息快速传递。NoC通过节点和链路组成,采用不同拓扑结构优化性能,如网状、环形等。高效路由算法、流量控制机制及拓扑结构优化是其关键技术,旨在解决带宽瓶颈、延迟等问题,推动人工智能和高性能计算发展。
496 14
|
机器学习/深度学习 人工智能 运维
CodeFuse团队2024年10篇论文总结
CodeFuse 是蚂蚁集团开发的多语言代码大型语言模型(LLM),基于海量高质量代码数据和多任务微调技术,已在内部研发人员的编码、测试、运维等场景中广泛应用。2024年,CodeFuse 在国际顶会如ICSE、ICDE、KDD等发表多篇论文,涵盖CodeLLM、机器学习、AI等领域,并开源多个自研大模型,总下载量近200万。项目持续迭代,欢迎贡献和建议。
860 11
|
存储 编译器 C语言
【C语言程序设计——入门】C语言入门与基础语法(头歌实践教学平台习题)【合集】
本文档介绍了C语言环境配置和编程任务,主要内容包括: - **C语言环境配置**:详细讲解了在Windows系统上配置C语言开发环境的步骤。 - **第1关:程序改错**:包含任务描述、相关知识(如头文件引用、基本语法规则)、编程要求、测试说明及通关代码。 - **第2关:scanf函数**:涉及`scanf`和`printf`函数的格式与使用方法,提供编程要求、测试说明及通关代码。 文档结构清晰,涵盖从环境搭建到具体编程任务的完整流程,适合初学者学习和实践。
523 4

热门文章

最新文章