当前位置:首页 > JavaScript

js mvvm实现

2026-01-31 22:24:41JavaScript

MVVM 模式简介

MVVM(Model-View-ViewModel)是一种前端架构模式,通过数据绑定实现视图(View)与数据模型(Model)的分离,ViewModel 作为中间层负责处理业务逻辑和状态管理。

核心实现步骤

数据劫持(响应式原理)

使用 Object.definePropertyProxy 监听数据变化,触发更新:

js mvvm实现

// Proxy 实现  
const reactive = (obj) => {
  return new Proxy(obj, {
    get(target, key) {
      return Reflect.get(target, key);
    },
    set(target, key, value) {
      Reflect.set(target, key, value);
      console.log(`数据更新: ${key} = ${value}`);
      // 触发视图更新  
      return true;
    }
  });
};

模板编译

解析 DOM 模板,替换插值表达式(如 {{data}})并建立依赖关系:

js mvvm实现

function compile(el, vm) {
  const nodes = el.childNodes;
  nodes.forEach(node => {
    if (node.nodeType === 3) { // 文本节点  
      const text = node.textContent;
      const reg = /\{\{(.*?)\}\}/g;
      if (reg.test(text)) {
        const key = RegExp.$1.trim();
        node.textContent = vm.data[key];
        // 监听数据变化并更新视图  
        new Watcher(vm, key, (val) => {
          node.textContent = val;
        });
      }
    }
  });
}

依赖收集(发布-订阅)

通过 DepWatcher 实现数据变化的订阅与通知:

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

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

整合 ViewModel

将数据劫持、模板编译和依赖收集结合:

class MVVM {
  constructor(options) {
    this.data = reactive(options.data); // 响应式数据  
    this.el = document.querySelector(options.el);
    compile(this.el, this); // 编译模板  
  }
}

使用示例

<div id="app">{{message}}</div>
<script>
  const vm = new MVVM({
    el: '#app',
    data: { message: 'Hello MVVM!' }
  });
  setTimeout(() => {
    vm.data.message = 'Data changed!'; // 触发视图更新  
  }, 1000);
</script>

注意事项

  • 现代框架(如 Vue 3)使用 Proxy 替代 Object.defineProperty,支持深层对象监听。
  • 虚拟 DOM 可优化直接操作 DOM 的性能问题。
  • 双向绑定可通过 v-model 等指令扩展实现。

标签: jsmvvm
分享给朋友:

相关文章

js实现动画

js实现动画

使用 CSS 动画与 JavaScript 控制 通过 JavaScript 动态添加或移除 CSS 类来触发动画。CSS 定义关键帧(@keyframes),JavaScript 通过 classL…

js实现倒计时

js实现倒计时

使用 setInterval 实现倒计时 通过 setInterval 定时器每秒更新剩余时间,适用于简单倒计时场景。 function countdown(seconds, callbac…

vue mvvm实现

vue mvvm实现

Vue 的 MVVM 实现原理 Vue 是一个基于 MVVM(Model-View-ViewModel)设计模式的前端框架,通过数据绑定和响应式系统实现视图与数据的自动同步。以下是 Vue 实现 MV…

js树实现

js树实现

树的基本概念 树是一种非线性的数据结构,由节点和边组成。每个节点包含一个值和指向子节点的引用。树的顶部节点称为根节点,没有子节点的节点称为叶节点。 树的实现方式 在JavaScript中,树可以通过…

vue实现js休眠

vue实现js休眠

实现 JavaScript 休眠的方法 在 Vue 中实现 JavaScript 休眠(延迟执行)可以通过以下方式实现。由于 JavaScript 本身没有内置的 sleep 函数,通常使用 Prom…

js实现视口

js实现视口

js实现视口检测的方法 使用JavaScript检测元素是否进入视口(viewport)可以通过Intersection Observer API或手动计算元素位置实现。以下是两种常见方法: Int…