JavaScript插件式封装

JavaScript插件式封装

Charliexiu Lv2

封装组件的三个部分

  1. 结构 HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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>
</div>
  1. 效果 CSS

  2. 行为 JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 轮播图类 里面封装一些api
class Slider {
constructor(id) {
this.container = document.getElementById(id);
this.items = this.container.querySelectorAll(
".slider-list__item, .slider-list__item--selected"
);
}
// 获取选中的图片元素
getSelectedItem() {
const selected = this.container.querySelector(
".slider-list__item--selected"
);
return selected;
}
//获取选中图片的索引值,返回其在items数组中的位置
getSelectedItemIndex() {
// Array.from() 方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
// querySelectorAll返回NodeList 对象,NodeList 不是一个数组,是一个类似数组的对象(Like Array Object)。
// 虽然 NodeList 不是一个数组,但是可以使用 forEach() 来迭代。你还可以使用 Array.from() 将其转换为数组。
return Array.from(this.items).indexOf(this.getSelectedItem());
}
// 跳转到指定索引的图片
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";
}
}
// 跳转到下一索引的图片,将下一张图片标记为选中状态
slideNext() {
const currentIdx = this.getSelectedItemIndex();
const nextIdx = (currentIdx + 1) % this.items.length;
this.slideTo(nextIdx);
}
// 跳转到上一索引的图片,将上一张图片标记为选中状态
slidePrevious() {
const currentIdx = this.getSelectedItemIndex();
const previousIdx =
(this.items.length + currentIdx - 1) % this.items.length;
this.slideTo(previousIdx);
}
}
const slider = new Slider("my-slider");
setInterval(() => {
slider.slideNext();
}, 1000);

封装需要考虑的原则

  1. 封装性

  2. 正确性

  3. 扩展性

  4. 复用性

  5. 简易性


实现插件化

将控制元素抽取成插件

插件与组件之间通过依赖注入方式建立联系

实现模板化

这一步对结构 HTML进行模块化, 更易扩展和消除

实现抽象化

转化为组件的关键步骤

将通用组件模型抽象出来


vue 中在components文件夹下,通过写一个页面包含三个部分在另一个页面通过组件名引入的方式就是封装组件最好的理解方式

插件化解耦JavaScript

这是在还没插件化之前的javascript,初始化,构造函数的配置,包括了很多事件监听和鼠标点击事件,以及动画的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
constructor(id, cycle = 3000) {
this.container = document.getElementById(id);
this.items = this.container.querySelectorAll(
".slider-list__item, .slider-list__item--selected"
);
this.cycle = cycle;

const controller = this.container.querySelector(
".slide-list__control"
);
if (controller) {
const buttons = controller.querySelectorAll(
".slide-list__control-buttons, .slide-list__control-buttons--selected"
);

// 给小圆点加监听,经过某个圆点的就将图片切换到该位置的图片
controller.addEventListener("mouseover", (evt) => {
const idx = Array.from(buttons).indexOf(evt.target);
if (idx >= 0) {
this.slideTo(idx);
this.stop();
}
});

// 鼠标移开小圆点,就继续开始循环轮播
controller.addEventListener("mouseout", (evt) => {
this.start();
});

// 注册slide事件,将选中的图片和小圆点设置为selected状态
this.container.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";
});
}

下面一段代码是在实现插件化之后的构造函数

1
2
3
4
5
6
7
constructor(id, cycle = 3000) {
this.container = document.getElementById(id);
this.items = this.container.querySelectorAll(
".slider-list__item, .slider-list__item--selected"
);
this.cycle = cycle;
}

对比可以发现,少了很多,在解耦合之前,也就是插件化封装之前,

  • 获取小圆点下标

  • 鼠标移开小圆点事件

  • slide事件

  • button事件

都在构造函数里面,且无法通过直观的看出需要修改或是删除哪几个部分才能更改这个配置

于是采用插件化

1
2
3
registerPlugins(...plugins) {
plugins.forEach((plugin) => plugin(this));
}
1
2
3
function pluginController(slider) { }
function pluginPrevious(slider) { }
function pluginNext(slider) { }

抽离后,采用调用插件的方式引入这些插件,实现增加和删除或是修改的操作

1
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);

更多

更多更详细的可以前往查看

网址:【字节前端青训营】跟着月影学JavaScript—— 前端代码优化三大原则之组件封装,用原生JS写一个轮播图并封装 - 腾讯云开发者社区-腾讯云

  • 标题: JavaScript插件式封装
  • 作者: Charliexiu
  • 创建于: 2023-04-18 23:49:24
  • 更新于: 2023-04-19 00:19:15
  • 链接: https://ccharlie-xiu.github.io/2023/04/18/组件封装/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。