面试中常问到的发布订阅和瀑布流分析

106 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情 >>>

⛹🏿‍♂发布订阅(pubsub)

发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都将得到通知

注意:一对多(一指的是发布,多指的是订阅),是先订阅再发布

👋�作用:

(1)支持简单的广播通信,当对象状态发生改变时,会自动通知已经订阅过的对象

(2)可以应用在异步编程中,替代回调函数,可以订阅ajax之后的事件,只需要订阅自己需要的部分

(3)对象之间的松耦合

(4)跨组件之间的传值

👋🏿如何实现发布--订阅模式?

1.首先要想好谁是发布者?

2.然后给发布者添加一个缓存列表,用于存放回调函数来通知订阅者

3.最后就是发布消息,发布者遍历这个缓存列表,依次触发里面存放的订阅者回调函数

👋🏿定义一个发布者

var shoeObj ={}

👋🏿有一个列表用来存放函数

shoeObj.list=[]

👋🏿增加订阅者

shoeObj.listen =function(key,fn){

​		if(!this.list[key]){

​			this.list[key]=[]

​		}

​		this.list[key].push(fn)

}

👋🏿发布消息

shoeObj.trigger =function(){

//取出这个key

var key =Array.prototype.shift.call(arguments)

var  fns = this.list[key]



//遍历这个数组 然后执行这个函数

if(!fns || fns.length ==0){

​	return

}

​	for(var i =0,fn; fn = fns[i++]){

​			fn.apply(this,arguments)

}

}

👋🏿订阅

shoeObj.listen('red',function(size){

​	console.log('小红订阅的尺码是${size}');

})



shoeObj.listen('black',function(size){

​	console.log('小明订阅的尺码是${size}');

})

👋🏿移除订阅

if(!fns){

return false;

}

if(!fn){

fns && (fns.length = 0);

}else{

​	for(var i =fns.length -1 ;i>=0;i--){

​	var _fn=fns[i];

​	if(_fn === fn){

​	//移除这个数组

​		fns.splice(i,1)

}

}

}


👋🏿发布

shoeObj.trigger('red''37')

shoeObj.tigger('black''42')

⛹🏿‍♂瀑布流的实现

思路:首先确定视口宽度 再确定第一行的每个块的宽度 通过两者来知道第一行有多少个块

其次 将第一行的每个块的高度push到arr数组中存放 获取第一行块的距离左边的距离

最后 将第二行的块放在第一行的高度最短的块下面 获取第一行高度最短的块的offsetLeft当成自己的offsetLeft

剩下的块以此类推 依次找上一行高度最短的块的下面补齐(注:第二行的块的高度会加到原来第一行最短块的高度上)

function waterFall(){

//视口的宽度

var pageWidth = getClient().width		//视口的宽度

var itemWidth = items[0].offsetWidth   //每个块的宽度

// column = pageWidth % itemWidth   

var columns =parseInt( pageWidth/(itemWidth + gap) )

//gap指的是columns之间的间隔



var arr=[]  //里面放的是高度的值

for(var i=0;i<items.length;i++){

if(i<columns){

//确定第一行

items[i].style.top=0

items[i].style.left=(itemWidth+gap)*i+px

arr.push(items[i].offsetHeight)

}else{

//其他行

var minHeight =arr[0]

var index =0

for(var j=0;j<arr.length;i++){

if(minHeight>arr[j]){

minHeight=arr[j]

index=j

}

}



//设置下一行第一个盒子的位置 第一张图片的位置

//top

items[i].style.top=arr[index]+gap+'px'

//left

items[i].style.top=items[index].offsetLeft+'px'



//改变最小列的高度

arr[index] =arr[index] =items[i].offsteHeight + gap

}

}

}

3977704424-614a1220797dd_fix732.png