前端星计划之高复用的组件的设计

前言

感觉这次去北京参加的前端星计划,收获非常的大,特别是月影大大讲的js课程,让我感觉再次之前根本就没有学到js的精髓,一直都是在为了完成某个页面而去写这个页面,根本没有去考虑这个页面接下来的维护,所有的变量全部都耦合在一起,为了改一个点,你需要该无数地方的代码。然后在更多的时候都是在写重复的代码,根本没有考虑到组件的复用的问题。然后对es6很多新的方法都没有接触过。总而言之,就是自己太菜了,还要加把劲的学习。

轮播图组件实现大概思想

轮播组件之结构设计

在编写一个组件的时候你先需要把组件的样式给写出来,比如说,我们要做一个轮播的组件,然后就是几张图片叠加在一起,需要哪张图片就显示哪张图片,这个是基础的样式。

  1. 图片结构是一个列表型结构,所以主体用
  2. 使用 css 绝对定位将图片重叠在同一个位置
  3. 轮播图切换的状态使用修饰符(modifier)
  4. 轮播图的切换动画使用 css transition

    轮播组件之API设计

    在你想好要做组件之前,你需要对这个组件进行api的设置。建一个类,然后在类中写各种需要的方法。
    image

    轮播组件之控制流设计

    在类之中的方法之间还是会有一定的耦合,这样的话可以采用自定义事件的方法,只需要绑定事件就可以

控制结构

<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', {bubbles:true, detail})
this.container.dispatchEvent(event)

轮播图之各种优化

在完成上面的后你还可以进行各种优化,比如说,依赖注入,把每一个小插件作为一个依赖注入到组件中,需要这个依赖就注入一下就好,不需要就不要管他。代码也不会报错。然后你还可以进行插件化和模版化把每个依赖的小插件的html代码写在js中,只有使用了这个插件才会渲染这段代码。

拖动条组件的设计

样式设计

大概写出来是这个样子,左边是输入框,通过输入框输入可以改变右边的进度,然后右边是可以拖动的拖动条,拖动后可以改变左边的输入框的值。

image

API设计

这个组件大概包括以下的几个接口

扫描二维码关注公众号,回复: 940981 查看本文章

image.png

实现思路

由于需要数据双向绑定,这里使用的方法是,在你改变数据的时候不是直接改变数据,而是调用setData方法来改变数据,调用setData方法里面会调用数据的渲染方法,就和小程序一样,这样改变数据才会激活视图的更新。

然后clickDot是实现点击小圆点来拖动的效果。对小圆点设置一个mousedown事件,发生按下去的事件后对窗口设置一个mousemove事件随时改变小圆点的位置,当松开的时候就清楚mousemove事件。

同时在小圆点动的时候激活一个自定义的移动事件,为了响应的更改input中的数据。

改变进度和小圆点的位置的时候,全部依赖的是定义的数据,所以渲染界面只需要setData一下就可以了。

然后对于输入框,如果界面改变了,就会激活自定义事件,监听一下,然后通过getPercentage来获得当前的数据。如果输入框里面的值变了,然后调用setData方法就好了。

总结反思

这是第一次使用类的方式来写组件,基本实现了数据的双向绑定,然后在new的时候你可以配置一些基本的参数,然后还学会了自定义事件,在此之前是通过回调函数来实现的。但是还是有许多需要改进的地方,组件还可以细分成几个小的插件,在新建的时候就可以通过依赖注入的方式来注入想要的插件

代码

html
<div id="control">
    <div class="sensitivity" id="sensitivity">
        <div class="line" id="line">
            <div class="progress" id="progress"></div>
        </div>
        <div class="dot"></div>
    </div>
</div>
css
*{
    margin: 0;
    padding: 0;
}
.sensitivity {
    width: 100px;
    position: relative;
}
.line {
    width: 100%;
    height: 2px;
    background-color: #cccccc;
    border-radius: 1px;
    overflow: hidden;
}
.progress {
    height: 2px;
    width: 0;
    background-color: #57A3F3;
    -webkit-transition: all .2s;
    -moz-transition: all .2s;
    -ms-transition: all .2s;
    -o-transition: all .2s;
    transition: all .2s;
}
.dot {
    cursor: pointer;
    height: 6px;
    width: 6px;
    border: 2px solid #57A3F3;
    box-sizing: border-box;
    background-color: #ffffff;
    border-radius: 50%;
    position: absolute;
    top: -2px;
    left:  -3px;
    -webkit-transition: all .2s;
    -moz-transition: all .2s;
    -ms-transition: all .2s;
    -o-transition: all .2s;
    transition: all .2s;
}

.dot:hover {
    cursor: pointer;
    border: 1px solid #57A3F3;
}
js-滑动类
class Slide {
    constructor(dot, progress, father) {
        this.data = 0;
        //判断是否存在
        this.dot = dot;
        this.progress = progress;
        //父组件
        this.father = father;
    }
    //设置数据
    setData(data) {
        this.data = data;
        this.setPercentage()
    }
    //渲染方法
    render() {
        this.clickDot();
    }
    //所有监听事件来控制拖动条
    clickDot() {
        let sensitivity = this.father.querySelector(".sensitivity");
        let dot = this.father.querySelector(".sensitivity .dot");
        //自定义事件,通过监听事件来重新渲染dom
        const slideEvent = new CustomEvent("slide");

        dot.addEventListener("mousedown", (e) => {
            document.onmousemove = (e) => {
                //设置data
                this.setData((e.clientX - sensitivity.offsetLeft) / sensitivity.offsetWidth * 100);
                document.dispatchEvent(slideEvent);
            };
            document.onmouseup = () => {
                document.onmousemove = null;
            }
        });
    }
    //设置百分数来改变进度
    setPercentage() {
        if (this.data < 0) {
            this.data = 0;
        }
        if (this.data > 100) {
            this.data = 100;
        }
        let sensitivityWidth = this.father.querySelector(".sensitivity").offsetWidth;

        if (this.dot) {
            this.setDot(this.data * sensitivityWidth * 0.01 - 3 + 'px');
        }
        if (this.progress) {
            this.setProgress(this.data * sensitivityWidth * 0.01 + "px");
        }
    }
    //得到当前的百分数
    getPercentage() {
        return this.data;
    }
    //设置点的位置
    setDot(position) {
        let dot = this.father.querySelector(".sensitivity .dot");
        if (dot) {
            dot.style.left = position;
        }
    }
    //设置进度的位置
    setProgress(position) {
        let progress = this.father.querySelector(".sensitivity .progress");
        if (progress) {
            progress.style.width = position;
        }
    }
}
js-new
    let father = document.querySelector("#control");
    let a = new Slide(true, true, father);
    a.render();

    document.addEventListener("slide", (e) => {
        document.querySelector("#input").value = parseInt(a.getPercentage());
    });
    //监听输入框改变
    document.querySelector("#input").onkeyup = () => {
        a.setData(document.querySelector("#input").value)
    }

猜你喜欢

转载自www.cnblogs.com/xiedashuaige/p/9061898.html