javaScript的三大原则——组件封装 | 青训营笔记
这是我参与「第四届青训营」笔记创作活动的的第3天
组件是指Web页面上抽出来的一个个包含模板(HTML),功能(js)和样式(CSS)的单元
-
结构设计 HTML
-
展现效果 CSS
-
行为设计 JavaScript
- API (功能)
- Event (控制流)
但要具备的基本应该
具备封装性、正确性、扩展性、复用性
所有对基本的轮播图进行重构
定义一个组件类,以后直接进行调用
class Component {
constructor(id, opts = {
name,
data: []
}) {
this.container = document.getElementById(id);
this.options = opts;
this.container.innerHTML = this.render(opts.data);
}
registerPlugins(...plugins) {
plugins.forEach(plugin => {
const pluginContainer = document.createElement('div');
pluginContainer.className = `.${name}__plugin`;
pluginContainer.innerHTML = plugin.render(this.options.data);
this.container.appendChild(pluginContainer);
plugin.action(this);
});
}
render(data) {
/* abstract */
return ''
}
}
之后得轮播图组件继承我们定义得通用组件
class Slider extends Component {
constructor(id, opts = {
name: 'slider-list',
data: [],
cycle: 3000
}) {
super(id, opts);
this.items = this.container.querySelectorAll('.slider-list__item, .slider-list__item--selected');
this.cycle = opts.cycle || 3000;
this.slideTo(0);
}
render(data) {
const content = data.map(image => `
<li class="slider-list__item">
<img src="${image}"/>
</li>
`.trim());
return `<ul>${content.join('')}</ul>`;
}
getSelectedItem() {
const selected = this.container.querySelector('.slider-list__item--selected');
return selected
}
getSelectedItemIndex() {
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';
}
const detail = {
index: idx
}
const event = new CustomEvent('slide', {
bubbles: true,
detail
})
this.container.dispatchEvent(event)
}
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);
}
addEventListener(type, handler) {
this.container.addEventListener(type, handler);
}
start() {
this.stop();
this._timer = setInterval(() => this.slideNext(), this.cycle);
}
stop() {
clearInterval(this._timer);
}
}
把其他得作为插件,然后之间进行调用
const slider = new Slider('my-slider', {
name: 'slide-list',
data: ['https://p5.ssl.qhimg.com/t0119c74624763dd070.png',
'https://p4.ssl.qhimg.com/t01adbe3351db853eb3.jpg',
'https://p2.ssl.qhimg.com/t01645cd5ba0c3b60cb.jpg',
'https://p4.ssl.qhimg.com/t01331ac159b58f5478.jpg'
],
cycle: 1000
});
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
slider.start();
结果如下图:
这样可以完美得实现封装性,复用性,拓展性等,有很好的优点
可以形成一个不错的小框架 这样的不断解耦JS实现插件化,解耦HTML实现模板化,甚至还可以解耦CSS,这中思路提供了代码设计和抽象的一套通用规范,而遵循这套规范的基础库,实际上就是完整的UI组件框架。