这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
相信大家在日常写项目中,都会遇到写轮播图的问题,或许我们选择使用一些现成的轮播图的库去实现轮播图的功能,又或者是我们选择自己手写一个。但是在手写的时候,大家是否思考过我们可以把轮播图写成一个组件的样子,这样在我们日后使用的时候也是非常方便的
轮播图组件封装
下面我们封装一个轮播图组件,主要功能有自动轮播,点击左右切换按钮可跳转上一张或是下一张
思考一下,在封装这个组件之前,我们要做哪些准备工作?
- 结构设计
- 展现效果
- 行为设计
-
- API(功能)
-
- Event(控制流)
- ......
本篇笔记重点在对API和Event的记录
API部分
我们思考一下,完成一个自动播放轮播图需要哪些功能
- 获取当前展示图片序号
- 播放下一张
- 播放上一张
- 自动播放
- 停止自动播放
这样我们就可以让这个轮播图自动播放起来
class Slider {
constructor(sliderBoxId, imageData) {
this.container = document.getElementById(sliderBoxId);
this.timer = undefined;
this.items = this.container.querySelectorAll('.slider-list_item,.slider-list_item-selected');
}
autoPlayStart() {
this.autoPlayStop()
this.timer = setInterval(() => {
this.goToNext()
}, 1500)
}
autoPlayStop() {
clearInterval(this.timer)
}
getSelectedIdx() {
const item = document.querySelector('.slider-list_item-selected')
return Array.from(this.items).indexOf(item);
}
goToNext() {
const selectedIdx = this.getSelectedIdx()
const nextSelectedIdx = (selectedIdx + 1) % (this.items.length);
if (selectedIdx === -1) {
this.container.querySelectorAll('.slider-list_item,.slider-list_item-selected')[nextSelectedIdx].className = 'slider-list_item-selected'
}
else {
this.items[selectedIdx].className = 'slider-list_item';
this.items[nextSelectedIdx].className = 'slider-list_item-selected'
}
}
goToPre() {
const selectedIdx = this.getSelectedIdx()
const preSelectedIdx = (selectedIdx + 4) % (this.items.length);
this.items[selectedIdx].className = 'slider-list_item';
this.items[preSelectedIdx].className = 'slider-list_item-selected'
}
}
切换按钮
我们可以在上面代码中加入下面部分,记得要先获取按钮元素,本处就不展示了
goNextBtnWork() {
this.goNextBtn.addEventListener('click', () => {
this.goToNext(this.container, this.items);
})
}
goPreBtnWork() {
this.goPreBtn.addEventListener('click', () => {
this.goToPre(this.container, this.items);
})
}
再想想有没有什么改进的地方
1.插件化
我们可以将切换按钮变成独立的插件插入到我们的轮播图中,将插件与组件之间通过依赖注入的方式建立联系
//在js文件中写入以下内容
class btnPrePlugin {
action(slider) {
const preBtn = slider.container.querySelector(`.goPreBtn`);
if (preBtn) {
preBtn.addEventListener('click', (e) => {
slider.autoPlayStop()
slider.goToPre(slider.container, slider.items);
slider.autoPlayStart()
e.preventDefault()
})
}
}
}
class btnNextPlugin {
action(slider) {
const nextBtn = slider.container.querySelector(`.goNextBtn`);
if (nextBtn) {
nextBtn.addEventListener('click', (e) => {
slider.autoPlayStop()
slider.goToNext(slider.container, slider.items);
slider.autoPlayStart()
e.preventDefault()
})
}
}
}
2.模板化
我们再想想还有什么能优化的?我们可以将HTML模板化,更易于扩展
下面是将图片展示列表的部分模板化
class Slider {
constructor(sliderBoxId, imageData) {
this.container = document.getElementById(sliderBoxId);
this.timer = undefined;
this.imgs = imageData.data
this.container.innerHTML += this.render()
this.items = this.container.querySelectorAll('.slider-list_item,.slider-list_item-selected');
}
render() {
const sliderList = this.imgs.map(img =>
`
<li class="slider-list_item">
<img src="${img}" />
</li>
`.trim())
return `<ul>${sliderList.join('')}</ul>`
}
...
}
同样我们可以对按钮插件进行同样操作
render() {
return `<button class='slider-list-btn goNext(Pre)Btn'>></button>`
}
收尾部分
const slider = new Slider('my-slider', imageData)
const pre = new btnPrePlugin();
const next = new btnNextPlugin()
slider.registerAction(pre, next)
slider.autoPlayStart()
这样我们就可以完成一个简单的轮播图组件啦!
写在结尾
这次月影老师对于js讲解的课程让我受益匪浅,对于编写js代码有了一个全新的视角,很开心能够学到今天的知识,并自己尝试写了一个很简单的demo,有写的不好的地方希望大家能够帮我指出,感谢各位大佬!