-
设计模式
- 发布订阅-观察者
- 事件池 存放->按顺序执行
- 模块模式
- 闭包
- 工厂模式
- 无法区分关系
- 构造函数模式
- 混合模式(工厂 模块)
- 定制化
- 单例模式
- 有且只有一个
- 发布订阅-观察者
-
JQ的发布订阅
-
pond1=('.submit').click(function(){
pond1.add(func) //添加到事件池中的方法
$pond1.remove(func) //移除事件池中的方法
-
pond1=('.submit').click(function(){
-
DOM0和DOM2
- 语法上的区别
- dom0 box.onclick=function(){}
- dom2 box.addEventListener('click',function(a,b,c){}) //a:事件名 click b:方法名 c:true-捕获阶段调用 false-冒泡阶段调用
- 底层运行机制
- dom0 元素某个属性绑定方法值 有效绑定的方法只有一个(后面替换之前的)
- dom2 基于事件池机制完成,每增加一个绑定的方法,都会往事件池中存放一个 当事件触发会依次执行事件池中的事件(类似发布订阅模式 模拟事件池机制),可以给同一个元素的某个事件绑定多个不同的方法
- dom2中可以给一些特殊的事件类型绑定方法,这些类型dom0不支持绑定,DOMContentLoaded(dom结构加载完成 触发执行事件)、transitioned(css3 过渡动画执行完成触发)
-
(function(){}) dom2 可以绑定多个
- dom结构加载完成就执行
- window.onload dom0 只能绑定一个 => dom2 window.addEventListener('onload',function(){})
- dom树+所有相关资源均加载完毕才执行
-
(function(){}) dom2 可以绑定多个
- dom2的事件池机制
- 基于addEventListener/attachEvent(IE6-8)向事件池追加方法、新版本浏览器会根据元素和事件类型对新增方法做重复校验,但是IE6-8不可以
- removeEventListener/dttachEvent删除事件 不能移除匿名函数
- 当事件行为触发,会把事件池中的方法按照增加的顺序执行,但IE6-8中执行的顺序是不固定的(乱序执行) 捕获 目标 冒泡
- 语法上的区别
事件池--数组塌陷
let _subscribe=(function(){
//发布订阅类subscribe
class Sub(){
constructor(){
//创建事件池 存储后期需要执行的方法
this.$pond = [];
//向事件池中追加方法 func(需要追加的方法 判断是否是方法 去重)
add(func){
/*some
arr.some(item=>{
return item>1
})
找true
是否存在满足条件的 true 循环结束没有 false 不检测空数组,不改变原始数组)
every
找false
找到后终止并返回false 每个对象是否满足条件
find
arr.find(item=>{
return item.flag
})
返回找到的满足条件的第一项,停止循环 不改变原始数组 循环完毕没找到返回undefined,不检测空数组)
includes(arr.includes(1) true/false) filter(筛选 返回新数组,不改变旧的)
map(映射 返回新数组,不改变旧的)
*/
let flag = this.$pond.some(item=>{
return item===func
})
if(!flag){
this.$pond.push(func)
}
// !flag ? this.$pond.push(func) : null;
}
//移除事件池中的方法
remove(func){
//splice filter 浅拷贝 堆内存 引用类型
let $pond=this.$pond;
for(let i=0;i<$pond.length;i++){
let item=$pond[i];
if(item===func){
//移除 不改变方法顺序(改变顺序 删除当前项 将最后一项添加到当前位置,然后删除最后一位--性能优化) splice(i,n)
$pond.splice(i,1); //导致数组塌陷-->假移除 赋值为null
$pond[i]=null//解决数组塌陷 伪删除 保证索引
break;
//终止循环 区别return(终止当次循环)
}
}
}
//通知事件池中的方法依次执行
fire(...args){ //...扩展运算符 args 传进来所有参数的数组(不确定参数有几个)
let $pond=this.$pond
for(let i=0;i<$pond.length;i++){
let item=$pond[i]
if(typeOf item!=='function'){
$pond.splice(i,1); //再进行删除
i--;
continue;//跳过循环体中剩下的语句
}
item.call(this,...args) //this指向当前实例 单独传参 在三个或以上参数时 call的性能略优与apply --apply 数组传参
}
}
}
}
return function subscribe(){ //暴露外界使用 做普通函数
return new Sub()
}
})();//闭包 防止污染 冲突
let s1 = _subscribe(); //创建实例 事件池
document.querySelector('.submit').onclick=function(event){
let evt=event?event:window.event; //cancelBubble 取消事件冒泡 stopPropagation 取消事件冒泡和下沉
s1.fire(evt) //执行事件池中的方法执行
}
s1.add(func)
s1.remove(func)
- B站学习偶然看到的 up主-光影哔哩 珠峰培训课程
- 之前的知识忘却大部分了 有错误的地方欢迎大佬联系我改正
- 好久不学习了~ 咸鱼太久了啊