js的小知识 | 青训营笔记

97 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第24天,也是课程结束后的第一天,本篇将对在青训营里学到的javascript相关内容进行一个总结。

深夜食堂

结论:

  1. html、css、js各司其职
  2. 避免不必要的由js直接操作
  3. class可用来表示状态
  4. 纯展示类交互寻求零js方案

组件封装

组件:web页面上拖出来的一个个包含模板(html)、功能(js)、样式(css)的单元

好的组件特性: 封装性、正确性、扩展性、复用性

案例教学

轮播图

行为: API: getSelectedItem() getSelectedItemIndex() slideTo() slideNext() slidePrevious()

基本方法

  1. 结构设计
  2. 展现效果
  3. 行为设计 API(功能) Event(控制流):自定义事件解耦

重构:插件化

原先组件功能没问题,但是不够灵活:不能更改控件... 改进:重构,插件化组件

原先代码大多在construcrtor里,不好

开发自定义事件:

  1. 定义事件数据 const detail = {index : idx} //index为名称

  2. 创建事件 const myEvent = new CustomEvent('事件名称', {可配置项}) 可配置项:事件冒泡bubbles:true , 传递参数detail

  3. 添加事件监听 .addEventListener('事件名称',e=>{ (e.detail.index 调用参数) 事件; })

  4. 派发事件 .dispatchEvent(myEvent)

//创建
const detail = {index: idx}
const event = new CustomEvent('slide', {bubbles:true, detail})
this.container.dispatchEvent(event)
//
addEventListener(type, handler){
    this.container.addEventListener(type, handler)
}
//事件监听
slider.addEventListener('slide', evt => {
    const idx = evt.detail.index;
    const selected = controller.querySelector('.btn-control--selected');
    if(selected) selected.className = 'btn-control';
    buttons[idx].className = 'btn-control--selected';
});

解耦

  1. 将控制元件抽取成插件

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

重构:模板化

将html模板化,易于扩展

组件封装-总结

  1. 组件设计原则: 封装性,正确性,扩展性,复用性

  2. 实现组件的步骤: 结构设计,展现效果,行为设计

  3. 三次重构 插件化 模板化 抽象化

过程抽象

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

input x --> output f(x)click

只触发一次click addEventListener('click',()=>{},(once:true)) addEventListener('click', once( ()=>{ } ) ) 封装成一个过程抽象/高阶函数

function once(fn) {
    //外部闭包
    return function(...args){
        if(fn){
            const ret = fn.apply(this, args);
            fn = null;
            return ret;
        }
    }
}

高阶函数

函数作为参数 函数作为返回值 常用于做函数装饰器

//等价高阶函数
function HOF0(fn){
    return function(...args){
        return fn.apply(this, args);
    }
}

常用高阶函数:

  1. once
  2. throttle节流函数
function throttle(fn, time = 500){
    let timer ;

    return function(...args){
        if(timer == null){
            fn.apply(this, args);
            timer = setTimeout(() => {
                timer = null;
            }, time);
        }
    }
}
  1. debounce防抖 比如打字或者移动鼠标,不动了再进行保存
function debounce(fn, dur){
    dur = dur || 100;
    let timer;
    return function(){
        clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.apply(this, arguments);
        }, dur);
    }
}
  1. consumer/2
  2. Iterative 可迭代方法,批量操作
const isTterable = obj => !=null && typeof obj[Symbol.iterative] === 'function';

function Iterative(fn){
    return function(subject, ...rest){
        const ret = [];
        for(let obj of subject){
            ret.push(fn.apply(this. [obj, ...rest]));
        }
        return ret;
    }
    return fn.apply(this, [subject, ...rest]);
}

为什么要使用高阶函数

编程范式

命令式与声明式

红绿灯:

function toggle(...actions){
  return function(...args){
    let action = actions.shift();
    actions.push(action);
    return action.apply(this, args);
  }
}

switcher.onclick = toggle(
  evt => evt.target.className = 'warn',
  evt => evt.target.className = 'off',
  evt => evt.target.className = 'on'
);