当前位置:首页 > JavaScript

js实现mvvm

2026-04-07 05:21:45JavaScript

MVVM 模式简介

MVVM(Model-View-ViewModel)是一种前端架构模式,核心思想是将视图(View)与业务逻辑(ViewModel)解耦,通过数据绑定实现双向同步。Model 管理数据,View 负责渲染,ViewModel 作为桥梁处理逻辑和状态。

js实现mvvm

实现 MVVM 的关键技术

  1. 数据劫持(响应式数据)
    通过 Object.definePropertyProxy 监听数据变化,触发更新。

    js实现mvvm

    // 使用 Proxy 实现响应式
    function reactive(obj) {
      return new Proxy(obj, {
        get(target, key) {
          return target[key];
        },
        set(target, key, value) {
          target[key] = value;
          updateView(); // 触发视图更新
          return true;
        }
      });
    }
  2. 模板编译
    解析 HTML 模板中的指令(如 v-model{{}}),替换为动态数据并绑定事件。

    function compile(template, data) {
      return template.replace(/\{\{(.*?)\}\}/g, (_, key) => {
        return data[key.trim()];
      });
    }
  3. 依赖收集与发布订阅
    为每个数据属性维护一个依赖列表(Dep),当数据变化时通知所有依赖(Watcher)更新。

    class Dep {
      constructor() {
        this.subscribers = [];
      }
      depend() {
        if (Watcher.target) this.subscribers.push(Watcher.target);
      }
      notify() {
        this.subscribers.forEach(watcher => watcher.update());
      }
    }

完整实现示例

class MVVM {
  constructor(options) {
    this.$el = document.querySelector(options.el);
    this.$data = options.data;
    this.observe(this.$data);
    this.compile(this.$el);
  }

  observe(data) {
    Object.keys(data).forEach(key => {
      let value = data[key];
      const dep = new Dep();
      Object.defineProperty(data, key, {
        get() {
          if (Watcher.target) dep.depend();
          return value;
        },
        set(newVal) {
          value = newVal;
          dep.notify();
        }
      });
    });
  }

  compile(node) {
    Array.from(node.childNodes).forEach(child => {
      if (child.nodeType === 3) { // 文本节点
        const text = child.textContent;
        const reg = /\{\{(.*?)\}\}/g;
        if (reg.test(text)) {
          const key = RegExp.$1.trim();
          new Watcher(this.$data, key, () => {
            child.textContent = text.replace(reg, this.$data[key]);
          });
        }
      } else if (child.nodeType === 1) { // 元素节点
        Array.from(child.attributes).forEach(attr => {
          if (attr.name === 'v-model') {
            const key = attr.value;
            child.value = this.$data[key];
            child.addEventListener('input', e => {
              this.$data[key] = e.target.value;
            });
            new Watcher(this.$data, key, () => {
              child.value = this.$data[key];
            });
          }
        });
        this.compile(child);
      }
    });
  }
}

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

使用示例

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

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

优化方向

  1. 虚拟 DOM:减少直接 DOM 操作,通过 diff 算法批量更新。
  2. 指令扩展:支持 v-forv-if 等复杂指令。
  3. 性能优化:避免不必要的依赖触发,如计算属性缓存。

通过以上实现,可以构建一个基础的 MVVM 框架,类似 Vue 的响应式原理。

标签: jsmvvm
分享给朋友:

相关文章

js实现图片预览

js实现图片预览

使用FileReader API实现图片预览 通过FileReader对象读取用户选择的图片文件并显示预览: const input = document.getElementById('image…

js进度条实现

js进度条实现

使用HTML和CSS创建基础结构 在HTML中创建一个容器元素用于显示进度条,通常使用<div>元素。CSS用于设置进度条的样式,包括宽度、高度、颜色和圆角等属性。 <div cl…

js 实现页面刷新

js 实现页面刷新

使用 location.reload() location.reload() 是原生 JavaScript 提供的页面刷新方法。调用该方法会重新加载当前页面,相当于点击浏览器的刷新按钮。 // 基本…

js实现删除

js实现删除

使用 splice 方法删除数组元素 splice 方法可以删除数组中的元素,并返回被删除的元素。它接受两个参数:起始索引和要删除的元素数量。 const array = [1, 2, 3, 4…

js 实现日历

js 实现日历

实现日历的基本思路 日历的核心功能是展示日期,并允许用户进行日期选择或导航。JavaScript 可以动态生成日历的 HTML 结构,并处理用户交互逻辑。 基础日历结构 日历通常包含头部(显示月份和…

js实现图片移动

js实现图片移动

使用CSS和JavaScript实现图片移动 方法一:使用CSS动画结合JavaScript控制 通过CSS定义动画关键帧,JavaScript动态添加或移除动画类。 /* CSS部分 */ .m…