当前位置:首页 > JavaScript

js mvvm实现

2026-01-31 22:24:41JavaScript

MVVM 模式简介

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

核心实现步骤

数据劫持(响应式原理)

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

// 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}})并建立依赖关系:

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

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

js mvvm实现

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
分享给朋友:

相关文章

vue怎样实现mvvm

vue怎样实现mvvm

Vue 实现 MVVM 的原理 Vue 的 MVVM(Model-View-ViewModel)模式通过数据绑定和响应式系统实现视图与数据的自动同步。以下是 Vue 实现 MVVM 的核心机制: 数…

js实现跳转

js实现跳转

使用 window.location 跳转 通过修改 window.location.href 或直接使用 window.location 实现页面跳转,适用于普通跳转或带参数的 URL。 // 方…

js实现报表

js实现报表

使用JavaScript实现报表 在JavaScript中实现报表功能可以通过多种方式完成,常见的方法包括使用原生JavaScript、第三方库(如Chart.js、D3.js)或结合后端数据渲染。以…

js实现路由

js实现路由

js实现路由的方法 在JavaScript中实现路由功能可以通过多种方式完成,以下是几种常见的方法: 使用原生JavaScript实现路由 通过监听window.onhashchange事件来实现基…

js 实现全选

js 实现全选

实现全选功能的方法 使用 JavaScript 实现全选功能通常需要操作复选框(checkbox)的状态。以下是几种常见的实现方式。 通过 DOM 操作实现全选 // 获取全选复选框和子复选框 co…

js 实现图片轮播

js 实现图片轮播

基础实现方案 使用HTML、CSS和JavaScript创建一个简单的图片轮播。HTML部分定义轮播容器和图片,CSS负责样式布局,JavaScript处理轮播逻辑。 <div class="…