当前位置:首页 > VUE

proxy实现vue

2026-02-10 12:48:15VUE

使用Proxy实现Vue响应式系统

Proxy是ES6引入的特性,能够拦截对象的操作,Vue3利用Proxy替代了Vue2中的Object.defineProperty来实现响应式。以下是实现核心逻辑的方法:

创建响应式对象

function reactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      track(target, key); // 依赖收集
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return true;
    }
  });
}

依赖收集与触发

proxy实现vue

const targetMap = new WeakMap();
let activeEffect = null;

function track(target, key) {
  if (!activeEffect) return;
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }
  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }
  dep.add(activeEffect);
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  const effects = depsMap.get(key);
  effects && effects.forEach(effect => effect());
}

副作用函数处理

function effect(fn) {
  activeEffect = fn;
  fn();
  activeEffect = null;
}

实现计算属性

基于上述响应式系统,可以扩展实现计算属性:

proxy实现vue

function computed(getter) {
  let value;
  let dirty = true;

  const runner = effect(getter, {
    lazy: true,
    scheduler() {
      dirty = true;
      trigger(obj, 'value');
    }
  });

  const obj = {
    get value() {
      if (dirty) {
        value = runner();
        dirty = false;
      }
      track(obj, 'value');
      return value;
    }
  };

  return obj;
}

实现模板编译

结合Proxy响应式系统,可以模拟Vue的模板编译:

function compile(template) {
  return function render(ctx) {
    const div = document.createElement('div');
    div.innerHTML = template.replace(/{{(.*?)}}/g, (_, exp) => {
      return exp.split('.').reduce((obj, k) => obj[k], ctx);
    });
    return div.firstChild;
  };
}

完整示例组合

将各部分组合成简易Vue实现:

class MiniVue {
  constructor(options) {
    this.$options = options;
    this.$data = reactive(options.data());
    this.proxyData();
    this.$el = document.querySelector(options.el);
    this.compile();
  }

  proxyData() {
    for (const key in this.$data) {
      Object.defineProperty(this, key, {
        get: () => this.$data[key],
        set: val => (this.$data[key] = val)
      });
    }
  }

  compile() {
    const render = compile(this.$options.template);
    effect(() => {
      const newNode = render(this.$data);
      this.$el.innerHTML = '';
      this.$el.appendChild(newNode);
    });
  }
}

注意事项

Proxy相比Object.defineProperty的优势在于能检测到新增属性、数组索引变化等,但需要注意以下问题:

  • 浏览器兼容性:Proxy无法被polyfill
  • 性能考虑:嵌套对象的处理需要递归代理
  • 原始值处理:需要额外包装为对象才能被代理

这种实现展示了Vue响应式原理的核心思想,实际Vue3的实现还包含更多优化和边界情况处理。

标签: proxyvue
分享给朋友:

相关文章

vue 路由 实现

vue 路由 实现

Vue 路由实现方法 Vue Router 是 Vue.js 的官方路由管理器,用于构建单页面应用(SPA)。以下是实现 Vue 路由的详细步骤: 安装 Vue Router 通过 npm 或 ya…

简单实现vue

简单实现vue

Vue 的基本实现 创建一个简单的 Vue 应用需要引入 Vue 库,并编写基本的模板和数据绑定逻辑。 <!DOCTYPE html> <html lang="en"> &l…

vue实现表白

vue实现表白

Vue 实现表白页面 使用 Vue 可以快速创建一个动态、交互式的表白页面。以下是一个简单的实现方案: 基础结构 创建一个 Vue 项目或单文件组件,包含以下核心部分: <template&…

vue实现单据

vue实现单据

Vue 实现单据功能的方法 使用 Vue 实现单据功能通常涉及表单设计、数据绑定、验证和提交等环节。以下是具体实现方案: 表单设计与数据绑定 使用 Vue 的 v-model 指令实现表单数据的双向…

vue实现treeselect

vue实现treeselect

Vue TreeSelect 实现方法 使用 Vue 实现 TreeSelect 组件可以通过以下几种方式完成,包括使用现成的第三方库或自行封装组件。 使用第三方库 推荐使用成熟的第三方 TreeS…

vue工序实现

vue工序实现

Vue 工序实现方法 在Vue中实现工序(或流程)功能,通常涉及状态管理、组件通信和动态渲染。以下是几种常见方法: 使用动态组件 通过Vue的<component :is="currentCo…