原生JS封装拖动验证滑块你会吗?

作者:微信小助手

发布时间:2020-08-04T18:12:23

作者:_release
原文地址:https://juejin.im/post/5ed37a73e51d45788c739784

前言

闲着没事,就想着写写原生js玩玩,在网上看了几个效果后决定做这个效果,并且使用了prototype和eventEmitter封装成了库。

最终效果

分析

看到这个效果我们首先应该想到和拖动有关的api: onmousedown, onmousemove, onmouseup

其次要支持用户传入放置这个组件的dom元素和完成的回调事件。

最终如何使用?

我们先来看下使用方式,再来决定我们怎么编写这个库

具体使用就是这样的,我们还想用户能通过import等方式使用,所以我们就要支持esMoudule的导入方式。

编写库的整体初始框架

(function ({
    // =================代码块1=========================================
    var root = (typeof self == 'object' && self.self == self && self) ||
        (typeof global == 'object' && global.global == global && global) ||
        this || {}; 
    var util = {
        extendfunction (target{
            for (var i = 1, len = arguments.length; i < len; i++) {
                for (var prop in arguments[i]) {
                    if (arguments[i].hasOwnProperty(prop)) {
                        target[prop] = arguments[i][prop]
                    }
                }
            }
            return target
        },
        isValidListenerfunction (listener{
            if (typeof listener === 'function') {
                return true
            } else if (listener && typeof listener === 'object') {
                return util.isValidListener(listener.listener)
            } else {
                return false
            }
        },
        addCSSfunction (cssText{
            var style = document.createElement('style'),  //创建一个style元素
                head = document.head || document.getElementsByTagName('head')[0]; //获取head元素
            style.type = 'text/css'//这里必须显示设置style元素的type属性为text/css,否则在ie中不起作用
            if (style.styleSheet) { //IE
                var func = function ({
                    try { //防止IE中stylesheet数量超过限制而发生错误
                        style.styleSheet.cssText = cssText;
                    } catch (e) {

                    }
                }
                //如果当前styleSheet还不能用,则放到异步中则行
                if (style.styleSheet.disabled) {
                    setTimeout(func, 10);
                } else {
                    func();
                }
            } else { //w3c
                //w3c浏览器中只要创建文本节点插入到style元素中就行了
                var textNode = document.createTextNode(cssText);
                style.appendChild(textNode);
            }
            head.appendChild(style); //把创建的style元素插入到head中
        },
        indexOffunction (array, item{
            if (array.indexOf) {
                return array.indexOf(item);
            } else {
                var result = -1;
                for (var i = 0, len = array.length; i < len; i++) {
                    if (array[i] === item) {
                        result = i;
                        break;
                    }
                }
                return result;
            }
        }
    }
    
    function EventEmitter({
        this._events = {}
    }

    EventEmitter.prototype.on = function (eventName, listener{
        if (!eventName || !listener) return;
        if (!util.isValidListener(listener)) {
            throw new TypeError('listener must be a function');
        }
        var events = this._events;
        var listeners = events[eventName] = events[eventName] || [];
        var listenerIsWrapped = typeof listener === 'object';
        // 不重复添加事件
        if (util.indexOf(listeners, listener) === -1) {
            listeners.push(listenerIsWrapped ? listener : {
                listener: listener,
                oncefalse
            });
        }
        return this;
    };
    EventEmitter.prototype.once = function (eventName, listener{
        return this.on(eventName, {
            listener: listener,
            oncetrue
        })
    };
    EventEmitter.prototype.off = function (eventName, listener{
        var listeners = this._events[eventName];
        if (!listeners) return;
        var index;
        for (var i = 0, len = listeners.length; i < len; i++) {
            if (listeners[i] && listeners[i].listener === listener) {
                index = i;
                break;
            }
        }
        if (typeof index !== 'undefined') {
            listeners.splice(index, 1null)
        }
        return this;
    };
    EventEmitter.prototype.emit = function (eventName, args{
        var listeners = this._events[eventName];
        if (!listeners) return;
        for (var i = 0; i < listeners.length; i++) {
            var listener = listeners[i];
            if (listener) {
                listener.listener.apply(this, args || []);
                if (listener.once) {
                    this.off(eventName, listener.listener)
                }
            }
        }
        return this;
    };
    
    // =================代码块2=========================================
    function SliderTools(options{
        this.options = util.extend({}, this.constructor.defaultOptions, options)
        this.init();
        this.bindEvents();
        this.diffX = 0;
        this.flag = false;//是否拖动到最右侧
    }

    SliderTools.defaultOptions = {
        eldocument.body //默认放到body里
    };
    
    var proto = SliderTools.prototype = new EventEmitter();//SliderTools继承emitter
    
    proto.constructor = SliderTools;//修正构造器

    proto.init = function ({
        this.createSlider();//创建插件所需要的dom元素
        this.getElements();//获取创建好的元素
    }