[前端与HTML]

121 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

前言

  • 怎么样才能写好javaScript
  • 什么是组件封装
  • 什么是高阶函数

写好js的一些原则:

  1. 各司其职
  2. 组件封装
  3. 过程抽象

(一)各司其职
  • HTML/CSS/JS各司其责
  • 应当避免不必要的由JS直接操作样式
  • 可以用class来表示状态
  • 纯展示类交互寻求零JS方案

(二)组件封装

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


总结:

  • 组件设计的原则:封装性,正确性,扩展性,复用性
  • 实现组件的步骤:结构设计,展现效果,行为设计
  • 三次重构
    1. 插件化
    2. 模板化
    3. 抽象化(组件框架)

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

组件封装的例子:

用原生JS写一个电商网站的轮播图,应该如何实现?

结构设计:HTML

轮播图是一个典型的列表结构,可以使用无序列表< ul >元素实现

<div id="my-slider"class='slider-list'>
    <ul>
        <li class="slider-list__item--selected">
            <img src="https://p5.ssl.qhimg.com/t0119c74624763dd070.png" alt="">
        </li>
        <li class="slider-list__item">
            <img src="https://p4.ssl.qhimg.com/t01adbe3351db853eb3.jpg" alt="">
        </li>
        <li class="slider-list__item">
            <img src="https://p2.ssl.qhimg.com/t01645cd5ba0c3b60cb.jpg" alt="">
        </li>
        <li class="slider-list__item">
            <img src="https://p4.ssl.qhimg.com/t01331ac159b58f5478.jpg" alt="">
        </li>
    </ul>
</div>

展现效果:CSS

  • 使用CSS绝对定位将图片重叠在同一个位置
  • 轮播图切换的状态使用修饰符(modifier)
  • 轮播图的切管动画使用CSS(transition)
 *{
        margin: 0;
        padding: 0;
    }
    li{
        list-style: none;
    }
    a{
        text-decoration: none;
        color: inherit;
    }
    #my-slider{
        position: relative;
        width: 790px;
    }
    .slider-list ul{
        list-style-type: none;
        position: relative;
        
    }

    .slider-list__item,
    .slider-list__item--selected{
        position: absolute;
        transition: opacity 1s;
        opacity: 0;
        text-align: center;
    }

    .slider-list__item--selected{
        transition: opacity 1s;
        opacity: 1;
    }

行为设计:API(JS)

  • API设计应保证原子操作,职责单一,满足灵活性。
  • Slider
    • +getSelectedItem()
    • +getSelectedItemIndex
    • +slideTo()
    • +slideNext
    • +slidePrevious()
class Slider{
        constructor(id){
            this.container=document.getElementById(id);
            this.items=this.container.querySelectorAll('.slider-list__item,.slider-list__item--selected');
        }
        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';
            }
        }
        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)
        }
    }

行为设计:控制流

<a class="slide-list__next"></a>
<a class="slide-list__previous"></a>
<div class="slide-list__control">
    <span class="slide-list__control-buttons--selected"></span>
    <span class="slide-list__control-buttons"></span>
    <span class="slide-list__control-buttons"></span>
    <span class="slide-list__control-buttons"></span>
</div>
 

            const detail={index:idx};
            const event=new CustomEvent('slide',{bubble:true,detail});
            this.container.dispatchEvent(event)

改进空间:

  • 重构:插件化
    • 将控制元素抽取成插件
    • 插件与组件之间通过依赖注入方式建立联系
  • 重构:模板化
    • 将HTML模板化
  • 重构:组件框架
    • 将通用的组件模型抽象出来

  • 高阶函数:

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