author: 陈家宾
email: 617822642@qq.com
date: 2018/3/1
复制代码

MVVM 背景

都说懒惰使人进步,MVVM 的进化史,正印证了这句话,是一步步让开发人员更懒惰更简单的历史:

直接 DOM 操作 -> MVC -> MVP -> MVVM

最开始的前端交互,是很直接的 DOM 操作,最出名的这类库当数 jQuery 了,封装了 DOM API,让一切 DOM 操作都变得简单。

但当页面数据和交互多的时候,散乱的代码将使项目变得难以维护,让人发狂。所以才有了 MV* 模式的发展。

MV* 模式

MVC & MVP & MVVM 三者对比伪代码:点我

MVC

  • Model:数据模型 & 手动渲染模板
  • View:模板
  • Controller:修改数据

MVP

  • Model:数据模型
  • View:模板
  • Presenter:修改数据 & 手动渲染模板

MVP 是 MVC 模式的一种改造(这里不说改进,是因为两者其实很相似,没有本质上的变化),将 手动渲染 步骤** 从 Model 移到了 Presenter,让 View 和 Model 更独立更存粹了,但从另一个角度来说,也加大了 Presenter 的工作。

MVVM

  • Model:数据模型
  • View:带特殊属性的 html 模板
  • ViewModel:依靠 Directive,修改数据 & 自动渲染

MVVM 模式依靠 Directive,实现了 模板自动渲染,极大地解放了开发者的双手,此时开发者只需关注 View 和 Model,效率和可维护性方面达到了飞跃式的进步。

下面将着重介绍下神奇的 Directive。

数据变更检测方案(Directive)

(一)手动触发绑定

在页面需要改变时,手动触发检测,改变 model 数据,并扫描元素,对有特殊标记的元素进行修改

let data = {value: 'hello'
};let directive = {html: function (html) {this.innerHTML = html;},value: function (html) {this.setAttribute('value', value);}
};ViewModelSet('value', 'hello world');function ViewModelSet(key, value) {data[key] = value;scan();
}function scan() {for (let elem of elems) {elem.directive = [];for (let attr of elem.attributes) {if (attr.nodeName.indexOf('v-') >= 0) {directive[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);}}}
}
复制代码

(二)脏检测机制

针对手动绑定进行优化,只对修改到的数据进行更新元素

function scan(elems, val) {let list = document.querySelectorAll(`[v-bind=${val}]`); // 只扫描修改到的数据涉及的元素for (let elem of elems) {for (let attr of elem.attributes) {let dataKey = elem.getAttribute('v-bind');if (elem.directive[attr.nodeValue] !== data[dataKey]) { // 当元素值有变时,更新元素directive[attr.nodeValue].call(elem, data[dataKey]); elem.directive[attr.nodeValue] = data[dataKey]; // 保存元素当前值}}}
}
复制代码

(三)前端数据对象劫持(Hijacking)

在上面的基础更进一步,使用 Object.defineProperty 对数据进行 get & set 监听,当数据有变时,自动执行 scan 扫描并更新元素。

原来是在改变数据时,还要手动 scan。现在只需要直接改变数据,会自动 scan,更新元素。

defineGetAndSet(data, 'value');data.value = 'hello world';function defineGetAndSet(obj, propName) {Object.efineProperty(obj, propName, {get: function () {return this.bVal;},set: function (newVal) {this.bVal = newVal;scan();},enumerable: true,configurable: true});
}
复制代码

(四)ECMAScript 6 Proxy

与方法三类似,换了种写法,这里应用了 ES6 里的 Proxy

let data = new Proxy({get: function (obj, key) {return obj[key];},set: function (obj, key, val) {obj[key] = val;scan();return obj[key];}
});
复制代码

以上。

参考资料

  1. 《现代前端 技术解析》,张成文,2017 年 4 月第 1 版d
  2. 《MVC,MVP 和 MVVM 的图示》,阮一峰,2015年2月 1日,http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html

前端 MVVM 原理相关推荐

  1. 又想到了模板引擎和前端MVVM框架

    最近接手了一个和报表有关的项目.项目后端的大部分工作都是在操作数据库,作为一个后端新手谈不上有什么感觉.但对于看了前端的写法之后,还是有一点点感想. 项目前端主要使用jQuery及其插件,也许这就是大 ...

  2. vue指令写在html中的原理,详解Vue中的MVVM原理和实现方法

    对Vue中的MVVM原理解析和实现首先你对Vue需要有一定的了解,知道MVVM.这样才能更有助于你顺利的完成下面原理的阅读学习和编写下面由我阿巴阿巴的详细走一遍Vue中MVVM原理的实现,这篇文章大家 ...

  3. python sanic orm_Sanic + 前端MVVM 一种新一代Python高性能全栈开发实践

    SanicCRUD-vue Sanic + 前端MVVM 一种新一代Python高性能全栈开发实践 背景 本项目将使用Sanic + Vue2 + Webpack2 配合最简单CRUD的逻辑来展示一个 ...

  4. 浅谈前端路由原理hash和history

    浅谈前端路由原理hash和history

  5. c# mvvm模式获取当前窗口_对Vue中的MVVM原理解析和实现

    首先你对Vue需要有一定的了解,知道MVVM.这样才能更有助于你顺利的完成下面原理的阅读学习和编写 下面由我阿巴阿巴的详细走一遍Vue中MVVM原理的实现,这篇文章大家可以学习到: 1.Vue数据双向 ...

  6. 关于RFID电感耦合方式的射频前端工作原理,你了解吗?

    关于RFID电感耦合方式的射频前端工作原理,你了解吗? IoT的核心技术之一就是RFID,对于RFID的组件RFID读写器和电子标签的工作原理,你了解嘛?其实RFID的两种组件是通过天线进行通信, 采 ...

  7. 「知其所以然」前端技术原理

    文章目录 前言 一.Ajax原理 二.Jsonp原理 三.Cors原理 四.Axios原理 五.Webpack原理 前言 前端技术原理. 一.Ajax原理 [1]浏览器通过Javascript的方式, ...

  8. 奇舞周刊第 460 期:详聊前端异常原理

    记得点击文章末尾的" 阅读原文 "查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 详聊前端异常原理 随着近年来前端监控体系建设日益完善,前端工程师对异常更加关注 ...

  9. 单页面应用的前端路由原理是什么?

    前置知识 在了解单页面应用的前端路由原理之前,我们先了解下什么事单页面应用,什么是多页面应用,他们之间的区别又是什么? 什么是单页面应用? 单页面应用指的是第一次进入页面的时候会请求一个html文件, ...

最新文章

  1. python使用matplotlib可视化堆叠的直方图(stacked histogram plot)、多个类别的数据在直方图区间层面累积堆叠起来
  2. Java 对象都是在堆上分配内存吗?
  3. 20155313 2016-2017-2 《Java程序设计》第二周学习总结
  4. JavaScrpt简单介绍
  5. DCASE挑战赛原始提案文件(详细信息)
  6. 使用AspectCore动态代理
  7. 实现任意行数的杨辉三角
  8. 建筑专业规范大全 2020版_房屋建筑工程现行规范标准目录汇编(2020版)—建筑电气...
  9. java 记事本全选_java 编写的记事本程序怎么实现复制 黏贴 剪切 全选的功能 ?...
  10. Spring Bean的循环依赖解决方案
  11. java中 CopyOnWriteArrayList 的使用
  12. [Linux程序设计][调试][splint]
  13. 51单片机温度控制系统报警器,不会做课程设计的就拿走
  14. 【python中级】通过ISAPI协议接口获得海康IPC云台的PTZ
  15. W806/W801/W800多通道ADC同时使用
  16. Linux系统地址栏,Linux下Chrome地址栏输入卡顿该怎么办?
  17. JavaScript 汉字转拼音
  18. YY游戏云的AngularJS实践
  19. A40i使用笔记:系统配置
  20. JAVA基础(一)——什么是java

热门文章

  1. js之- 简解Promise的resolved,rejected,Promise.all 和Promise.race(知识记录)
  2. 人脸识别技术的优缺点
  3. 淘宝自定义添加旺旺代码
  4. 米老师教你如何解决问题
  5. 2021-01-22Day2
  6. 淘宝穿衣搭配算法_方案三
  7. C#应用程序通过SqlClient读取附加mdf文件数据库的连接字符串
  8. JETSON TX2 突然关机
  9. Unity 2D案例学习——制作Roguelike随机地下城
  10. python print覆盖输出