javaScript的三大原则——组件封装 | 青训营笔记

59 阅读1分钟

javaScript的三大原则——组件封装 | 青训营笔记

这是我参与「第四届青训营」笔记创作活动的的第3天

组件是指Web页面上抽出来的一个个包含模板(HTML),功能(js)和样式(CSS)的单元

  • 结构设计 HTML

  • 展现效果 CSS

  • 行为设计 JavaScript

    • API (功能)
    • Event (控制流)

但要具备的基本应该

具备封装性、正确性、扩展性、复用

所有对基本的轮播图进行重构

image.png

定义一个组件类,以后直接进行调用

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();

结果如下图:

图片.png

这样可以完美得实现封装性,复用性,拓展性等,有很好的优点

可以形成一个不错的小框架 这样的不断解耦JS实现插件化,解耦HTML实现模板化,甚至还可以解耦CSS,这中思路提供了代码设计和抽象的一套通用规范,而遵循这套规范的基础库,实际上就是完整的UI组件框架。