MVVM 是 Model-View-ViewModel 缩写,也就是把 MVC 中的 Controller 演变成 ViewModel。Model 层代表数据模型,View 代表 UI 组件,ViewModel 是 View 和 Model 层的桥梁,数据会绑定到 viewModel 层并自动将数据渲染到页面中,视图变化的时候会通知 viewModel 层更新数据。

  1. Model: 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑。我们可以把 Model 称为数据层,因为它仅仅关注数据本身,不关心任何行为
  2. View: 用户操作界面。当 ViewModel 对 Model 进行更新的时候,会通过数据绑定更新到 View
  3. ViewModel: 业务逻辑层,View 需要什么数据,ViewModel 要提供这个数据;View 有某些操作,ViewModel 就要响应这些操作,所以可以说它是 Model for View.

总结: MVVM 模式简化了界面与业务的依赖,解决了数据频繁更新。MVVM 在使用当中,利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。

实现一个简易的 MVVM 分为这么几步来

1.类 Vue:这个类接收的是一个 options。
   el属性:根元素的id
data属性:双向绑定的数据。
2.Dep 类:
   subNode数组:存放所依赖这个属性  的依赖,
addSub方法:添加依赖的
removeSub方法:删除,
updata方法:遍历更新它subs中的所有依赖
target静态属性:用来表示 '当前的观察者' ,依赖收集的时候可以将它添加到dep. subNode中 静态的是指向类自身,而不是指向实例对象,主要是归属不同,这是静态属性的核心
3.observe 方法:监听数据变化(参数:data,也就是 options.data)
   遍历data:使用Object.defineProperty()来重写它的get和set,
使用new Dep():实例化一个dep对象,
get时:addSub 添加 '当前的观察者Dep.target' 完成依赖收集,
set时:dep.updata 通知每一个依赖它的观察者进行更新
4.compile 方法:来将 HTML 模版和数据结合起来(参数:node 节点)。
   遍历它的所有子级,判断是否有firstElmentChild
有:进行递归调用compile方法,
没有:child.innderHTML用判断是否有(/\{\{(.*)\}\}/)需要双向绑定的数据,
有:new Reg('\\{\\{\\s*' + key + '\\s*\\}\\}', 'gm')替换msg变量。
5.将 Dep.target 指向当前的这个 child,
  调用this.opt.data[key]:触发这个数据的get来对当前的child进行依赖收集,
目的:下次数据变化通知child进行视图更新,
将Dep.target指为null(其实在Vue中是有一个targetStack栈用来存放target的指向的)
6.监听 document 的 DOMContentLoaded
   回调函数中实例化这个Vue对象就可以了

需要注意的点:

childNodes 会获取到所有的子节点以及文本节点(包括元素标签中的空白节点)

firstElementChild 表示获取元素的第一个字元素节点,以此来区分是不是元素节点,如果是的话则调用 compile 进行递归调用,否则用正则匹配

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>MVVM</title>
</head>
<body>
<div id="app">
<h3>姓名</h3>
<p>{{name}}</p>
<h3>年龄</h3>
<p>{{age}}</p>
</div>
</body>
</html>
<script>
document.addEventListener(
"DOMContentLoaded",
function () {
let opt = { el: "#app", data: { name: "等待修改...", age: 20 } };
let vm = new Vue(opt);
setTimeout(() => {
opt.data.name = "jing";
}, 2000);
},
false
);
class Vue {
constructor(opt) {
this.opt = opt;
this.observer(opt.data);
let root = document.querySelector(opt.el);
this.compile(root);
}
observer(data) {
Object.keys(data).forEach((key) => {
let obv = new Dep();
data["_" + key] = data[key]; Object.defineProperty(data, key, {
get() {
Dep.target && obv.addSubNode(Dep.target);
return data["_" + key];
},
set(newVal) {
obv.update(newVal);
data["_" + key] = newVal;
},
});
});
}
compile(node) {
[].forEach.call(node.childNodes, (child) => {
if (!child.firstElementChild && /\{\{(.*)\}\}/.test(child.innerHTML)) {
let key = RegExp.$1.trim();
child.innerHTML = child.innerHTML.replace(
new RegExp("\\{\\{\\s*" + key + "\\s*\\}\\}", "gm"),
this.opt.data[key]
);
Dep.target = child;
this.opt.data[key];
Dep.target = null;
} else if (child.firstElementChild) this.compile(child);
});
}
} class Dep {
constructor() {
this.subNode = [];
}
addSubNode(node) {
this.subNode.push(node);
}
update(newVal) {
this.subNode.forEach((node) => {
node.innerHTML = newVal;
});
}
}
</script>

10分钟了解MVVM,实现简易MVVM的更多相关文章

  1. 不用搭环境的10分钟AngularJS指令简易入门01(含例子)

    不用搭环境的10分钟AngularJS指令简易入门01(含例子) `#不用搭环境系列AngularJS教程01,前端新手也可以轻松入坑~阅读本文大概需要10分钟~` AngularJS的指令是一大特色 ...

  2. 【云开发】10分钟零基础学会做一个快递查询微信小程序,快速掌握微信小程序开发技能(轮播图、API请求)

    大家好,我叫小秃僧 这次分享的是10分钟零基础学会做一个快递查询微信小程序,快速掌握开发微信小程序技能. 这篇文章偏基础,特别适合还没有开发过微信小程序的童鞋,一些概念和逻辑我会讲细一点,尽可能用图说 ...

  3. 【MySQL】花10分钟阅读下MySQL数据库优化总结

    1.花10分钟阅读下MySQL数据库优化总结http://www.kuqin.com2.扩展阅读:数据库三范式http://www.cnblogs.com3.my.ini--->C:\Progr ...

  4. 对iOS后台模式最多10分钟运行时间的进一步理解

    在app进入后台时,系统初始默认是只有10s的处理时间,但如果10s不够,我们可以主动申请,网上流传最多的一个说法是10分钟. 但这种说法有个前提: 那就是iOS7之前,是这样 但从iOS7开始,我们 ...

  5. Apache Shiro系列三,概述 —— 10分钟入门

     一.介绍 看完这个10分钟入门之后,你就知道如何在你的应用程序中引入和使用Shiro.以后你再在自己的应用程序中使用Shiro,也应该可以在10分钟内搞定. 二.概述 关于Shiro的废话就不多说了 ...

  6. 破解YunFile下载间隔10分钟/下载等待30秒

    [破解10分钟间隔] 可以采用断网重连等方法重新获取IP地址,就不用再等十分钟了 [破解30秒等待] 收藏一个书签,书签地址如下 javascript:var downpage_link = docu ...

  7. JavaScript 10分钟入门

    JavaScript 10分钟入门 随着公司内部技术分享(JS进阶)投票的失利,先译一篇不错的JS入门博文,方便不太了解JS的童鞋快速学习和掌握这门神奇的语言. 以下为译文,原文地址:http://w ...

  8. emacs最简单入门,只要10分钟

    macs最简单入门,只要10分钟  windwiny @2013    无聊的时候又看到鼓吹emacs的文章,以前也有几次想尝试,结果都是玩不到10分钟就退出删除了. 这次硬着头皮,打开几篇文章都看完 ...

  9. UWP开发入门(十九)——10分钟学会在VS2015中使用Git

    写程序必然需要版本控制,哪怕是个人项目也是必须的.我们在开发UWP APP的时候,VS2015默认提供了对微软TFS和Git的支持.考虑到现在Git很火,作为微软系的程序员也不得不学一点防身,以免被开 ...

  10. U盘10分钟安装linux系统

    说来可能不信,10分钟包括创建U盘启动盘,用U盘启动,安装,不联网,不更新,不安装语言包,等装好系统再更新. Windows系统硬盘分区 如果你用的是Windows系统,现有的硬盘没有未分配的空间,需 ...

随机推荐

  1. HTTPS 基础知识(密钥、对称加密、非对称加密、数字签名、数字证书)

    HTTPS 概述 对称加密 非对称加密 非对称加密改良方案 非对称加密 + 对称加密 中间人攻击 数字证书 数字签名 HTTPS 工作原理 HTTPS 概述 HTTPS(全称:Hyper Text T ...

  2. 核磁共振成像学习笔记——从FID信号到K空间

    在理想磁场环境下(没有不存在场不均匀性),对于一个没有梯度场的方块. 此时,RF pulse的两路正交信号(相位差为90°)对此方块进行激发,然后收取信号,我们可以得到由此方块产生的FID信号. 设此 ...

  3. i春秋Musee de X

    打开提示我们如果要操作就需要登录 题目也没有给出tips提示 /tmp/memes/wosun 注册成功后提示我们我们的文件被储存在了.....可能这道题会用到一句话木马,毕竟他目录都给我们了 然后去 ...

  4. python进阶(28)import导入机制原理

    前言 在Python中,一个.py文件代表一个Module.在Module中可以是任何的符合Python文件格式的Python脚本.了解Module导入机制大有用处. 1. Module组成 一个.p ...

  5. c++题目:切香肠

    c++题目:切香肠 题目 题目描述 有 n 条香肠,每条香肠的长度相等.我们打算将这些香肠切开后全部分给 k 名客人,且要求每名客人获得一样多的香肠.请问最少需要切几刀?注意一刀只能切断一条香肠,每个 ...

  6. MyEclipse反编译插件安装于使用

    在MyEclipse开发中,使用反编译插件可以对jar包的源码进行随机的查看,节约了使用jd-gui查看时间. 百度云分享地址:链接:https://pan.baidu.com/s/1efNR6A 密 ...

  7. 使用pycharm or vscode来编写python代码?

    pycharm社区版可用于商业项目 pycharm社区版可用于商业项目,来源于官方的回答:Can I use Community Editions of JetBrains IDEs for deve ...

  8. .NET 6 中外部引用项目NU1105异常问题解决

    .NET 6 Project中,添加了其他解决方案的工程后,本地能编译通过,代码签入后,其他同事下载代码,编译报错: 错误 NU1105 找不到"E:\Teld\01Code\TTP_CTP ...

  9. 在生产中部署 ES2015+ 代码

    大多数 Web 开发人员都喜欢编写具有所有最新语言特性的 JavaScript--async/await.类.箭头函数等.然而,尽管事实上所有现代浏览器都可以运行 ES2015+ 代码并原生支持我刚才 ...

  10. [OpenCV实战]14 使用OpenCV实现单目标跟踪

    目录 1 背景 1.1 什么是目标跟踪 1.2 跟踪与检测 2 OpenCV的目标跟踪函数 2.1 函数调用 2.2 函数详解 2.3 综合评价 3 参考 在本教程中,我们将了解OpenCV 3中引入 ...