手把手教你实现MVVM架构
引言
现在的前端真可谓是百花齐放,百家争鸣,各种框架层出不穷,但是主要目前用的最多的还是要数Vue
、React
、以及Angular
,这三种,当然不乏近期新出的一些其他框架,但是她们都有一个显著的特点,那就是使用了MVVM的架构。
首先我们要搞清楚什么是
MVVM
?
MVVM
就是Model-View-ViewModel的缩写,MVVM
最早由微软提出来,它借鉴了桌面应用程序的MVC
思想,在前端页面中,把Model
用纯JavaScript
对象表示,View
负责显示,两者做到了最大限度的分离。把Model
和View
关联起来的就是ViewModel
。ViewModel
负责把Model
的数据同步到View
显示出来,还负责把View
的修改同步回Model
。改变
JavaScript
对象的状态,会导致DOM结构
作出对应的变化!这让我们的关注点从如何操作DOM
变成了如何更新JavaScript
对象的状态,而操作JavaScript
对象比DOM
简单多了。这就是
MVVM
的设计思想:关注Model
的变化,让MVVM
框架去自动更新DOM
的状态,从而把开发者从操作DOM
的繁琐步骤中解脱出来!
接下来我会带着你们如何去实现一个简易的MVVM架构。
一、构建MVVM构造函数
创建一个MVVM
构造函数,用于接收参数,如:data
、methods
、computed
等:
function MVVM(options) { this.$options = options; let data = this._data = this.$options.data; observe(data); for (let key in data) { Object.defineProperty(this, key, { enumerable: true, get() { return this._data[key]; }, set(newVal) { this._data[key] = newVal; } }); }; initComputed.call(this); new Compile(options.el, this); options.mounted.call(this);
}
复制代码
二、构建Observe构造函数
创建一个Observe
构造函数,用于监听数据变化:
function Observe(data) { let dep = new Dep(); for (let key in data) { let val = data[key]; observe(val); Object.defineProperty(data, key, { enumerable: true, get() { Dep.target && dep.addSub(Dep.target); return val; }, set(newVal) { if (val === newVal) { return; } val = newVal; observe(newVal); dep.notify(); } }); };
};
复制代码
三、构建Compile构造函数
创建一个Compile
构造函数,用于解析模板指令:
function Compile(el, vm) { vm.$el = document.querySelector(el); let fragment = document.createDocumentFragment(); while (child = vm.$el.firstChild) { fragment.appendChild(child); } replace(fragment);function replace(frag) {Array.from(frag.childNodes).forEach(node => { let txt = node.textContent; let reg = /\{\{(.*?)\}\}/g; if (node.nodeType === 3 && reg.test(txt)) { let arr = RegExp.$1.split('.'); let val = vm; arr.forEach(key => { val = val[key]; }); node.textContent = txt.replace(reg, val).trim(); new Watcher(vm, RegExp.$1, newVal => { node.textContent = txt.replace(reg, newVal).trim(); }); }if (node.nodeType === 1) { let nodeAttr = node.attributes; Array.from(nodeAttr).forEach(attr => { let name = attr.name; let exp = attr.value; if (name.includes('v-')) { node.value = vm[exp]; } new Watcher(vm, exp, newVal => { node.value = newVal; }); node.addEventListener('input', e => { let newVal = e.target.value; vm[exp] = newVal; }); }); };if (node.childNodes && node.childNodes.length) { replace(node); } }); }vm.$el.appendChild(fragment);
}
复制代码
四、构建Watcher构造函数
创建一个Watcher
构造函数,用于更新视图:
function Watcher(vm, exp, fn) { this.fn = fn; this.vm = vm; this.exp = exp; Dep.target = this; let arr = exp.split('.'); let val = vm; arr.forEach(key => { val = val[key]; }); Dep.target = null;
} Watcher.prototype.update = function() { let arr = this.exp.split('.'); let val = this.vm; arr.forEach(key => { val = val[key]; }); this.fn(val);
}
复制代码
五、构建Dep构造函数
创建一个Dep
构造函数,用于管理Watcher
:
function Dep() { this.subs = [];
} Dep.prototype.addSub = function(sub) { this.subs.push(sub);
} Dep.prototype.notify = function() { this.subs.forEach(sub => { sub.update(); });
}
复制代码
六、构建initComputed构造函数
创建一个initComputed
构造函数,用于初始化计算属性:
function initComputed() { let vm = this; let computed = this.$options.computed; Object.keys(computed).forEach(key => { Object.defineProperty(vm, key, { get: typeof computed[key] === 'function' ? computed[key] : computed[key].get, set() {} }); });
}
复制代码
总结:
至此我们就完成了一个简易的MVVM框架,虽然简易,但是基本的核心思想差不多都已经表达出来了,最后还是希望大家不要丢在收藏文件夹里吃灰,还是要多多动手练习一下,所谓眼过千遍,不如手过一遍。
手把手教你实现MVVM架构相关推荐
- Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影系统
作者:JackTian 微信公众号:杰哥的IT之旅(ID:Jake_Internet) LAMP 系列导读 01. LAMP 系列教程(一)| 详解 Linux 环境下部署 HTTPD 服务 02. ...
- 手机端创新体验——手把手教你搭建VRAR架构
声明:本文阿里巴巴技术论坛整理文章,首发于CSDN,未经许可,禁止任何形式的转载. 作者:袁岳峰,阿里移动平台虚拟&互动实验室负责人,GM Lab技术负责人. 责编:钱曙光,关注架构和算法领域 ...
- 阿里云专家手把手教你重塑 IT 架构!
进入21世纪以来,我们见证了企业分布式应用架构从SOA(Service-Oriented Architecture)到微服务架构,再到云原生应用架构的演化. 为了说明企业架构演化背后的思考,我们先谈一 ...
- 大神手把手教你设计秒杀架构模型
中生代技术 链接技术大咖,分享技术干货 全文:4000字 作者:Yrion 原文首发:https://www.cnblogs.com/wyq178/p/11261711.html 前言:秒杀系统相信很 ...
- 资深架构师手把手教你性能优化
图片来源:pexels.com 孔庆龙,一线架构师,具有多年的金融架构经验,具备 SOA 服务化.服务治理.系统优化.分布式系统项目经验.目前关注于互联网金融技术架构设计.分布式架构.微服务架构.De ...
- 百度架构师手把手教深度学习之心得
<<百度架构师手把手教深度学习>>心得 课程内容 作业打磨 感言 祝愿 课程链接 经过紧张有序的三个星期的学习,终于完成了<百度架构师手把手教深度学习>>! ...
- 手把手教你架构3D引擎高级篇概述
前几年写过一本书<手把手教你架构3D游戏引擎>电子工业出版社,主要内容讲的是固定流水线编程,目的是让读者理解第一代引擎是如何实现的,从本篇博客开始,给读者介绍关于使用可编程流水线自己搭建3 ...
- 云架构师进阶【SAP迁移方案设计】手把手教您玩转SAP上云
一,项目背景介绍 今天又接到了北京某制造企业SAP迁移的场景,先简单说明一下,好好的SAP在运行着为什么要做迁移这类大动作呢?众所周知SAP的ERP是企业的绝对核心系统,尤其对于制造业更是核心的系统, ...
- [原创]手把手教你写网络爬虫(2):迷你爬虫架构
手把手教你写网络爬虫(2) 作者:拓海 (https://github.com/tuohai666) 摘要:从零开始写爬虫,初学者的速成指南! 封面: 介绍 大家好!回顾上一期,我们在介绍了爬虫的基本 ...
最新文章
- msteel能计算钢结构楼梯吗_坚持爬楼梯能减肥吗 怎么爬楼梯可以减肥
- 双系统XP和ubuntu,升级ubuntu出现no such device grub rescue
- 项目: 用easyx实现消砖块
- php抓取页面400错误
- Python中各进制间的转换
- 数组和lookup函数
- 训练日志 2019.7.25
- 消除ie上的:为了有利于保护安全性,IE已限制此网页运行可以访问计算机的脚本或 ActiveX 控件...
- 《中国人工智能学会通讯》——11.34 基于近似动态规划的优化控制研究及 在电力系统中的应用...
- python400集视频教程-微软官方出品的400集Python精品视频教程,这正是我们急需的!...
- php自学好还是培训,转行php选择自学还是培训
- 对比修改过的两个BOM表
- Kotlin教程,从入门到精通
- google翻译退出中国后如何仍然使用windows版本
- 龙果 mycat mysql_龙果学院Spring Boot源码解析视频教程完整未加密(价值599)
- ttl接地是高电平还是低电平_说明图3.12中各门电路的输出是高电平还是低电平。已知它们都是74HC系列的CMOS电路 简单的逻辑门电路 判断各门电路...
- 计算机无法识别ipad2,win10系统无法识别iphone、ipad的修复方法
- 哔咔漫画怎样切换横屏?
- boundschecher2
- php 促销方案,七步就轻松搞定,促销活动方案
热门文章
- securecrt启动mini2440卡在Please press Enter to activate this console问题已解决
- assert利用蚁剑登录
- Salesforce考试丨Marketing Cloud管理员认证考试指南 exam guide(中文版)
- 【性能评估】ROC曲线
- 计算机和信息技术主题,主题二信息技术及其应用和发展.ppt
- 戴尔 Vostro 3470 成就商务台式机(i3-8100) 安装Win7系统
- 人人都是产品经理2.0-02章摘要总结
- 计算机无法识别相机,教您如果戴尔计算机无法检测到相机怎么办
- ORA-12899:value too large for column
- 【Java成王之路】EE初阶第二十三篇: HTTP协议和Tomcat