当前位置:首页 > JavaScript

js mvvm 实现

2026-03-01 03:58:53JavaScript

MVVM 实现原理

MVVM(Model-View-ViewModel)是一种前端架构模式,通过数据绑定实现视图与数据的自动同步。核心在于ViewModel作为中间层,连接View和Model。

核心实现步骤

数据劫持(响应式) 通过Object.definePropertyProxy监听数据变化:

js mvvm 实现

// Proxy实现
const data = { text: '' };
const handler = {
  set(target, key, value) {
    target[key] = value;
    updateView(); // 触发视图更新
    return true;
  }
};
const viewModel = new Proxy(data, handler);

模板编译 解析DOM模板中的指令(如v-model)并建立绑定关系:

function compile(el) {
  const nodes = el.querySelectorAll('[v-model]');
  nodes.forEach(node => {
    const key = node.getAttribute('v-model');
    node.addEventListener('input', (e) => {
      viewModel[key] = e.target.value; // 数据变更触发Proxy.set
    });
    node.value = viewModel[key]; // 初始化值
  });
}

依赖收集 通过Dep类和Watcher实现发布-订阅模式:

js mvvm 实现

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;
    vm[key]; // 触发getter收集依赖
    Dep.target = null;
  }
  update() { this.cb(this.vm[this.key]); }
}

完整示例实现

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

    this.observe(this.$data);
    this.compile(this.$el);
  }

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

  compile(el) {
    const childNodes = el.childNodes;
    childNodes.forEach(node => {
      if (node.nodeType === 3) { // 文本节点
        const text = node.textContent;
        const reg = /\{\{(.*?)\}\}/;
        if (reg.test(text)) {
          const key = RegExp.$1.trim();
          new Watcher(this.$data, key, val => {
            node.textContent = text.replace(reg, val);
          });
          node.textContent = text.replace(reg, this.$data[key]);
        }
      }
    });
  }
}

关键优化点

虚拟DOM Diff 复杂场景下可引入虚拟DOM提高性能:

function createVNode(tag, props, children) {
  return { tag, props, children };
}

function diff(oldVNode, newVNode) {
  // 实现差异对比算法
}

批量异步更新 使用PromiseMutationObserver合并多次更新:

let pending = false;
function queueUpdate() {
  if (!pending) {
    pending = true;
    Promise.resolve().then(() => {
      updateView();
      pending = false;
    });
  }
}

以上实现展示了MVVM的核心机制,实际框架(如Vue)会包含更多优化和功能扩展。

标签: jsmvvm
分享给朋友:

相关文章

js实现跳转

js实现跳转

使用 window.location 跳转 通过修改 window.location.href 实现页面跳转,这是最常用的方法。 window.location.href = 'https://…

js实现复制

js实现复制

使用document.execCommand方法 在较旧的浏览器中,可以使用document.execCommand('copy')实现复制功能。创建一个临时的textarea或input元素,将需要…

js实现论坛

js实现论坛

实现论坛的基本功能 使用JavaScript实现一个论坛需要结合前端和后端技术。前端可以使用React、Vue或Angular等框架,后端可以选择Node.js配合Express或Koa框架。数据库可…

js实现驼峰

js实现驼峰

实现驼峰命名的几种方法 使用正则表达式和字符串替换 通过正则表达式匹配字符串中的特定模式(如下划线或短横线),并将其后的字母转换为大写,同时移除分隔符。 function toCamelCase(s…

js实现图

js实现图

JavaScript 实现图的常用方法 在 JavaScript 中,图(Graph)可以通过多种方式实现,常见的包括邻接表(Adjacency List)和邻接矩阵(Adjacency Matrix…

js树实现

js树实现

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