10分钟搞定简易MVVM
实现一个简易的 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的更多相关文章
- 【转】让你10分钟搞定Mac--最简单快速的虚拟安装
文章出处:让你10分钟搞定Mac--最简单快速的虚拟安装http://bbs.itheima.com/thread-106643-1-1.html (出处: 黑马程序员训练营论坛) 首先说明一下. 第 ...
- OpenCV3.4.1快速集成到Android studio中,10分钟搞定
OpenCV3.4.1快速集成到Android studio中,10分钟搞定 转载 https://blog.csdn.net/yu540135101/article/details/8259 ...
- 10分钟搞定让你困惑的 Jenkins 环境变量
前言 Jenkins, DevOps 技术栈的核心之一,CI/CD 离不开编写 Pipeline 脚本,上手 Jenkins ,简单查一下文档,你就应该不会被 agent,stages,step 这类 ...
- Python基于VS2013 开发环境搭建 Hello World 10分钟搞定
1.先下载Python 安装 Next ->安装完成 2.以前安装过VS2013 打开VS2013 文件->新建项目 (此时如果没有Python Application,请点击里面的安装插 ...
- 10分钟搞定 Java 并发队列好吗?好的
| 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it ...
- 【前端知识体系-JS相关】10分钟搞定JavaScript正则表达式高频考点
1.正则表达式基础 1.1 创建正则表达式 1.1.1 使用一个正则表达式字面量 const regex = /^[a-zA-Z]+[0-9]*\W?_$/gi; 1.1.2 调用RegExp对象的构 ...
- 10分钟搞定nginx实现负载均衡
10.1 负载均衡的概念 对用户请求的数据进行调度的作用 对用户访问的请求网站可以进行压力的分担 10.2 常见的代理方式 10.2.1 正向代理 10.2.2 反向代理 10.3 负载均衡的部署环节 ...
- 10分钟搞定react-router
1.路由的安装: $ npm install -S react-router 2.引入路由文件 import {Router, Route, browserHistory} from 'react-r ...
- 10分钟搞定webpack打包
入门前端这个职位近三年的时间了,但是脑子里的东西不多也不少,今天就从脑袋里把新版本的webpack打包过程拔出来给大家鲁一遍,就算帮助那些小白了,废话不多说,开始鲁起来,大家跟着我一起撸... 首先, ...
- JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查)
前言:关于Vue框架,好几个月之前就听说过,了解一项新技术之后,总是处于观望状态,一直在犹豫要不要系统学习下.正好最近有点空,就去官网了解了下,看上去还不错的一个组件,就抽空研究了下.最近园子里vue ...
随机推荐
- scp工具上传下载
1.从本地复制到远程 scp local_file remote_username@remote_ip:remote_folder 或者 scp local_file remote_username@ ...
- Pairs of Numbers 辗转相除
# 42. Pairs of Numbershttps://blog.csdn.net/qq_43521140/article/details/107853492- 出题人:OJ- 标签:[" ...
- adb版本不同导致一个服务杀死另一个服务
前言 由于我用安装模拟器进行调试app,需要连接到固定端口, 而开发测试的时候用到eclipse中调用sdk中包含一个版本的adb, 另外Android killer中也包含一个版本的adb, 另外我 ...
- Datawhale组队学习_Task01:概览西瓜书+南瓜书第1、2章
第一章 绪论 1.1引言 打开书,五分钟后,合上书:嗯!学会了!如何判断一个好瓜 1.2基本术语 分类:对离散值进行预测的学习任务,是有监督学习的代表 回归:对连续值进行预测的学习任务,是有监督学习的 ...
- js- day03- 将数据变成柱形图
柱形图的渲染 * { margin: 0; padding: 0; } .box { display: fle ...
- bug处理记录:Error running 'WorkflowApplication': Command line is too long. Shorten command line for WorkflowApplication or also for Spring Boot default configuration?
1.报错信息 Error running 'WorkflowApplication': Command line is too long. Shorten command line for Workf ...
- java中的杨辉三角
本文主要介绍如何打印杨辉三角(直角三角形),如下图所示: 规律如下: 第一行全为1,对角线元素全为1,设i表示行标,j表示列标. arr[i][0] = 1; arr[i][i] = 1; 当i &g ...
- Pytorch 基本操作
Pytorch 基础操作 主要是在读深度学习入门之PyTorch这本书记的笔记.强烈推荐这本书 1. 常用类numpy操作 torch.Tensor(numpy_tensor) torch.from_ ...
- ArcObjects SDK开发 024开发的技术和技巧
1.基本技术 开发方面.会使用C#开发语言和Visual Studio开发工具.会使用WinForm或者WPF开发. 理论知识方面.了解GIS的相关概念,例如矢量数据,栅格数据,空间参考.比例尺等概念 ...
- APICloud平台使用融云模块实现音视频通话实践经验总结分享
需求概要:实现视频拨打.接听.挂断.视频界面大小窗口.点击小窗口实现大小窗口互换. 实现思路:一方拨打后,另一方要能收到相应事件,然后接听.接通后,渲染对方视频画面.那么己方视频画面什么时候渲染呢?对 ...