当前位置:首页 > VUE

手动实现vue视图

2026-02-19 04:54:29VUE

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

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

数据劫持(响应式系统)

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

手动实现vue视图

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):

手动实现vue视图

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 类整合上述功能:

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.js 可以通过 CDN 引入或使用 npm/yarn 安装。 CDN 方式: <script src="https://cdn.jsdelivr…

vue实现高亮

vue实现高亮

Vue 实现文本高亮的方法 在 Vue 中实现文本高亮可以通过多种方式完成,以下是几种常见的方法: 方法一:使用 v-html 指令 通过 v-html 指令可以动态插入 HTML 内容,将需要高…

vue实现级联

vue实现级联

Vue 实现级联选择器的方法 级联选择器(Cascader)是常见的表单组件,用于处理多层级联动数据选择(如省市区选择)。以下是几种实现方式: 基于 Element UI 的 el-cascade…

vue实现$.extend

vue实现$.extend

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

vue实现翻译

vue实现翻译

Vue 实现翻译功能的方法 使用 i18n 插件实现多语言切换 安装 vue-i18n 插件: npm install vue-i18n 创建语言资源文件(如 en.json 和 zh.json):…

vue实现选人

vue实现选人

实现选人功能的基本思路 在Vue中实现选人功能通常涉及以下核心环节:数据绑定、用户交互处理、状态管理以及界面渲染。以下是具体实现方法: 数据准备与组件结构 创建包含人员信息的数组,通常从API获取…