>[warning]订阅者&观察者定义
****
1. 思路:
(1): 新建订阅者Dep, 在属性劫持时, 往Dep中给每个属性绑定一个Watcher对象
(2): 当属性触发set方法时, 调用Dep里所有的watcher执行
![](https://box.kancloud.cn/e30e19743fbfc5f3df7e36c17feda65d_746x346.png)
2. 代码如下:
~~~
<script>
function myObjectDefinePropery(data, key, val) {
if (val && typeof val === 'object') {
observe(val);
return;
}
// 7. 实例化Dep类对象
let dep = new Dep();
Object.defineProperty(data, key, {
get: function() {
// 8. (Dep.target 指的是Watcher实例对象, 如果有, 则添加到订阅类中)
if (Dep.target){
// 9. 添加Watcher到订阅类中
dep.addSub(Dep.target);
}
return val;
},
set: function(newVal) {
// 判断set时值一样则退出
if (val === newVal){
return;
}
val = newVal;
// 10. 属性发生变化, 通知订阅者, 调用所有Wathcer执行对应方法
dep.notify();
}
});
}
function observe(data) {
Object.keys(data).forEach(function(key) {
myObjectDefinePropery(data, key, data[key]);
});
}
// 1. 新建订阅类, 属性改变, 触发方法, 收集这些方法
function Dep () {
// 用于放置每个属性变化时应该执行的方法体
this.watcherArr = [];
}
Dep.prototype = {
// 2. 用于添加属性改变对应执行的方法
addSub: function(watcher){
this.watcherArr.push(watcher);
},
// 3. 用于通知所有watcher, 让watcher观察者执行自己对应的方法体
notify: function(){
this.watcherArr.forEach(function(watcher){
// 4. 观察者执行对应代码, 可以跳转到Watcher类的update方法查看
watcher.update();
})
}
};
// 5. 定义观察类, 用于监视某些属性
function Watcher(model, exp) {
// 用在Object.definePropery的get方法中, 用于保存当前观察者对象
Dep.target = this;
// 给这个model绑定数据劫持
observe(model);
// 触发Object.definePropery的get方法
model[exp];
}
// 6. 属性被修改了, 触发update方法
Watcher.prototype = {
update: function() {
console.log("属性更新了");
}
};
// 11. 实例化观察类, 让它观察这个对象
let model = {
userName: ""
};
new Watcher(model, "userName");
// 12. 修改属性值, 看update方法里代码是否执行
model.userName = "ok";
</script>
~~~
[当前页源代码](https://github.com/lidongxuwork126com/ldx_vue/tree/master/%E4%BB%BFVue%E6%BA%90%E7%A0%81)
那么如何模拟Vue类呢, 看下个文章
- web前端
- CSS问题
- 布局
- 双飞翼布局_flex方式
- 双飞翼布局_margin方式
- 圣杯布局_flex方式
- 圣杯布局_margin方式
- 子元素居中问题
- 弹性布局
- 概念_
- 标准模式与混杂模式
- 各种FC
- line-height
- vertical-align
- CSS3新特性
- 效果
- div添加箭头
- CSS绘制三角形
- JavaScript
- 兼容
- 事件相关
- 原理
- Ajax原理
- 继承原理
- 原型链继承
- 组合继承
- 寄生组合继承
- 数据绑定
- 1单向数据绑定m到c到v
- 2伪双向数据绑定
- 3双向数据绑定
- socket.io
- 运行时
- this指向
- 0.1+0.2问题
- 对象/数组-深拷贝&浅拷贝
- 事件循环
- typeof
- instanceof
- 概念
- 闭包
- 回调函数
- Promise
- 原生对象
- Attribute和property区别
- 防抖函数
- 节流函数
- 语言类型
- Vue
- Vue优缺点
- 仿Vue源码
- 1数据绑定_Observe
- 2数据绑定_订阅者&观察者定义
- 3数据绑定_Vue类实现
- 4数据绑定_Vue访问data更改
- 5DOM编译_Compile_双大括号模板讲解
- 6DOM编译_v-model讲解
- 7DOM编译_v-on:事件绑定讲解
- 项目总结
- 使用Svg图标
- vueCli环境_真机测试
- vueCli集成环信SDK
- 父子组件双向绑定
- React
- React优缺点
- 我的组件库
- Vue的组件库
- 环信_聊天组件
- 面试题
- HTML_分类
- CSS_分类
- JavaScript_分类
- VueJS_分类
- ReactJS_分类
- AngularJS_分类
- 浏览器端
- 笔试题
- CSS
- 特殊布局
- JavaScript_
- 经典_宏任务_微任务
- 浏览器问题
- CORS
- web服务器
- Apache
- 开启跨域
- Nginx
- 常用命令
- 正向代理
- 反向代理
- 负载均衡
- mac安装Nginx
- 配置80端口
- 算法
- 冒泡排序
- 选择排序
- 合并对象_排序
- 杨辉三角
- 红黑树
- 计算机基础
- 网络相关
- OSI七层模型
- http协议
- http工作原理
- https协议
- GET和POST区别
- hosts文件
- php相关
- session机制
- Linux
- 阿里云服务器
- linux使用Mysql
- 安装mysql
- 导入.sql文件
- 远程连接mysql
- linux使用xampp
- 安装Xampp
- 配置web访问
- 域名绑定服务器
- linux搭建git服务器_apache下
- 代码管理
- 什么是git
- 命令行_使用git
- .gitignore文件讲解
- 软件
- VSCode的安装
- 理财
- 基金
- 摄影