zoukankan      html  css  js  c++  java
  • JS 自定义组件

    经常会用到JS插件,但从未研究过插件的写法

    目前主流的写法有多种,各有各的优缺点,下面,我就以最常规的一种写法举例

    // plugin.js
    ;(function(undefined) {//防止出现undefined问题
        "use strict"
        var _global;
    
        // 工具函数
        // 对象合并
        function extend(o,n,override) {
            for(var key in n){
                if(n.hasOwnProperty(key) && (!o.hasOwnProperty(key) || override)){
                    o[key]=n[key];
                }
            }
            return o;
        }
        // 自定义模板引擎
        function templateEngine(html, data) {
            var re = /<%([^%>]+)?%>/g,
                reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
                code = 'var r=[];
    ',
                cursor = 0;
            var match;
            var add = function(line, js) {
                js ? (code += line.match(reExp) ? line + '
    ' : 'r.push(' + line + ');
    ') :
                    (code += line != '' ? 'r.push("' + line.replace(/"/g, '\"') + '");
    ' : '');
                return add;
            }
            while (match = re.exec(html)) {
                add(html.slice(cursor, match.index))(match[1], true);
                cursor = match.index + match[0].length;
            }
            add(html.substr(cursor, html.length - cursor));
            code += 'return r.join("");';
            return new Function(code.replace(/[
    	
    ]/g, '')).apply(data);
        }
        // 通过class查找dom
        if(!('getElementsByClass' in HTMLElement)){
            HTMLElement.prototype.getElementsByClass = function(n){
                var el = [],
                    _el = this.getElementsByTagName('*');
                for (var i=0; i<_el.length; i++ ) {
                    if (!!_el[i].className && (typeof _el[i].className == 'string') && _el[i].className.indexOf(n) > -1 ) {
                        el[el.length] = _el[i];
                    }
                }
                return el;
            };
            ((typeof HTMLDocument !== 'undefined') ? HTMLDocument : Document).prototype.getElementsByClass = HTMLElement.prototype.getElementsByClass;
        }
    
        // 插件构造函数 - 返回数组结构
        function MyDialog(opt){
            debugger;
            this._initial(opt);
        }
        MyDialog.prototype = {
            constructor: this,//这种原型链写法必须要加上constructor
            _initial: function(opt) {
                // 默认参数
                var def = {
                    ok: true,
                    ok_txt: '确定',
                    cancel: false,
                    cancel_txt: '取消',
                    confirm: function(){},
                    close: function(){},
                    content: '',
                    tmpId: null
                };
                debugger;
                this.def = extend(def,opt,true); //配置参数
                this.tpl = this._parseTpl(this.def.tmpId); //模板字符串
                this.dom = this._parseToDom(this.tpl)[0]; //存放在实例中的节点
                this.hasDom = false; //检查dom树中dialog的节点是否存在
                this.listeners = []; //自定义事件,用于监听插件的用户交互
                this.handlers = {};
            },
            _parseTpl: function(tmpId) { // 将模板转为字符串
                var data = this.def;
                var tplStr = document.getElementById(tmpId).innerHTML.trim();
                return templateEngine(tplStr,data);
            },
            _parseToDom: function(str) { // 将字符串转为dom
                var div = document.createElement('div');
                if(typeof str == 'string') {
                    div.innerHTML = str;
                }
                return div.childNodes;
            },
            show: function(callback){
                var _this = this;
                if(this.hasDom) return ;
                debugger;
           //自定义事件监听 if(this.listeners.indexOf('show') > -1) { if(!this.emit({type:'show',target: this.dom})) return ; } document.body.appendChild(this.dom); this.hasDom = true; this.dom.getElementsByClass('close')[0].onclick = function(){ _this.hide(); if(_this.listeners.indexOf('close') > -1) { _this.emit({type:'close',target: _this.dom}) } !!_this.def.close && _this.def.close.call(this,_this.dom); }; this.dom.getElementsByClass('btn-ok')[0].onclick = function(){ _this.hide(); if(_this.listeners.indexOf('confirm') > -1) { _this.emit({type:'confirm',target: _this.dom}) } !!_this.def.confirm && _this.def.confirm.call(this,_this.dom); }; if(this.def.cancel){ this.dom.getElementsByClass('btn-cancel')[0].onclick = function(){ _this.hide(); if(_this.listeners.indexOf('cancel') > -1) { _this.emit({type:'cancel',target: _this.dom}) } }; } callback && callback(); if(this.listeners.indexOf('shown') > -1) { this.emit({type:'shown',target: this.dom}) } return this; }, hide: function(callback){ if(this.listeners.indexOf('hide') > -1) { if(!this.emit({type:'hide',target: this.dom})) return ; } document.body.removeChild(this.dom); this.hasDom = false; callback && callback(); if(this.listeners.indexOf('hidden') > -1) { this.emit({type:'hidden',target: this.dom}) } return this; }, modifyTpl: function(template){ if(!!template) { if(typeof template == 'string'){ this.tpl = template; } else if(typeof template == 'function'){ this.tpl = template(); } else { return this; } } this.dom = this._parseToDom(this.tpl)[0]; return this; }, css: function(styleObj){ for(var prop in styleObj){ var attr = prop.replace(/[A-Z]/g,function(word){ return '-' + word.toLowerCase(); }); this.dom.style[attr] = styleObj[prop]; } return this; }, function(val){ this.dom.style.width = val + 'px'; return this; }, height: function(val){ this.dom.style.height = val + 'px'; return this; }, on: function(type, handler){ // type: show, shown, hide, hidden, close, confirm if(typeof this.handlers[type] === 'undefined') { this.handlers[type] = []; } this.listeners.push(type); this.handlers[type].push(handler); return this; }, off: function(type, handler){ if(this.handlers[type] instanceof Array) { var handlers = this.handlers[type]; for(var i = 0, len = handlers.length; i < len; i++) { if(handlers[i] === handler) { break; } } this.listeners.splice(i, 1); handlers.splice(i, 1); return this; } }, emit: function(event){ debugger; if(!event.target) { event.target = this; } debugger; if(this.handlers[event.type] instanceof Array) { var handlers = this.handlers[event.type]; for(var i = 0, len = handlers.length; i < len; i++) { handlers[i](event); return true; } } return false; } } // 最后将插件对象暴露给全局对象 _global = (function(){ return this || (0, eval)('this'); }()); if (typeof module !== "undefined" && module.exports) { module.exports = MyDialog; } else if (typeof define === "function" && define.amd) { define(function(){return MyDialog;}); } else { !('MyDialog' in _global) && (_global.MyDialog = MyDialog); } }());

    调用:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
        <link rel="stylesheet" type="text/css" href="index.css">
    </head>
    <body>
    
    </body>
    <script type="text/template" id="dialogTpl">
        <div class="mydialog">
            <span class="close">×</span>
            <div class="mydialog-cont">
                <div class="cont"><% this.content %></div>
            </div>
            <div class="footer">
                <% if(this.cancel){ %>
                <span class="btn btn-ok"><% this.ok_txt %></span>
                <span class="btn btn-cancel"><% this.cancel_txt %></span>
                <% } else{ %>
                <span class="btn btn-ok" style=" 100%"><% this.ok_txt %></span>
                <% } %>
            </div>
        </div>
    </script>
    <script src="MyDialog.js" type="text/javascript"></script>
    <script>
        var mydialog = new MyDialog({
            tmpId: 'dialogTpl',
            cancel: true,
            content: 'hello world!'
        });
        mydialog.on('confirm',function(ev){
        debugger;
            console.log('you click confirm!');
            // 写你的确定之后的逻辑代码...
        });
        mydialog.show();
    </script>
    </html>
  • 相关阅读:
    timer.Interval用法简介
    .net 未被引用的错误
    将Sql查询语句获取的数据插入到List列表里面
    .net 里面打不出来ConfigurationManager
    .net MVC框架里怎么写控件
    数据库里面几个字符类型的区别
    怎么在.net里面解析JSON文件?
    SqlCommand.ExecuteScalar()方法
    git学习笔记
    可变参数的lambda表达式
  • 原文地址:https://www.cnblogs.com/zyxiaohuihui/p/9412118.html
Copyright © 2011-2022 走看看