如何实现一个轻量级的MVVM框架


实现轻量级MVVM需核心四步:1. 用Proxy劫持数据实现响应式;2. 遍历DOM解析{{}}和v-model指令;3. 编译时收集依赖,将更新函数存入watchers;4. 数据变化时触发回调,通知所有依赖更新视图。

如何实现一个轻量级的mvvm框架

实现一个轻量级的MVVM框架,核心在于数据绑定、响应式更新和视图与模型的分离。不需要依赖庞大的库,只需抓住几个关键机制:数据劫持、模板解析、依赖收集和视图更新。下面一步步说明如何从零构建一个极简但可用的 MVVM 框架。

数据劫持与响应式系统

要让数据变化能自动触发视图更新,必须监听数据的变化。在现代 J*aScript 中,可以使用 Proxy 或 Object.defineProperty 来实现属性的 getter 和 setter 劫持。

这里以 Proxy 为例,因为它更简洁且支持数组和动态属性:

const observe = (data, callback) => { return new Proxy(data, { get(target, key, receiver) { return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { const oldValue = target[key]; const result = Reflect.set(target, key, value, receiver); if (oldValue !== value) { callback(key, value); // 通知变化 } return result; } }); };

这个函数将传入的对象包装成响应式对象,每次修改属性时都会调用回调函数。

模板解析与指令识别

MVVM 的核心是把数据渲染到 DOM。我们需要解析模板中的绑定语法,比如 {{ message }} 或自定义指令如 v-model。

遍历 DOM 节点,查找文本节点中的插值表达式或元素上的指令:

const compile = (el, data, updateView) => { const childNodes = el.childNodes; childNodes.forEach(node => { if (node.nodeType === 3) { // 文本节点 const text = node.textContent; const reg = /\{\{(.+?)\}\}/g; if (reg.test(text)) { const key = RegExp.$1.trim(); updateView(node, key); // 初次更新 // 数据变化时重新执行 updateView } } else if (node.nodeType === 1) { // 元素节点 const attrs = node.attributes; Array.from(attrs).forEach(attr => { if (attr.name === 'v-model') { const key = attr.value; node.value = data[key]; node.addEventListener('input', () => { data[key] = node.value; }); updateView(node, key, true); // 绑定 input 更新 } }); } if (node.childNodes.length) { compile(node, data, updateView); // 递归子节点 } }); };

依赖收集与视图更新

当数据变化时,需要知道哪些视图依赖了该数据。可以在初始化编译时记录每个绑定对应的 DOM 节点和更新逻辑。

ThinkPHP3.2.3完全开发 ThinkPHP3.2.3完全开发

ThinkPHP是一个快速、简单的基于MVC和面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,尤其注重开发体验和易用性,并且拥有众多的原创功能和特性,为WEB应用开发提供了强有力的支持。 3.2版本则在原来的基础上进行一些架构的调整,引入了命名空间支持和模块化的完善,为大型应用和模块化开发提供了更多的便利。

ThinkPHP3.2.3完全开发 321 查看详情 ThinkPHP3.2.3完全开发

定义一个简单的更新函数:

const updateView = (node, key, isInput = false) => { if (isInput) { node.addEventListener('input', e => { vm.$data[key] = e.target.value; }); } // 初始化和后续更新都通过此函数 const updateFn = () => { if (isInput) { node.value = vm.$data[key]; } else { node.textContent = vm.$data[key]; } }; // 立即执行一次 updateFn(); // 将更新函数注册为该 key 的订阅者(简化版) vm.$watchers[key].push(updateFn); };

在数据劫持的回调中通知所有订阅者更新:

this.$watchers = {}; Object.keys(this.$data).forEach(key => { this.$watchers[key] = []; }); // 在 observe 的 callback 中: callback = (key, value) => { this.$watchers[key].forEach(fn => fn()); };

整合成 MVVM 类

把以上逻辑封装成一个类:

class TinyMVVM { constructor(options) { this.$el = options.el; this.$data = options.data(); this.$watchers = {}; Object.keys(this.$data).forEach(key => { this.$watchers[key] = []; }); // 响应式化数据 this.$data = observe(this.$data, (key, value) => { this.$watchers[key].forEach(fn => fn()); }); // 编译模板 const el = document.querySelector(this.$el); compile(el, this.$data, (node, key, isInput) => { const updateFn = () => { if (isInput) { node.value = this.$data[key]; } else { node.textContent = this.$data[key]; } }; updateFn(); this.$watchers[key].push(updateFn); }); } }

使用方式:

new TinyMVVM({ el: '#app', data() { return { message: 'Hello Tiny MVVM!' }; } });

HTML 示例:

{{ message }}

基本上就这些。一个轻量级 MVVM 的核心就是数据劫持 + 模板解析 + 视图更新。虽然没有 Vue 那样完整的虚拟 DOM 和编译优化,但理解这些原理有助于掌握响应式框架的本质。不复杂但容易忽略细节,比如递归编译、事件绑定和依赖管理。

以上就是如何实现一个轻量级的MVVM框架的详细内容,更多请关注其它相关文章!


# 新和  # 靠谱网站推广加盟项目  # 长丰营销推广公司  # 海门企业网站推广  # 婚纱的网络营销推广形式  # 五莲搜索排名关键词  # SEO堆砌关键字  # SEO标题优化分类  # 肇庆seo文章标题  # 海鲜餐饮营销推广方案ppt  # 专注营销推广比较实惠  # 是一个  # 后端  # 复用  # 服务端  # mvvm框架  # 遍历  # 如何实现  # 回调  # 绑定  # 递归  # proxy  # 回调函数  # app  # node  # html  # java  # javascript  # vue  # 轻量 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894 】


相关推荐: sublime text 4如何安装_最新版sublime下载与汉化教程  无人机考证官网 中国民航无人机考证官网登录入口  如何在解析前预检查XML文件的完整性? 比如检查文件大小或特定结束标签  芒果TV官网登录入口 芒果TV官方网站登录入口  苹果17 Pro如何启用分屏浏览_iPhone 17 Pro分屏浏览设置步骤  《百果园》充值余额方法  steam缓存文件在哪儿_steam缓存文件的路径查找方法与结构说明  苹果11如何更换iCloud账号_苹果11账号切换的具体步骤  mysql中如何配置字符集和排序规则_mysql字符集排序配置  CDR如何复制交互式填充色  J*aScript 数值去小数位处理:多种方法与实践  利用Flexbox实现图片元素的二维布局:2x2网格排列指南  铁路12306官网登录入口 铁路12306在线购票官方平台  Dash应用中自定义HTML页面标题与网站图标(F*icon)的实用指南  毒蘑菇VOLUMESHADER_BM官网首页登录入口 毒蘑菇VOLUMESHADER_BM官网首页登录入口说明  厨房地面防滑垫的油污怎么洗? 机洗和手洗防滑垫的注意事项  京东快递物流信息不更新怎么办_物流停滞原因与处理方法  向日葵客户端怎么进行语音通话_向日葵客户端语音通话功能使用方法  太平年在哪个平台播出  cad加载的线型看不见怎么办_cad线型不可见问题解决方法  OTT月报 | 2025年9月智能电视大数据报告  优化响应式标题底部边框:CSS实现技巧与最佳实践  b站怎么查看视频的码率_b站视频码率查看方法  如何配置VS Code作为您Git操作的默认编辑器  c++中的const关键字用法大全_c++ const正确使用指南  招商淘客入门指南  《广发易淘金》国债逆回购操作教程  《一起考教师》账号注销方法  Google Drive API服务器端访问指南:服务账户认证详解  高德地图怎么查看未来行程规划_高德地图未来行程规划查看方法  C++ static关键字作用_C++静态成员变量与静态函数  4399正版网页版入口高清直达链接  发布小红书怎么屏蔽粉丝?屏蔽粉丝能看到吗?  VBA Outlook邮件自动化:高效集成Excel数据与列标题的策略  uc浏览器官网网页版使用 uc浏览器官网免费在线首页  《深林》冬季章节图文攻略  Excel怎么用XLOOKUP函数实现双向查找_ExcelXLOOKUP替代VLOOKUP+HLOOKUP的高级用法  《豆瓣》私信用户方法  C++ optional用法详解_C++17处理可能为空的返回值  铁路12306官网入口 铁路12306中国铁路官网登录首页  AffinityDesigner图层蒙版怎么用_AffinityDesigner图层蒙版设计应用  使用VS Code作为你的个人知识管理系统  如何外贸网站设计-能留住客户提升用户体验!  猫眼电影app如何筛选支持退改签的影院_猫眼电影退改签影院筛选方法  猫眼电影app如何设置电影上映提醒_猫眼电影上映提醒设置教程  钉钉任务无法提醒如何处理 钉钉任务提醒优化方法  如何在Python中安全地将环境变量转换为整数并满足Mypy类型检查  管理打开的编辑器:固定、分组和关闭技巧  在Dash应用中自定义HTML标题和网站图标  电脑视频号|直播|如何分享屏幕 

 2025-11-01

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.