分析一个轮播图实例
HTML 分析
<div id="my-slider" class="slider-list">
<ul>
<li class="slider-list__item--selected">
<img src="https://p5.ssl.qhimg.com/t0119c74624763dd070.png"/>
</li>
<li class="slider-list__item">
<img src="https://p4.ssl.qhimg.com/t01adbe3351db853eb3.jpg"/>
</li>
<li class="slider-list__item">
<img src="https://p2.ssl.qhimg.com/t01645cd5ba0c3b60cb.jpg"/>
</li>
<li class="slider-list__item">
<img src="https://p4.ssl.qhimg.com/t01331ac159b58f5478.jpg"/>
</li>
</ul>
<a class="slide-list__next"></a>
<a class="slide-list__previous"></a>
<div class="slide-list__control">
<span class="slide-list__control-buttons--selected"></span>
<span class="slide-list__control-buttons"></span>
<span class="slide-list__control-buttons"></span>
<span class="slide-list__control-buttons"></span>
</div>
</div>
div#my-slider 作为轮播图容器,包括了一个轮播图 ul 和控制流( a.slide-list__next, a.slide-list__previous, div.slide-list__control )。
内容是静态的所以说我们增删都需要直接修改 HTML 文件结构,修改组件也是需要直接修改 HTML ,这样会导致维护起来比较困难。
CSS 分析
这里有一个有意思的地方
.slide-list__control{
position: relative;
display: table;
background-color: rgba(255, 255, 255, 0.5);
padding: 5px;
border-radius: 12px;
bottom: 30px;
margin: auto;
}
这里边的 bottom 是相对上一个元素 ul 定位的,如果改成 top 的话,就会相对下一个元素定位(这里没有所以会沉下去)。
在处理前后翻页的时候,没有在 a 标签内直接写<和 >,而是在后边加了一个伪元素:after,可能是因为不能选中的关系,不过也是挺巧妙的,第一次遇到。
.slide-list__previous:after {
content: '<';
}
.slide-list__next:after {
content: '>';
}
JS 分析
JS这部分分析比较头疼,第一次遇到,不过大受震惊。
分析 Slider
class Slider{
...
registerPlugins(...plugins){
plugins.forEach(plugin => plugin(this));
}
...
}
注册插件这里看了半天,遍历 plugins ,对于每个子项 plugin ,把它当做方法并调用,参数 this 指的是 Slider 本身。
举例子:
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
等价于
pluginController(slider);
pluginPrevious(slider);
pluginNext(slider);
下一部分 slideTo 函数
class Slider{
...
slideTo(idx){
const selected = this.getSelectedItem();
if(selected){
selected.className = 'slider-list__item';
}
const item = this.items[idx];
if(item){
item.className = 'slider-list__item--selected';
}
const detail = {index: idx}
const event = new CustomEvent('slide', {bubbles:true, detail})
this.container.dispatchEvent(event);
...
}
}
上方很好理解,获取已选中的 item 取消样式,获取将要选中的 item 设置样式,下边 new 了一个自定义事件:事件名叫做 slide ,冒泡,有一个参数 index;然后派发给 slider 容器。
分析 Controller
开头很容易理解(代码已省略),鼠标经过跳转,停止 cycle,离开继续 cycle。
重点看一下 slide 的事件监听
function pluginController(slider){
...
slider.addEventListener('slide', evt => {
const idx = evt.detail.index
const selected = controller.querySelector('.slide-list__control-buttons--selected');
if(selected) selected.className = 'slide-list__control-buttons';
buttons[idx].className = 'slide-list__control-buttons--selected';
});
...
}
流程大概这样的:
- 获取事件参数——新的index
- 获取已经选到的小圆点
- 将其样式复原
- 将新的index设置样式
整体流程是这样的:
- 鼠标悬浮到小圆点上(
mouseover监听) - 跳转到指定
item(slider.slideTo(idx)) - 触发
slide事件 (dispatchEvent(event)) - 捕获
slide事件 (slide监听) - 改变小圆点样式
Next和Previous的流程跟上方分析基本一样,不过是将 mouseover 监听替换了 click 监听。
个人总结
我之前也写过一些简单的静态网页,但是很一次性,基本不具备复用性,第一次看见这么厉害的代码还是比较激动的,分析了挺长时间。
同时,如果有误请指正。