当前位置:首页 > JavaScript

js 实现mvvm

2026-02-02 09:17:15JavaScript

js 实现mvvm

js 实现mvvm

MVVM 实现原理

MVVM(Model-View-ViewModel)是一种前端架构模式,核心在于数据绑定和视图与数据的自动同步。在 JavaScript 中实现 MVVM 通常需要以下几个关键部分:

  • 数据劫持/代理:通过 Object.definePropertyProxy 监听数据变化。
  • 依赖收集:在数据读取时收集依赖(如模板中的变量),数据变化时通知依赖更新。
  • 模板编译:解析模板中的指令(如 v-model{{}}),绑定数据与视图。

核心代码实现

数据劫持(基于 Proxy

class Observer {
  constructor(data) {
    return this.defineReactive(data);
  }

  defineReactive(data) {
    const dep = new Dep();
    return new Proxy(data, {
      get(target, key) {
        Dep.target && dep.addSub(Dep.target); // 收集依赖
        return target[key];
      },
      set(target, key, value) {
        target[key] = value;
        dep.notify(); // 触发更新
        return true;
      },
    });
  }
}

依赖管理

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}
Dep.target = null; // 全局唯一依赖标记

编译模板(简单示例)

class Compiler {
  constructor(el, vm) {
    this.el = document.querySelector(el);
    this.vm = vm;
    this.compile(this.el);
  }

  compile(node) {
    Array.from(node.childNodes).forEach(child => {
      if (child.nodeType === 3) { // 文本节点
        this.compileText(child);
      } else if (child.nodeType === 1) { // 元素节点
        this.compileElement(child);
      }
      if (child.childNodes.length) {
        this.compile(child);
      }
    });
  }

  compileText(node) {
    const text = node.textContent;
    const reg = /\{\{(.*?)\}\}/g;
    if (reg.test(text)) {
      const key = RegExp.$1.trim();
      new Watcher(this.vm, key, val => {
        node.textContent = text.replace(reg, val);
      });
    }
  }
}

观察者(Watcher)

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

完整 MVVM 类

class MVVM {
  constructor(options) {
    this.$el = options.el;
    this.$data = options.data;
    new Observer(this.$data);
    new Compiler(this.$el, this);
    this.proxyData(this.$data);
  }

  proxyData(data) {
    Object.keys(data).forEach(key => {
      Object.defineProperty(this, key, {
        get() {
          return data[key];
        },
        set(newVal) {
          data[key] = newVal;
        },
      });
    });
  }
}

使用示例

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

<script>
  const vm = new MVVM({
    el: '#app',
    data: { message: 'Hello MVVM!' },
  });
</script>

关键点说明

  1. 数据劫持:通过 ProxyObject.defineProperty 监听数据变化。
  2. 依赖收集:在模板编译过程中,解析 {{}} 或指令时会创建 Watcher,触发数据的 getter 从而收集依赖。
  3. 更新触发:数据变化时通过 setter 通知 Dep,进而调用所有 Watcherupdate 方法更新视图。

此实现为简化版,实际框架(如 Vue)会处理更多边界条件和性能优化。

标签: jsmvvm
分享给朋友:

相关文章

css3结合js制作

css3结合js制作

CSS3 结合 JavaScript 制作动态效果 CSS3 和 JavaScript 结合可以实现丰富的动态效果,包括动画、交互和响应式设计。以下是几种常见的实现方式: CSS3 动画与 Java…

js 进度条的实现

js 进度条的实现

使用 HTML 和 CSS 创建基础进度条 HTML 结构可以简单使用一个 div 元素作为容器,内部嵌套另一个 div 表示进度: <div class="progress-containe…

js 实现vue

js 实现vue

Vue.js 的基本实现 在 JavaScript 中实现 Vue.js 的核心功能,可以通过数据绑定、响应式系统和虚拟 DOM 来实现。以下是实现 Vue.js 核心功能的简化版本。 数据响应式系…

js实现tab选项卡切换

js实现tab选项卡切换

实现Tab选项卡切换的JavaScript方法 使用纯JavaScript实现Tab切换功能,可以通过监听点击事件动态切换内容显示状态。以下是两种常见实现方式: 基础DOM操作实现 // 获取所有…

js 实现mvc

js 实现mvc

MVC 模式简介 MVC(Model-View-Controller)是一种软件设计模式,将应用程序分为三个核心组件:模型(Model)处理数据和业务逻辑,视图(View)负责展示数据,控制器(Con…

vue js实现弹窗

vue js实现弹窗

Vue.js 实现弹窗的方法 使用组件实现弹窗 创建一个独立的弹窗组件,例如 Modal.vue,包含弹窗的 HTML 结构和样式。在组件中定义 props 控制弹窗的显示与隐藏。 <temp…