【青训营】写好JS——组件封装(下)

简介: 【青训营】写好JS——组件封装(下)

重构:插件化



组件设计比较复杂的点往往在于控制的地方和组件本身有一定的耦合。


比如说上篇轮播图显示第几个图片,第几个小圆点就会标红,它们之间的状态就是耦合的,所以说我们需要解耦:


  1. 将用户控制元素(小圆点和左右箭头)抽取成插件
  2. 插件和组件之间通过依赖注入的方式建立联系


核心就是通过插件注册来实现依赖注入,插件初始化依赖于组件,而组件并不知道插件的存在:


registerPlugins(...plugins) {
  plugins.forEach(plugin => plugin(this));
}
复制代码


然后把原本在构造器中的函数抽取成插件:


image.png


类增加一个addEventListener()的API:


addEventListener(type, handler) {
  this.container.addEventListener(type, handler);
}
复制代码

最后调用即可:


const container = document.querySelector('.slider');
const slider = new Slider({ container });
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
slider.start();
复制代码


这样以来用户控制就解耦了,当PM有新的需求时,我们可以仅删除slider.registerPlugins()中的插件或者创建新的插件再添加。

但是问题是我们还要删除对应的HTML代码,这样还是要修改很多地方,所以下一步我们要把HTML模板化


重构:模板化


现在HTML部分只需要保留一个div:


<div id="my-slider" class="slider-list"></div>
复制代码

在类中实现一个render函数来进行模板化的渲染,通过传入的参数返回正确的HTML模板:


constructor(id, opts = { images: [], cycle: 3000 }) {
  this.container = document.getElementById(id);
  this.options = opts;
  this.container.innerHTML = this.render();
  this.items = this.container.querySelectorAll('.slider-list__item, 
                                              .slider-list__item--selected');
  this.cycle = opts.cycle || 3000;
  this.slideTo(0);
}
render() {
  const images = this.options.images;
  const content = images.map(image => `
      <li class="slider-list__item">
        <img src="${image}"/>
      </li>    
    `.trim());
  return `<ul>${content.join('')}</ul>`;
}
复制代码

这样参数也可以自由设定多张图片,这里我们把它添加到5张:


const slider = new Slider('my-slider', {
  images: [
    'https://gitee.com/mancuojie/typo/raw/master/202201241731487.jpg',
    'https://gitee.com/mancuojie/typo/raw/master/202201241731486.jpg',
    'https://gitee.com/mancuojie/typo/raw/master/202201241731485.jpg',
    'https://gitee.com/mancuojie/typo/raw/master/202201241731484.jpg',
    'https://gitee.com/mancuojie/typo/raw/master/202201241731483.jpg'],
  cycle: 3000
});
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
slider.start();
复制代码


另外插件也要实现自己的render()函数,与组件同步:


image.png


通过action()正确初始化插件数据:


registerPlugins(...plugins) {
  plugins.forEach(plugin => {
    const pluginContainer = document.createElement('div');
    pluginContainer.className = '.slider-list__plugin';
    pluginContainer.innerHTML = plugin.render(this.options.images);
    this.container.appendChild(pluginContainer);
    plugin.action(this);
  });
}
复制代码


这样我们就可以通过传参和修改插件注册来满足不同需求,大大增强了扩展性。


重构:组件框架



组件模板化之后,我们可以在做一层抽象,将组件模型抽象出来进一步提升通用性和扩展性。


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 {
  ...
}
复制代码


改进空间



  1. CSS模板化
  2. 将组件插件结构统一,也就是不再区分组件和插件,全部都是组件,组件和组件之间可以结合成一个大的组件,然后解决父组件和子组件的状态同步和消息通信,就可以完成一个相对完整的多层级的组件框架。
目录
相关文章
|
2月前
sd.js 2.0封装:更加简化请求传参内容(逐步废弃、逐渐日落2024.01.02)
sd.js 2.0封装:更加简化请求传参内容(逐步废弃、逐渐日落2024.01.02)
|
2月前
|
JavaScript
JS封装节流函数
JS封装节流函数
32 0
|
2月前
|
JavaScript
Vue.js 修饰符:精准控制组件行为
Vue.js 修饰符:精准控制组件行为
|
5天前
|
自然语言处理 JavaScript 前端开发
JavaScript闭包是函数访问外部作用域变量的能力体现,它用于封装私有变量、持久化状态、避免全局污染和处理异步操作。
【6月更文挑战第25天】JavaScript闭包是函数访问外部作用域变量的能力体现,它用于封装私有变量、持久化状态、避免全局污染和处理异步操作。闭包基于作用域链和垃圾回收机制,允许函数记住其定义时的环境。例如,`createCounter`函数返回的内部函数能访问并更新`count`,每次调用`counter()`计数器递增,展示了闭包维持状态的特性。
20 5
|
19天前
|
JavaScript
Vue.js中实现自定义组件的双向绑定
Vue.js中实现自定义组件的双向绑定
|
19天前
|
JavaScript
Vue.js中使用作用域插槽实现自定义表格组件
Vue.js中使用作用域插槽实现自定义表格组件
|
3天前
|
JavaScript 前端开发
程序技术好文:第一百三十八节,JavaScript,封装库
程序技术好文:第一百三十八节,JavaScript,封装库
|
26天前
|
存储 移动开发 JavaScript
uni-app 64聊天类chat.js封装(一)
`uni-app` 是一个使用 Vue.js 开发所有前端应用的框架,可以编译到iOS、Android、H5以及各种小程序等多个平台。当你提到“64聊天类`chat.js`封装”时,我假设你希望了解如
|
16天前
JS-函数封装数组求和案例
JS-函数封装数组求和案例
|
2月前
|
JavaScript 前端开发
JavaScript实现缓慢动画的封装
JavaScript实现缓慢动画的封装
18 0