1.demo1.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<!--
1.js 内置观察者模式 对象的属性(描述对象)
--> <script type="text/javascript">
var obj = {name:"max",age:30};
console.log(obj.name); // name是一个属性
// 描述对象(针对对象的属性)
// Object.defineProperty 是 Object 的静态方法
Object.defineProperty(obj,"name",{ // 参数:观察对象 属性名 描述对象
get:function(){ // 获取 阻截访问属性 钩子函数
// console.log("max is max");
// return "yangyang"
return this.value;
}, // 将钩子函数的返回值作为 访问属相的返回值(集对象的属性值)
set:function(val){ // 设置
console.log(val); // 属性值
console.log("设置属性值"); //桥接模式 扩展对象属性的方式
this.value = val;
}
}) // 内置的观察者模式 obj.name = "yangyang"; // 调用set
console.log(obj.name); // 调用get console.log(obj.value); // yangyang console.log(obj); // vuejs
</script>
</body>
</html>

demo2.html :

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<input v-model="message" />
<p v-model="message"></p></div>
</div> <script>
// app 当前的模板
var model = { // 作为模型数据
// 设置message属性
message:"xxxxxxxxxxxxx"
} // 通过当前查找 通过属性查找子元素
var elments = app.querySelectorAll("[v-model=message]"); // 返回一个数组的集合
console.log(elments.length);
// 遍历
for(var i=0;i<elments.length;i++){
elments[i].onkeyup = function() {
// 获取 this.value
// console.log(this.value);
// 将值给model.message
model[this.getAttribute("v-model")] = this.value;
console.log(model.message);
}
} // Object.defineProperty 是 Object 的静态方法
Object.defineProperty(model,"message",{ // 参数:观察对象 属性名 描述对象
get:function(){ // 获取 阻截访问属性 钩子函数
// console.log("max is max");
// return "yangyang"
return this.value;
}, // 将钩子函数的返回值作为 访问属相的返回值(集对象的属性值)
set:function(val){ // 设置
var models = app.querySelectorAll("[v-model=message]");
for(var i=0;i<models.length;i++){
models[i].value = val;
models[i].innerHTML = val;
}
this.value = val;
}
}); // 内置的观察者模式 // 数据双向绑定
// 模板引擎
// 响应式原理
// observer模块
// 数据追踪
// 路由
// 状态管理
// 虚拟DOM
// 自定义指令
// 服务端渲染
</script>
</body>
</html>

demo3.html :

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<input v-model="message" />
<p v-model="message"></p>
</div> <script src="js/vue-1.1.0.js"></script>
<script>
var model = {
message:"",
data:model
} var app = new Vue({
el:"#app", // 绑定模块DOM结构
data:{
message:"",
text:""
}// 配置
}) //
</script>
</body>
</html>

模仿vue

vue-1.1.0.js :

// 自运行函数
(function(root,factory){ // 创建作用域 命名空间
// 调用工厂函数
root.Vue = factory(); // 返回vue 在window下扩展了vue的属性
})(this,function(){
// 默认配置
var _DEFALUT_ = { //用户没有传值,默认优先,用户传值,配置覆盖
el:"body",
data:{}
}
var Vue = function(option){ // 构造函数
// console.log(this.el); // body 扩展
this.extend(this,_DEFALUT_,option); // 合并 this实例对象
this.el = document.querySelectorAll(this.el); // 转换成element对象
// console.log(this.el);
// console.log(this.data); // 增加观察观察者模式
this.observer(); // 通过当前查找 通过属性查找子元素
var elments = this.el.querySelectorAll("[v-model]"); // 返回一个数组的集合
// 遍历
for(var i=0;i<elments.length;i++){
elments[i].onkeyup = function() {
// 获取 this.value
// console.log(this.value);
// 将值给model.message
model[this.getAttribute("v-model")] = this.value;
console.log(model.message);
}
}
}
// 创造extend,用于扩展
Vue.prototype = {
extend:function(){ // 扩展
// 从第二个对象开始循环
for(var i=1;i<arguments.length;i++){ // 2 arguments[1]
for(var name in arguments[i]){ // for in 循环当前对象的可枚举属性,例如name
// console.log(name);
// 开始扩展
this[name] = arguments[i][name]
}
}
},
observer:function(){
var el = this.el;
// let 定义块作用域
for(let key in this.data){
Object.defineProperty(this.data,key,{ // 参数:观察对象 属性名 描述对象
}get:function(){ // 获取 阻截访问属性 钩子函数
return this.value;
}, // 将钩子函数的返回值作为 访问属相的返回值(集对象的属性值)
set:function(val){ // 设置
console.log(key);
var models = el.querySelectorAll("[v-model]=" + key + "]");
for(var i=0;i<models.length;i++){
models[i].value = val
models[i].innerHTML = val
}
this.value = val;
}
}) // 内置的观察者模式
}
}
} return Vue;
}); // this 代表window对象 function 工厂函数 this也可以理解为根作用域 // console.log(Vue); // 拿到工厂函数中定义的构造函数 // 通过new方法,创建vue的实例

.

MVVM模式源码分析手写实现的更多相关文章

  1. 面试必会之ArrayList源码分析&手写ArrayList

    简介 ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,非常适合用于对元素进行查找,效率非常高. 线程 ...

  2. 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)

    作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...

  3. Spring源码分析 手写简单IOC容器

    Spring的两大特性就是IOC和AOP. IOC Container,控制反转容器,通过读取配置文件或注解,将对象封装成Bean存入IOC容器待用,程序需要时再从容器中取,实现控制权由程序员向程序的 ...

  4. 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理

    1. AQS共享模式 前面已经说过了AQS的原理及独享模式的源码分析,今天就来学习共享模式下的AQS的几个接口的源码. 首先还是从顶级接口acquireShared()方法入手: public fin ...

  5. springMVC源码分析--HttpMessageConverter写write操作(三)

    上一篇博客springMVC源码分析--HttpMessageConverter参数read操作中我们已经简单介绍了参数值转换的read操作,接下来我们介绍一下返回值的处理操作.同样返回值的操作操作也 ...

  6. 【一起学源码-微服务】Nexflix Eureka 源码十二:EurekaServer集群模式源码分析

    前言 前情回顾 上一讲看了Eureka 注册中心的自我保护机制,以及里面提到的bug问题. 哈哈 转眼间都2020年了,这个系列的文章从12.17 一直写到现在,也是不容易哈,每天持续不断学习,输出博 ...

  7. Android Doze模式源码分析

    科技的仿生学无处不在,给予我们启发.为了延长电池是使用寿命,google从蛇的冬眠中得到体会,那就是在某种情况下也让手机进入类冬眠的情况,从而引入了今天的主题,Doze模式,Doze中文是打盹儿,打盹 ...

  8. Spring源码 20 手写模拟源码

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  9. 《四 spring源码》手写springmvc

    手写SpringMVC思路 1.web.xml加载  为了读取web.xml中的配置,我们用到ServletConfig这个类,它代表当前Servlet在web.xml中的配置信息.通过web.xml ...

随机推荐

  1. C#操作XML序列化与反序列化

    public class XmlSerializerHelper { /// <summary> /// 从XML文件中反序列化读取对象 /// </summary> /// ...

  2. react dva routerRedux 备忘

    首先你需要import { Link, routerRedux } from 'dva/router'; 在方法里跳转用 function applyJobHandler(){ dispatch(ro ...

  3. 计算器的改良(纯字符串)o1

    原题传送门 这题比较水,就是细节..多了点. 首先字符串要处理好(废话..) 基础不行的话要多去看看书.. 然后捏,这题主要就是几个判断: 当我们读字符,如果读到运算符号,那么就要停下来,把之前的常数 ...

  4. java基础练习 14

    import java.util.Scanner; public class Fourtheen { /*打印出所有的"水仙花数",所谓"水仙花数"是指一个三位 ...

  5. linux题目整理(一)

    1.Linux如何挂载windows下的共享目录? mount.cifs /IP地址/server/ /mnt/server -O user=administrator password=yourpa ...

  6. 修改SVN路径

    由于服务器IP更换,所以SVN的路径也就更换了. 更换SVN路径的做法是: 选中SVN checkout的文件夹,右键选择TortoiseSVN的relocate.注意要选择checkout的根目录, ...

  7. 元素类型 “meta” 必须由匹配的结束标记 “” 终止

    报错 org.xml.sax.SAXParseException: 元素类型 “meta” 必须由匹配的结束标记 “” 终止 系统自动创建 <meta charset="UTF-8&q ...

  8. 洛谷 P1060 开心的金明【DP/01背包】

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就 ...

  9. UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)

    [题目链接] UVA11990 [题目大意] 给出一个数列,每次删去一个数,求一个数删去之前整个数列的逆序对数. [题解] 一开始可以用树状数组统计出现的逆序对数量 对于每个删去的数,我们可以用线段树 ...

  10. [BZOJ1194][HNOI2006][强连通分量Tarjan+dfs]潘多拉的盒子

    [BZOJ1194][HNOI2006]潘多拉的盒子 Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语 ...