一、发布订阅
1.目的
解耦,让各个组件之间没有紧密的联系,如果修改了什么属性,就尽可能更新这些属性对应的页面DOM
2.步骤描述
1)需要有中间的全局容器=》一个数组存放所有的订阅(watcher),发布的时候在这个里面取可以被触发的东西(函数、对称)
2)可以根据需求来订阅东西
3)等等,可以做一些其他的事情
4)当有某些需求就去查看全局容器,取出相应的东西来用
2)可以根据需求来订阅东西
3)等等,可以做一些其他的事情
4)当有某些需求就去查看全局容器,取出相应的东西来用
3.代码描述
1.eventObj={}描述存储的容器
2.event.on('事件名',响应函数)
1)订阅事件 可以连续订阅
2)可以移除:event.off()
移除所有
移除某一个类型的事件
移除某一类事件的某一个处理函数
3.处理别的代码
4.event.emit('事件名',参数),先前注册的时间处理函数会依次调用
2.event.on('事件名',响应函数)
1)订阅事件 可以连续订阅
2)可以移除:event.off()
移除所有
移除某一个类型的事件
移除某一类事件的某一个处理函数
3.处理别的代码
4.event.emit('事件名',参数),先前注册的时间处理函数会依次调用
二、Vue中的更新规则及模型
1.更新规则
在Vue中整个更新是按照**组件**为单位进行判断的,以节点为单位进行更新:
1)如果没有自定义组件,在比较算法的时候会将全部模板对应的虚拟DOM进行比较
2)如果有自定义组件,在比较算法的时候会判断更新的是哪一些组件中的属性,只会判断更新数据的组件,其他组件不会更新
2.模型
3.为什么设计为多个watcher?
每个组件都会对应一个watcher,初始渲染的时候会将所有的watcher都加入全局容器中,而往往开发中只有一部分组件的数据会发生变化,diff算法也只会对这部分组件重新生成抽象语法树,也只会访问这部分watcher,将这部分watcher再次被添加入全局的watcher中,其他的就不在了,因此页面更新的时候只会更新这一部分而不是全部更新,会提升一些渲染效率
三、实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> var event = (function () { eventObj = {}; return { /** 注册事件,可以连续注册并且能注册多个事件*/ on: function (type, handler) { (eventObj[type] || (eventObj[type] = [])).push(handler); }, /** 移除事件 * 如果没有参数就移除全部事件 * 如果有一个参数,就移除这个事件名下的所有事件 * 如果有两个参数,就移除这个事件中的这个具体的处理函数*/ off: function (type, handler) { if (arguments.length === 0) { eventObj = {}; } else if (arguments.length === 1) { eventObj[type] = []; } else if (arguments.length === 2) { if (!eventObj[type]) return;/** 如果没有这个事件名,则直接返回*/ for (let i = eventObj[type].length - 1; i >= 0; i--) { if (eventObj[type][i] == handler) { eventObj[type].splice(i, 1); } } } }, /** 发射事件(触发事件) * 包装参数,传递给时间处理函数 */ emit: function (type) { if (!eventObj[type]) return; let args = Array.prototype.slice.call(arguments, 1); for (let i = 0; i < eventObj[type].length - 1; i++) { eventObj[type][i].call(null, args); } } } }) </script> </body> </html>