前言
感觉这次去北京参加的前端星计划,收获非常的大,特别是月影大大讲的js课程,让我感觉再次之前根本就没有学到js的精髓,一直都是在为了完成某个页面而去写这个页面,根本没有去考虑这个页面接下来的维护,所有的变量全部都耦合在一起,为了改一个点,你需要该无数地方的代码。然后在更多的时候都是在写重复的代码,根本没有考虑到组件的复用的问题。然后对es6很多新的方法都没有接触过。总而言之,就是自己太菜了,还要加把劲的学习。
轮播图组件实现大概思想
轮播组件之结构设计
在编写一个组件的时候你先需要把组件的样式给写出来,比如说,我们要做一个轮播的组件,然后就是几张图片叠加在一起,需要哪张图片就显示哪张图片,这个是基础的样式。
- 图片结构是一个列表型结构,所以主体用
- 使用 css 绝对定位将图片重叠在同一个位置
- 轮播图切换的状态使用修饰符(modifier)
- 轮播图的切换动画使用 css transition
轮播组件之API设计
在你想好要做组件之前,你需要对这个组件进行api的设置。建一个类,然后在类中写各种需要的方法。

轮播组件之控制流设计
在类之中的方法之间还是会有一定的耦合,这样的话可以采用自定义事件的方法,只需要绑定事件就可以
控制结构
1 2 3 4 5 6 7 8
| <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>
|
自定义事件
1 2 3
| const detail = {index: idx} const event = new CustomEvent('slide', {bubbles:true, detail}) this.container.dispatchEvent(event)
|
轮播图之各种优化
在完成上面的后你还可以进行各种优化,比如说,依赖注入,把每一个小插件作为一个依赖注入到组件中,需要这个依赖就注入一下就好,不需要就不要管他。代码也不会报错。然后你还可以进行插件化和模版化把每个依赖的小插件的html代码写在js中,只有使用了这个插件才会渲染这段代码。
拖动条组件的设计
样式设计
大概写出来是这个样子,左边是输入框,通过输入框输入可以改变右边的进度,然后右边是可以拖动的拖动条,拖动后可以改变左边的输入框的值。

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

实现思路
由于需要数据双向绑定,这里使用的方法是,在你改变数据的时候不是直接改变数据,而是调用setData方法来改变数据,调用setData方法里面会调用数据的渲染方法,就和小程序一样,这样改变数据才会激活视图的更新。
然后clickDot是实现点击小圆点来拖动的效果。对小圆点设置一个mousedown事件,发生按下去的事件后对窗口设置一个mousemove事件随时改变小圆点的位置,当松开的时候就清楚mousemove事件。
同时在小圆点动的时候激活一个自定义的移动事件,为了响应的更改input中的数据。
改变进度和小圆点的位置的时候,全部依赖的是定义的数据,所以渲染界面只需要setData一下就可以了。
然后对于输入框,如果界面改变了,就会激活自定义事件,监听一下,然后通过getPercentage来获得当前的数据。如果输入框里面的值变了,然后调用setData方法就好了。
总结反思
这是第一次使用类的方式来写组件,基本实现了数据的双向绑定,然后在new的时候你可以配置一些基本的参数,然后还学会了自定义事件,在此之前是通过回调函数来实现的。但是还是有许多需要改进的地方,组件还可以细分成几个小的插件,在新建的时候就可以通过依赖注入的方式来注入想要的插件
代码
html
1 2 3 4 5 6 7 8
| <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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| *{ 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-滑动类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| 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
1 2 3 4 5 6 7 8 9 10 11
| 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) }
|