当前位置:首页 > VUE

手动实现vue视图

2026-02-19 04:54:29VUE

手动实现 Vue 视图的核心逻辑

Vue 的视图更新依赖于数据劫持和依赖收集,通过监听数据变化触发视图更新。以下是简化版实现的核心步骤:

数据劫持(响应式系统)

使用 Object.definePropertyProxy 拦截数据访问和修改:

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(); // 触发更新
    }
  });
}

依赖收集与观察者

实现依赖收集器(Dep)和观察者(Watcher):

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

class Watcher {
  constructor(vm, exp, cb) {
    this.vm = vm;
    this.exp = exp;
    this.cb = cb;
    Dep.target = this;
    this.value = this.get(); // 触发getter收集依赖
    Dep.target = null;
  }
  update() {
    const value = this.get();
    if (value !== this.value) {
      this.cb.call(this.vm, value, this.value);
      this.value = value;
    }
  }
  get() {
    return this.vm._data[this.exp]; // 简化版直接访问数据
  }
}

模板编译

实现简单的模板解析和指令处理:

function compile(el, vm) {
  const fragment = document.createDocumentFragment();
  let child;
  while ((child = el.firstChild)) {
    fragment.appendChild(child);
  }

  function replace(frag) {
    Array.from(frag.childNodes).forEach(node => {
      if (node.nodeType === 3) { // 文本节点
        const text = node.textContent;
        const reg = /\{\{(.*?)\}\}/g;
        if (reg.test(text)) {
          const exp = RegExp.$1.trim();
          new Watcher(vm, exp, newVal => {
            node.textContent = text.replace(reg, newVal);
          });
          node.textContent = text.replace(reg, vm._data[exp]);
        }
      }
      if (node.nodeType === 1) { // 元素节点
        Array.from(node.attributes).forEach(attr => {
          if (attr.name.startsWith('v-')) {
            const exp = attr.value;
            new Watcher(vm, exp, newVal => {
              node.value = newVal; // 简化版仅处理v-model
            });
            node.addEventListener('input', e => {
              vm._data[exp] = e.target.value;
            });
            node.value = vm._data[exp];
          }
        });
      }
      if (node.childNodes && node.childNodes.length) {
        replace(node);
      }
    });
  }
  replace(fragment);
  el.appendChild(fragment);
}

整合实现

创建 Vue 类整合上述功能:

手动实现vue视图

class Vue {
  constructor(options) {
    this.$options = options;
    this._data = options.data;
    this.observe(this._data);
    compile(options.el, this);
  }
  observe(data) {
    Object.keys(data).forEach(key => {
      defineReactive(data, key, data[key]);
    });
  }
}

使用示例

<div id="app">
  <input v-model="message">
  <p>{{ message }}</p>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    }
  });
</script>

实现要点

  • 响应式系统通过数据劫持实现自动依赖收集
  • 每个数据属性对应一个 Dep 实例管理依赖
  • 每个模板绑定对应一个 Watcher 实例触发更新
  • 编译阶段解析模板并建立数据与视图的关联

以上实现省略了虚拟 DOM、组件系统等复杂功能,但展示了 Vue 响应式视图的核心原理。实际应用中还需考虑性能优化、生命周期管理等更多细节。

标签: 视图vue
分享给朋友:

相关文章

vue实现文档导入

vue实现文档导入

Vue 实现文档导入的方法 在 Vue 中实现文档导入功能通常涉及文件上传、解析和处理。以下是几种常见的方法: 使用原生文件输入和 FileReader 通过 HTML 的原生 <input…

vue实现$.extend

vue实现$.extend

Vue 实现类似 jQuery 的 $.extend 功能 在 Vue 中实现类似 jQuery 的 $.extend 功能,可以通过多种方式完成。$.extend 主要用于合并多个对象的属性,Vue…

vue实现cs

vue实现cs

Vue 实现 CS(Client-Side)渲染的常见方法 Vue.js 是一个用于构建用户界面的渐进式框架,默认采用客户端渲染(CSR)。以下是几种常见的实现方式: 使用 Vue CLI 创建项目…

vue实现粘贴

vue实现粘贴

Vue 实现粘贴功能的方法 在 Vue 中实现粘贴功能通常涉及监听粘贴事件并处理剪贴板数据。以下是几种常见的实现方式: 监听原生粘贴事件 通过 @paste 指令或原生 addEventListen…

vue observer实现

vue observer实现

Vue Observer 实现原理 Vue 的响应式系统核心是通过 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现的 Observer 模式。以下是关键实现细…

vue 实现工具

vue 实现工具

Vue 实现工具的方法 使用 Vue 实现工具功能可以通过多种方式完成,具体取决于工具的类型和需求。以下是几种常见的方法: 组件化实现 创建一个独立的 Vue 组件来封装工具功能。例如,实现一个计…