JavaScript(1) | 青训营笔记

67 阅读2分钟

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

如何写好JavaScript?

写好JS的一些原则

  • CSS各司其职(让HTML,CSS和JavaScript职能分离)
  • 组件封装(好的ui组件具备正确性,扩展性,复用性)
    • 使代码有更好的扩展性,复用,变得更加通用
  • 过程抽象(应用函数式编程)

ffcd7f15410fad011e662132068a71e.png

组件封装

组件是指Web页面上抽出来一个个包含模板(HTML),功能(JS)和样式(CSS)的单元。好的组件具备封装性,正确性,扩展性,复用性。

基本方法

  • 结构设计(HTML)
  • 展现效果(CSS)
  • 行为设计(JS)
    • API(功能)
    • Event(控制流)

行为:JS

行为:JS

重构:插件化

重构:插件化

解耦

  • 将控制元素抽取成插件
  • 插件与组件之间通过依赖注入方式建立联系
  • 将HTML模板化,更易于扩展

9224c8beadc481932639a3081d3b755.png

class Slider{
    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>`;
    }

重构:模板化

抽象

将组件通用模型抽象出来

05415c13a8a2d2eaf492b44242c4e55.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 ''
    }
  }

组件框架

总结

  • 组件设计的原则:封装性、正确性、扩展性、复用性

  • 实现组件的步骤:结构设计、展现效果、行为设计

  • 三次重构

    1. 插件化
    2. 模板化
    3. 抽象化(组件框架)

过程抽象

  • 用来处理局部细节控制的一些方法
  • 函数式编程思想的基础应用

f432416a0ce32f0b7d9029b6c7add11.png

举例:

操作次数限制

  • 一些异步交互
  • 一次性的HTTP请求
const list = document.querySelector('ul');
  const buttons = list.querySelectorAll('button');
  buttons.forEach((button) => {
    button.addEventListener('click', (evt) => {
      const target = evt.target;
      target.parentNode.className = 'completed';
      setTimeout(() => {
        list.removeChild(target.parentNode);
      }, 2000);
    });
  });

image.png

高阶函数

Once

为了能够让“只执行一次“的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程我们称为过程抽象

 function once(fn) {
    return function(...args) {
      if(fn) {
        const ret = fn.apply(this, args);
        fn = null;
        return ret;
      }
    }
  }

HOF

  • 以函数作为参数
  • 以函数作为返回值
  • 常用于作为函数装饰器
function HOF0(fn) {
    return function(...args) {
      return fn.apply(this, args);
    }
  }

常用高阶函数

编程范式

命令式与声明式

image.png

 let list = [1, 2, 3, 4];
  let mapl = [];
  for(let i = 0; i < list.length; i++) {
    mapl.push(list[i] * 2);
  }
  let list = [1, 2, 3, 4];
  const double = x => x * 2;
  list.map(double);

例子

总结

  • 过程抽象 / HOF / 装饰器
  • 命令式 / 声明式

image.png

总结

对于javascript的内容很多,学习之路还很漫长,通过这次的学习了解到了很多之前不曾知道的关于javascript的内容。