zoukankan      html  css  js  c++  java
  • 前端星计划之高复用的组件的设计

    前言

    感觉这次去北京参加的前端星计划,收获非常的大,特别是月影大大讲的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设计

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

    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 {
         100px;
        position: relative;
    }
    .line {
         100%;
        height: 2px;
        background-color: #cccccc;
        border-radius: 1px;
        overflow: hidden;
    }
    .progress {
        height: 2px;
         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;
         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)
    	}
    
  • 相关阅读:
    C#中的正则表达式(1)
    sql link
    Repeater控件绑定数据、分页、数据操作,最佳代码
    存储过程事物
    sql db link string
    存储过程返回值
    net打包
    excel c# 输出
    常用的js验证数字,电话号码,传真,邮箱,手机号码,邮编,日期
    sql 大全
  • 原文地址:https://www.cnblogs.com/xiedashuaige/p/9061898.html
Copyright © 2011-2022 走看看