zoukankan      html  css  js  c++  java
  • jQuery插件写法总结以及面向对象方式写法总结

    写法一

    插件主体

    (function($, window){
        // 初始态定义
        var _oDialogCollections = {};
     
        // 插件定义
        $.fn.MNDialog = function (_aoConfig) {
            // 默认参数,可被重写
            var defaults = {
                // string
                sId : "",
                // num
                nWidth : 400,
                // bollean
                bDisplayHeader : true,
                // object
                oContentHtml : "",
                // function
                fCloseCallback : null
            };
     
            var _oSelf = this,
                $this = $(this);
     
            // 插件配置
            this.oConfig = $.extend(defaults, _aoConfig);
     
            // 初始化函数
            var _init = function () {
                if (_oDialogCollections) {
                    // 对于已初始化的处理
                    // 如果此时已经存在弹框,则remove掉再添加新的弹框
                }
                // 初始化弹出框数据
                _initData();
                // 事件绑定
                _loadEvent();
                // 加载内容
                _loadContent();            
            }
            // 私有函数
            var _initData = function () {};
            var _loadEvent = function () {};
            var _loadContent = function () {
                // 内容(分字符和函数两种,字符为静态模板,函数为异步请求后组装的模板,会延迟,所以特殊处理)
                if($.isFunction(_oSelf.oConfig.oContentHtml)) {
                    _oSelf.oConfig.oContentHtml.call(_oSelf, function(oCallbackHtml) {
                        // 便于传带参函数进来并且执行
                        _oSelf.html(oCallbackHtml);
                        // 有回调函数则执行
                        _oSelf.oConfig.fLoadedCallback && _oSelf.oConfig.fLoadedCallback.call(_oSelf, _oSelf._oContainer$);
                    });
                } else if ($.type(_oSelf.oConfig.oContentHtml) === "string") {
                    _oSelf.html(_oSelf.oConfig.oContentHtml);
                    _oSelf.oConfig.fLoadedCallback && _oSelf.oConfig.fLoadedCallback.call(_oSelf, _oSelf._oContainer$);
                } else {
                    console.log("弹出框的内容格式不对,应为function或者string。");
                }
            };
     
            // 内部使用参数
            var _oEventAlias = {
                click         : 'D_ck',
                dblclick     : 'D_dbl'
            };
     
            // 提供外部函数
            this.close = function () {
                _close();
            }        
     
            // 启动插件
            _init();
     
            // 链式调用
            return this;        
        };
        // 插件结束
    })(jQuery, window);

    调用

    var MNDialog = $("#header").MNDialog({
        sId : "#footer",        //覆盖默认值
        fCloseCallback : dialog,//回调函数
        oContentHtml : function(_aoCallback){
                _aoCallback(_oEditGrpDlgView.el);
            }
        }
    });
    // 调用提供的函数
    MNDialog.close;
    function dialog(){
     
    }

    点评

    1. 自调用匿名函数

    用处:通过定义一个匿名函数,创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏全局的命名空间。这点非常有用也是一个JS框架必须支持的功能,jQuery被应用在成千上万的JavaScript程序中,必须确保jQuery创建的变量不能和导入他的程序所使用的变量发生冲突。

    2. 匿名函数为什么要传入window

    通过传入window变量,使得window由全局变量变为局部变量,当在jQuery代码块中访问window时,不需要将作用域链回退到顶层作用域,这样可以更快的访问window;这还不是关键所在,更重要的是,将window作为参数传入,可以在压缩代码时进行优化,看看jquery.min.js:

    3. 全局变量this定义

    使得在插件的函数内可以使用指向插件的this

    4. 插件配置

    设置默认参数,同时也可以再插件定义时传入参数覆盖默认值

    5. 初始化函数

    一般的插件会有init初始化函数并在插件的尾部初始化

    6. 私有函数、公有函数

    私有函数:插件内使用,函数名使用”_”作为前缀标识

    共有函数:可在插件外使用,函数名使用”this.”作为前缀标识,作为插件的一个方法供外部使用

    7. return this

    最后返回jQuery对象,便于jQuery的链式操作

    写法二

    主体结构

    (function($){
        $.fn.addrInput = function(_aoOptions){
            var _oSelf = this;
            _oSelf.sVersion = 'version-1.0.0';
            _oSelf.oConfig = {
                nInputLimitNum : 9
            };
            // 插件配置
            $.extend(_oSelf.oConfig, _aoOptions);
     
            // 调用这个对象的方法,传递this
            $.fn.addrInput._initUI.call(_oSelf, event);
            $.fn.addrInput._initEvents.call(_oSelf);
     
            // 提供外部函数
            this.close = function () {
                _close();
            }
     
            //返回jQuery对象,便于Jquery的链式操作    
            return _oSelf;                   
        }
        $.fn.addrInput._initUI = function(event){
            var _oSelf = this,
                _oTarget = $(event.currentTarget);
        }
        $.fn.addrInput._initEvents = function(){}
    })(window.jQuery); 

    点评

    1. 美观

    插件的方法写在外部,并通过在插件主体传递this的方式调用

    2. 定义插件版本号

    不过在这里还是没有用到

    3. 关于call

    这里的第一个参数为传递this,后面的均为参数

    语法:

    定义:调用一个对象的一个方法,以另一个对象替换当前对象。

    说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

    4. 关于”this”

    在插件的方法中,可能有用到指向插件的this、和指向事件触发的this,所以事件触发的this用event来获取:event.cuerrntTarget

    • event.currentTarget:指向事件所绑定的元素,按照事件冒泡的方式,向上找到元素
    • event.target:始终指向事件发生时的元素

    如:

    html代码

     js代码

    $('#wrapper').click(function(e) {
        console.log('#wrapper');
        console.log(e.currentTarget);
        console.log(e.target);
    });
    $('#inner').click(function(e) {
        console.log('#inner');
        console.log(e.currentTarget);
        console.log(e.target);
    }); 

    结果输出

    写法三(原生写法)

    主体结构

    var MemberCard = function(_aoOption){
        // 配置(默认是从外面传进来)
        _aoOption || (_aoOption = {}) ;
        // 初始化函数
        _init(this);
    }
     
    var _init = function(_aoSelf) {
        // 函数执行
        _initData(_aoSelf);
        // 调用对象的私有方法
        _aoSelf._timedHide();
    }
     
    var _initData = function ( _aoSelf ) {}
     
    // 私有方法
    MemberCard.prototype._timedHide = function(_aoOptions) {
        var _oSelf = this;
        clearTimeout(this.iHideTimer);    
        // 使用underscore.js的extend方法来实现属性覆盖
        var oDefault = extend( { nHideTime: 300 }, _aoOptions );
        _oSelf.iHideTimer = setTimeout( function(){
            // 调用对象的共有方法
            _oSelf.hide();
        }, oDefault.nHideTime);        
    }
     
    // 公有方法
    MemberCard.prototype.hide = function(_aoOptions) {}

    使用

    var oColleagueCard = new MemberCard({ nHideTime: 200 });
    oColleagueCard.hide();
    

      

    点评

    1. 关于属性覆盖(对象深拷贝)

    原生函数实现方法

    demo:

    基于jQuery的实现方法

    用一个或多个其他对象来扩展一个对象,返回被扩展的对象。

    如果不指定target,则给jQuery命名空间本身进行扩展。这有助于插件作者为jQuery增加新方法。 如果第一个参数设置为true,则jQuery返回一个深层次的副本,递归地复制找到的任何对象。否则的话,副本会与原对象共享结构。 未定义的属性将不会被复制,然而从对象的原型继承的属性将会被复制。

    demo:

     2. 关于this

    这个对象的所有方法的this都指向这个对象,所以就不需要重新指定

    写法四

    主体结构

    function EditorUtil() {
        this._editorContent = $( '#editor_content' );
        this._picBtn = $( '#project_pic' );
        this.ieBookmark = null;
    }
    EditorUtil.prototype = {
        consturctor: EditorUtil,
     
        noteBookmark: function() {
        },
        htmlReplace: function( text ) {
            if( typeof text === 'string' ) {
                return text.replace( /[<>"&]/g, function( match, pos, originalText ) {
                    switch( match ) {
                        case '<':
                            return '<';
                        case '>':
                            return '>';
                        case '&':
                            return '&';
                        case '"':
                            return '"';
                    }
                });
            }
            return '';
        },
        init: function() {
            this._memBtn.bind( 'click', function( event ) {
                $(".error_content").hide();
                return false;
            });
        }
    };
     
    // 初始化富文本编辑器
    var editor = new EditorUtil();
    editor.init();

    点评

    写法四和写法三其实都差不多,但是你们有没有看出其中的不一样呢?

    1. 两种都是利用原型链给对象添加方法

    写法三:

    写法四:

    EditorUtil.prototype = {
        consturctor: EditorUtil,
        noteBookmark: function(){},    
        htmlReplace: function(){}
    }
    

      

    细看写法四利用“对象直接量”的写法给EditorUtil对象添加方法,和写法三的区别在于写法四这样写会造成consturctor属性的改变

    constructor属性:始终指向创建当前对象的构造函数

    每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数。如下例所示:

    function Person(name) {  
        this.name = name;  
    };  
    Person.prototype.getName = function() {  
        return this.name;  
    };  
    var p = new Person("ZhangSan");  
     
    console.log(p.constructor === Person);  // true  
    console.log(Person.prototype.constructor === Person); // true  
    // 将上两行代码合并就得到如下结果  
    console.log(p.constructor.prototype.constructor === Person); // true

    当时当我们重新定义函数的prototype时(注意:和上例的区别,这里不是修改而是覆盖),constructor属性的行为就有点奇怪了,如下示例:

    为什么呢?

    原来是因为覆盖Person.prototype时,等价于进行如下代码操作:

    而constructor属性始终指向创建自身的构造函数,所以此时Person.prototype.constructor === Object,即是:

    怎么修正这种问题呢?方法也很简单,重新覆盖Person.prototype.constructor即可:

  • 相关阅读:
    Spark研究笔记7:重要的工厂类UserManager(原创) CVT
    Spark研究笔记9:重要的工厂类PresenceManager(原创) CVT
    Spark研究笔记11:实体类 CVT
    Spark研究笔记5:重要的工厂类NativeManager(原创) CVT
    Spark研究笔记8:重要的工厂类PluginManager(原创) CVT
    Spark研究笔记6:重要的工厂类SessionManager(原创) CVT
    Spark研究笔记12:监听类 CVT
    Spark研究笔记10:重要的工厂类SoundManager(原创) CVT
    声明和定义的区别
    LINQ查询操作符
  • 原文地址:https://www.cnblogs.com/tkzc2013/p/5443225.html
Copyright © 2011-2022 走看看