vue 缩水版 双向绑定
function Observer(obj, key, value){
var dep = new Dep();
if (Object.prototype.toString.call(value) == '[object Object]') {
Object.keys(value).forEach(function(key){
new Observer(value,key,value[key])
})
};
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function(){
if (Dep.target) {
dep.addSub(Dep.target);
};
return value;
},
set: function(newVal){
value = newVal;
dep.notify();
}
})
}
function Watcher(fn){
this.update = function(){
Dep.target = this;
fn();
Dep.target = null;
}
this.update();
}
function Dep(){
this.subs = [];
this.addSub = function (watcher) {
this.subs.push(watcher);
}
this.notify = function(){
this.subs.forEach(function(watcher){
watcher.update();
});
}
}
<div id="test"></div>
var obj = {
a: 1,
b: 2,
c: 3
}
Object.keys(obj).forEach(function(key){
new Observer(obj, key, obj[key])
});
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.a;
})
function Observer(obj, key, value){
//这里会生成4个dep对象; 分别对应的是属性 a , b, b.b1, c 的派系; 如果一个数据total的计算需要 a的值, 就在第一个dep中添加第三个watcher,
// 这样obj.a改变, 就会触发第三个watcher的回调, 来更新页面; obj.c的改变也会触发第三个watcher
var dep = new Dep();
if (Object.prototype.toString.call(value) == '[object Object]') {
Object.keys(value).forEach(function(key){
new Observer(value,key,value[key])
})
};
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function(){
if (Dep.target) {
dep.addSub(Dep.target);
};
return value;
},
set: function(newVal){
value = newVal;
dep.notify();
}
})
}
function Watcher(fn){
this.update = function(){
Dep.target = this;
this.callback();
Dep.target = null;
}
this.callback = fn;
this.update();
}
function Dep(){
this.subs = [];
this.addSub = function (watcher) {
this.subs.push(watcher);
}
this.notify = function(){
this.subs.forEach(function(watcher){
watcher.update();
});
}
}
var obj = {
a: 1,
b: {
b1: 33
},
c: 3
}
Object.keys(obj).forEach(function(key){
new Observer(obj, key, obj[key])
});
new Watcher(function(){
document.querySelector("#app").innerHTML = obj.a; //执行到这里, 有一个取值的操作, 会进入obj对象a属性的get方法
})
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.b.b1; //执行到这里, 也有取值的操作, 先取obj.b, 第一次进入b属性的get方法, 第二次进入b1的get方法
})
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.a + obj.c;
})
obj.a = 100; //进入ojb属性a的set方法
function Observer(obj, key, value){
//这里注册被订阅主体
var dep = new Dep();
if (Object.prototype.toString.call(value) == '[object Object]') {
Object.keys(value).forEach(function(key){
new Observer(value,key,value[key])
})
};
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function(){
if (Dep.target) {
dep.addSub(Dep.target);
};
return value;
},
set: function(newVal){
value = newVal;
dep.notify();
}
})
}
//Watcher, 其实就是订阅者, 这个函数是面向页面更新操作
function Watcher(fn){
this.update = function(firstDef){
this.callback();
}
this.callback = fn; //这里其实可以放入多个回调,一个watcher存放多个回调函数,
Dep.target = this;
this.callback(); //先执行一次,来触发obj.a 的get方法; 从而a的dep收集这个watcher, 并且给页面赋值;
Dep.target = null;
}
//这是发布订阅系统, 这个东西是面向对象obj的属性的。 每个属性再defineProperty的时候, 新增了一个dep, 它可以被一个页面多个地方更新依赖,使用;
function Dep(){
this.subs = [];
this.addSub = function (watcher) {
this.subs.push(watcher);
}
this.notify = function(){
this.subs.forEach(function(watcher){
watcher.update();
});
}
}
var obj = {
a: 1,
b: {
b1: 33
},
c: 3
}
Object.keys(obj).forEach(function(key){
new Observer(obj, key, obj[key])
});
new Watcher(function(){
//这里就是收集依赖的过程, obj.a会触发get方法, 这样a属性的dep就添加了这个函数为回调的watcher, 作为依赖一
document.querySelector("#app").innerHTML = obj.a;
})
new Watcher(function(){
//这里再次收集依赖, obj.a会触发get方法, 这样a属性的dep就 又添加 添加了一个函数watcher, 作为依赖二, 这样
// a属性的dep就有了两个依赖, 在设置a属性的时候, 就会触发这两个依赖函数.
document.querySelector("#test").innerHTML = obj.a;
})
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.a + obj.c;
})
obj.a = 3;
function Observer(obj, key, value){
//这里注册被订阅主体
var dep = new Dep();
if (Object.prototype.toString.call(value) == '[object Object]') {
Object.keys(value).forEach(function(key){
new Observer(value,key,value[key])
})
};
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function(){
if (Dep.target) {
dep.addSub(Dep.target);
};
return value;
},
set: function(newVal){
value = newVal;
dep.notify();
}
})
}
//Watcher, 其实就是订阅者, 这个函数是面向页面更新操作
function Watcher(fn){
this.update = function(firstDef){
this.callback();
}
this.callback = fn; //这里其实可以放入多个回调,一个watcher存放多个回调函数,
Dep.target = this;
this.callback(); //先执行一次,来触发obj.a 的get方法; 从而a的dep收集这个watcher, 并且给页面赋值;
Dep.target = null;
}
//这是发布订阅系统, 这个东西是面向对象obj的属性的。 每个属性再defineProperty的时候, 新增了一个dep, 它可以被一个页面多个地方更新依赖,使用;
function Dep(){
this.subs = [];
this.addSub = function (watcher) {
this.subs.push(watcher);
}
this.notify = function(){
this.subs.forEach(function(watcher){
watcher.update();
});
}
}
var obj = {
a: 1,
b: {
b1: 33
},
c: 3
}
Object.keys(obj).forEach(function(key){
new Observer(obj, key, obj[key])
});
new Watcher(function(){
document.querySelector("#app").innerHTML = obj.a;
})
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.b.b1;
})
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.a + obj.c;
})
obj.a = 3;
function Observer(obj, key, value){
var dep = new Dep();
if (Object.prototype.toString.call(value) == '[object Object]') {
Object.keys(value).forEach(function(key){
new Observer(value,key,value[key])
})
};
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function(){
if (Dep.target) {
dep.addSub(Dep.target);
};
return value;
},
set: function(newVal){
value = newVal;
dep.notify();
}
})
}
function Watcher(fn){
this.update = function(firstDef){
if(firstDef){
Dep.target = this;
}
this.callback();
Dep.target = null;
}
this.callback = fn;
this.update(true);
}
function Dep(){
this.subs = [];
this.addSub = function (watcher) {
this.subs.push(watcher);
}
this.notify = function(){
this.subs.forEach(function(watcher){
watcher.update();
});
}
}
var obj = {
a: 1,
b: {
b1: 33
},
c: 3
}
Object.keys(obj).forEach(function(key){
new Observer(obj, key, obj[key])
});
new Watcher(function(){
document.querySelector("#app").innerHTML = obj.a;
})
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.b.b1;
})
new Watcher(function(){
document.querySelector("#test").innerHTML = obj.a + obj.c;
})
obj.a = 3;
vue 缩水版 双向绑定的更多相关文章
- Vue框架之双向绑定事件
Vue框架之双向绑定事件 首先介绍下Vue框架的语法 vue通过 {{temp}} 来渲染变量 {{count+100}} # 求和 v-text # 为标签插入text文本 v-html # 为标签 ...
- 用ES6的class模仿Vue写一个双向绑定
原文地址:用ES6的class模仿Vue写一个双向绑定 点击在线尝试一下 最终效果如下: 构造器(constructor) 构造一个TinyVue对象,包含基本的el,data,methods cla ...
- 组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双向绑定数据
组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双 ...
- Vue的数据双向绑定和Object.defineProperty()
Vue是前端三大框架之一,也被很多人指责抄袭,说他的两个核心功能,一个数据双向绑定,一个组件化分别抄袭angular的数据双向绑定和react的组件化思想,咱们今天就不谈这种大是大非,当然我也没到达那 ...
- 原生js实现 vue的数据双向绑定
原生js实现一个简单的vue的数据双向绑定 vue是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时 ...
- 对象的属性类型 和 VUE的数据双向绑定原理
如[[Configurable]] 被两对儿中括号 括起来的表示 不可直接访问他们 修改属性类型:使用Object.defineProperty() //IE9+ 和标准浏览器 支持 查看属性的 ...
- vue中数据双向绑定注意点
最近一个vue和element的项目中遇到了一个问题: 动态生成的对象进行双向绑定是失败 直接贴代码: <el-form :model="addClass" :rules=& ...
- vue中数据双向绑定的实现原理
vue中最常见的属v-model这个数据双向绑定了,很好奇它是如何实现的呢?尝试着用原生的JS去实现一下. 首先大致学习了解下Object.defineProperty()这个东东吧! * Objec ...
- 剖析Vue原理&实现双向绑定MVVM
转自:http://www.w3cmark.com/2016/496.html 本文能帮你做什么? 1.了解vue的双向数据绑定原理以及核心代码模块 2.缓解好奇心的同时了解如何实现双向绑定 为了便于 ...
随机推荐
- chmod 没有x权限怎么办
解决方法1: # /lib64/ld-linux-x86-64.so.2 /bin/chmod 755 /bin/chmod //linux动态命令库 解决方法2:方法2提到的两种方法形 ...
- 2.7 UML状态图
问题的引出 顺序图是对对象的动态行为进行建模,有多个对象的参与.协作 问题: 当需要考察单个实体的动态行为时, 用UML如何来建模呢? 什么是单个实体:一个软件系统?一个子系统?一个模块.一个构件? ...
- Ugly Number leetcode java
问题描述: Write a program to check whether a given number is an ugly number. Ugly numbers are positive n ...
- pytorch初步学习(一):数据读取
最近从tensorflow转向pytorch,感受到了动态调试的方便,也感受到了一些地方的不同. 所有实验都是基于uint16类型的单通道灰度图片. 一开始尝试用opencv中的cv.imread读取 ...
- (二)使用数组长度实现ADT bag(java)
目录 1.使用固定大小的数组实现ADT bag 包 1.1 一组核心方法 1.2 实现核心方法 1.3 让实现安全 1.4 测试核心方法 1.5 实现更多的方法 1.6 删除项的方法 1.7 测试 ...
- ccf碰撞的小球
之前的代码有人运行不成功,自己又看了一下是输入变量顺序输入错了,现在是正确答案- #include<stdio.h> struct node{ int x; int dir; }; int ...
- Oracle 11.2.0.4.0 Dataguard部署和日常维护(1)-数据库安装篇
本次测试环境 系统版本 CentOS release 6.8 主机名 ec2t-userdata-01 ec2t-userdata-01 IP地址 10.189.102.118 10.189.100. ...
- linux文件软链接、硬链接
在linux ext2文件系统中,一个文件的属性存放在inode中,而数据存放在block中.每个文件占用一个inode,inode中记录了文件的权限和block地址,通过inode可以定位到bloc ...
- WeRun is mini-app
WeRun is a mini-app within WeChat that allows users to monitor their daily step count. One of its mo ...
- frameset的固定放置模式,不能放入<form runat="server">中
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="admin_default.as ...