一、发布订阅
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> 
京公网安备 11010502036488号