当前位置:首页 > VUE

模拟vue实现原理

2026-01-19 05:30:32VUE

Vue 实现原理的核心模块

Vue 的核心实现原理主要包括响应式系统、虚拟 DOM、模板编译和组件化机制。以下是模拟 Vue 这些核心功能的简化实现方法。

响应式系统

Vue 使用 Object.definePropertyProxy 实现数据劫持,监听数据变化并触发更新。

基于 Object.defineProperty 的简化实现:

function defineReactive(obj, key, val) {
  const dep = new Dep(); // 依赖收集器

  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.addSub(Dep.target); // 收集依赖
      }
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // 通知更新
    },
  });
}

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

class Watcher {
  constructor(vm, key, updateFn) {
    Dep.target = this;
    vm[key]; // 触发 getter,收集依赖
    Dep.target = null;
    this.updateFn = updateFn;
  }
  update() {
    this.updateFn();
  }
}

虚拟 DOM 与 Diff 算法

虚拟 DOM 是一个轻量级的 JavaScript 对象,用于描述真实 DOM 结构。Diff 算法通过对比新旧虚拟 DOM 的差异,最小化 DOM 操作。

虚拟 DOM 的简化实现:

function createElement(tag, props, children) {
  return { tag, props, children };
}

function render(vnode) {
  if (typeof vnode === 'string') return document.createTextNode(vnode);

  const el = document.createElement(vnode.tag);
  for (const key in vnode.props) {
    el.setAttribute(key, vnode.props[key]);
  }
  vnode.children.forEach(child => {
    el.appendChild(render(child));
  });
  return el;
}

function patch(oldNode, newNode) {
  if (oldNode.tag !== newNode.tag) {
    return render(newNode); // 直接替换
  }

  const el = oldNode.el;
  for (const key in newNode.props) {
    if (newNode.props[key] !== oldNode.props[key]) {
      el.setAttribute(key, newNode.props[key]);
    }
  }

  const oldChildren = oldNode.children;
  const newChildren = newNode.children;
  for (let i = 0; i < Math.max(oldChildren.length, newChildren.length); i++) {
    if (!oldChildren[i]) {
      el.appendChild(render(newChildren[i]));
    } else if (!newChildren[i]) {
      el.removeChild(oldChildren[i].el);
    } else {
      patch(oldChildren[i], newChildren[i]);
    }
  }
  return el;
}

模板编译

Vue 将模板编译为渲染函数,生成虚拟 DOM。以下是一个极简的模板编译示例:

function compile(template) {
  const ast = parse(template); // 解析为 AST(抽象语法树)
  const code = generate(ast); // 生成渲染函数代码
  return new Function(`with(this) { return ${code} }`);
}

// 示例:简单插值表达式
function parse(template) {
  return {
    type: 'element',
    tag: 'div',
    children: [{
      type: 'text',
      content: `{{ message }}`
    }]
  };
}

function generate(ast) {
  return `createElement("${ast.tag}", {}, [this.message])`;
}

组件化机制

Vue 组件是带有预定义选项的可复用实例。以下是组件注册和渲染的简化逻辑:

class Vue {
  constructor(options) {
    this.$options = options;
    this._data = options.data();
    this._initReactive();
    this.$mount(options.el);
  }

  _initReactive() {
    Object.keys(this._data).forEach(key => {
      defineReactive(this, key, this._data[key]);
    });
  }

  $mount(el) {
    this.$el = document.querySelector(el);
    const updateComponent = () => {
      const vnode = this.$options.render.call(this);
      patch(this.$el, vnode);
    };
    new Watcher(this, updateComponent);
  }
}

// 使用示例
const app = new Vue({
  el: '#app',
  data: () => ({ message: 'Hello Vue' }),
  render() {
    return createElement('div', {}, [this.message]);
  }
});

总结

  1. 响应式系统:通过数据劫持和依赖收集实现数据驱动视图。
  2. 虚拟 DOM:用 JavaScript 对象描述 DOM 结构,配合 Diff 算法高效更新视图。
  3. 模板编译:将模板转换为渲染函数,生成虚拟 DOM。
  4. 组件化:将 UI 拆分为独立可复用的组件实例。

以上是 Vue 核心原理的简化实现,实际 Vue 源码还包含更多优化和边界处理。

模拟vue实现原理

标签: 原理vue
分享给朋友:

相关文章

vue单页面实现登录

vue单页面实现登录

实现登录功能的基本流程 在Vue单页面应用中实现登录功能,通常需要以下几个关键步骤: 创建登录表单组件 使用Vue的模板语法创建包含用户名和密码输入框的表单,并绑定数据到组件的data属性。 &l…

vue实现横向导航

vue实现横向导航

vue实现横向导航的方法 使用Flex布局实现横向导航 在Vue中可以通过Flex布局快速实现横向导航。创建一个组件,使用display: flex和flex-direction: row属性使导航项…

vue实现钟表

vue实现钟表

使用 Vue 实现动态钟表 以下是一个基于 Vue 3 的动态钟表实现方案,包含时分秒指针和数字时间显示。 模板部分 <template> <div class="clock-…

vue实现triger

vue实现triger

在Vue中实现触发器(trigger)功能通常涉及自定义事件或DOM事件触发。以下是几种常见场景的实现方法: 自定义事件触发 通过$emit方法触发父组件中监听的自定义事件: // 子组件 t…

vue实现分类

vue实现分类

Vue实现分类功能的方法 使用v-for和计算属性 通过计算属性对数据进行分类处理,结合v-for渲染分类后的列表。示例代码: <template> <div>…

vue 实现拖拽

vue 实现拖拽

Vue 实现拖拽功能 使用 HTML5 原生拖拽 API HTML5 提供了原生的拖拽 API,可以通过 draggable 属性和相关事件实现拖拽功能。 <template> &…