<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    silvermyth

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      1 隨筆 :: 12 文章 :: 1 評論 :: 0 Trackbacks
         先講一下背景,最近發(fā)現(xiàn)項(xiàng)目中有些js文件的規(guī)模越來越大,接近2000行,開始出現(xiàn)維護(hù)困難的苗頭;剛好實(shí)現(xiàn)的一個(gè)功能需要用到tree插件,在網(wǎng)上搜到一個(gè)bootstrap treeview插件可以用,但該插件無法支持懶加載和動(dòng)態(tài)添加功能,網(wǎng)上現(xiàn)有的擴(kuò)展方案都無法完全滿足我的要求。花了一些時(shí)間看了bootstrap treeview的代碼和Jquery插件的編寫方法,對其進(jìn)行了擴(kuò)展并在項(xiàng)目中實(shí)現(xiàn)了一個(gè)簡單的Select插件;另外計(jì)劃把項(xiàng)目中以前組件化的自定義UI控件也全部用Jquery插件實(shí)現(xiàn),以便復(fù)用并且清除冗余代碼,這一過程我會(huì)陸續(xù)發(fā)布出來,本篇主要以我的select插件為例講述如何才能編寫一個(gè)Jquery插件:
        要想編寫一個(gè)Jquery插件,首先必須對Jquery有所了解,尤其是以下幾個(gè)知識點(diǎn):
    •     知道(function($){...})(jQuery)是什么意思
      (function($){...})(jQuery)定義了一個(gè)函數(shù),并且以jQuery為參數(shù)進(jìn)行了調(diào)用,一般情況下,這是實(shí)現(xiàn)jQuery插件的標(biāo)準(zhǔn)姿勢,對這個(gè)有興趣的同學(xué)可以繼續(xù)深入研究。
    •     $.proxy(fun, context)
      該方法返回一個(gè)fun函數(shù)的代理,返回的代理函數(shù)功能和fun相同,不同的是返回函數(shù)使用context參數(shù)作為調(diào)用上下文。這段話有點(diǎn)繞口,不明白的同學(xué)請參考:
      http://www.cnblogs.com/hongchenok/p/3919497.html
    •     $.each(arr, function(){...})
      該方法在每個(gè)arr中的元素上執(zhí)行callback方法,存在很多變體。詳細(xì)請參見http://www.jb51.net/article/24581.htm
    •     $.extend(deep, obj, obj1, ..)
      Jquery提供的用來擴(kuò)展一個(gè)對象的方法,即將對象obj1合并到對象obj,一般被用來向jQuery對象中添加方法。詳細(xì)請參考http://www.cnblogs.com/tianguook/p/4084061.html
    •     $.data(dom, data-name, data-value)
      Jquery提供的用來綁定對象到dom對象中的方法,如果沒有定義data-value參數(shù),是讀取data-name的值;如果定義了data-value則是設(shè)置data-name的值。
          有了以上知識,我們來實(shí)現(xiàn)一個(gè)Select的Jquery插件,可以方便的創(chuàng)建、添加選項(xiàng)、刪除選項(xiàng)等等。代碼如下:
        /**
     * Created by gavinli on 17-3-30.
     
    */
    ;(function ($) {
        'use strict';

        var pluginName = 'myList';

        var _default = {};

        _default.settings = {};

        var MyList = function (element, options) {
            this.$element = $(element);
            this.init(options);
            return {
                init: $.proxy(this.init, this),
                add: $.proxy(this.add, this),
                remove: $.proxy(this.remove, this),
                list: $.proxy(this.list, this),
                clear: $.proxy(this.clear, this),
                getSelected: $.proxy(this.getSelected, this)
            }
        };

        MyList.prototype.init = function (options) {
            this.items = [];

            if (options.data) {
                if (typeof options.data === 'string') {
                    options.data = $.parseJSON(options.data);
                }
                this.items = $.extend(true, [], options.data);
                delete options.data;
            }
            this.options = $.extend({}, _default.settings, options);
            this.render();
            this.subscribeEvents();
        };

        MyList.prototype.subscribeEvents = function () {
            //TODO:
        };

        MyList.prototype.add = function (items) {
            if (!(items instanceof Array)) {
                items = [items];
            }
            var _this = this;
            $.each(items, function (i, value) {
                _this.items.push(value);
            });
            this.filterDup();
            this.render();
        }

        //Remove all duplicated items
        MyList.prototype.filterDup = function () {
            var _this = this;
            var values = {}
            $.each(_this.items, function (i, value) {
                if (values[value]) {
                    _this.items[i] = null;
                } else {
                    values[value] = true;
                }
            });
        }

        MyList.prototype.remove = function (items) {
            var _this = this;
            var toBeRemoved = {};
            $.each(items, function (i, value) {
                toBeRemoved[value] = true;
            });
            $.each(_this.items, function (i, value) {
                if (toBeRemoved[value] == true) {
                    _this.items[i] = null;
                }
            });
            this.render();
        }

        MyList.prototype.getSelected = function () {
            return this.$wrapper.val();
        }

        MyList.prototype.list = function (item) {
            var result = [];
            $.each(this.items, function (i, value) {
                if (value) {
                    result.push(value);
                }
            });
            return result;
        }

        //Clear all items
        MyList.prototype.clear = function () {
            delete this.items;
            this.items = [];
            this.render();
        }

        MyList.prototype.render = function () {
            if (!this.initialized) {
                this.$wrapper = $(this.template.list);
                this.initialized = true;
            }
            //Append select element to $element
            this.$element.empty().append(this.$wrapper.empty());

            //Build select options
            this.buildList(this.items);
        }

        MyList.prototype.buildList = function (items) {
            var _this = this;
            $.each(items, function (i, value) {
                if (value) {
                    var option = $(_this.template.item);
                    option.append(value);
                    _this.$wrapper.append(option);
                }
            });
        }

        MyList.prototype.template = {
            list: '<select multiple class="form-control"></select>',
            item: '<option></option>'
        };

        $.fn[pluginName] = function (options, args) {
            var result;
            this.each(function () {
                var _this = $.data(this, pluginName);
                if (typeof options === 'string') {
                    if (!_this) {
                        //logError('Not initialized, can not call method : ' + options);
                    }
                    else if (!$.isFunction(_this[options]) || options.charAt(0) === '_') {
                        //logError('No such method : ' + options);
                    }
                    else {
                        if (!(args instanceof Array)) {
                            args = [args];
                        }
                        result = _this[options].apply(_this, args);
                    }
                }
                else if (typeof options === 'boolean') {
                    result = _this;
                }
                else {
                    $.data(this, pluginName, new MyList(this, $.extend(true, {}, options)));
                }
            });
            return result || this;
        };

    })(jQuery);
        下面針對其中的關(guān)鍵方法進(jìn)行分析講解:
        MyList函數(shù):MyList對象的construnctor方法,接受options參數(shù)(options參數(shù)包含所有options的數(shù)組)
        MyList.prototype.init:根據(jù)options的data構(gòu)建并渲染Select控件
        MyList.prototype.add:添加option到Select中并渲染,其它remove,list,getSelected方法大家自行研究
        上面代碼中,最核心的部分在于如何將MyList對象和Dom元素結(jié)合、并且擴(kuò)展到Jquery中,具體參考如下注釋代碼:
        ////擴(kuò)展jQuery的prototype對象,這里的plugName等于myList,相當(dāng)于給jQuery對象添加了一個(gè)"myList"方法
        $.fn[pluginName] = function (options, args) { 
            var result;
            ////這里的this是一個(gè)jQuery對象
            this.each(function () {    
                //下面的this不是jQuery對象,而是jQuery對象中的Dom對象
                //從Dom對象中獲取"data-myList"屬性綁定的對象
                var _this = $.data(this, pluginName);
                //options是方法名,例如$('#list1').MyList('add',[]),這里的options等于'add'
                if (typeof options === 'string') {
                    if (!_this) {
                        //logError('Not initialized, can not call method : ' + options);
                    }
                    else if (!$.isFunction(_this[options]) || options.charAt(0) === '_') {
                        //logError('No such method : ' + options);
                    }
                    else {
                        if (!(args instanceof Array)) {
                            args = [args];
                        }
                        //調(diào)用MyList對象的方法
                        result = _this[options].apply(_this, args);
                    }
                }
                else if (typeof options === 'boolean') {
                    result = _this;
                }
                else {
                    //創(chuàng)建MyList對象并綁定到Dom對象的data-myList屬性
                    $.data(this, pluginName, new MyList(this, $.extend(true, {}, options)));
                }
            });
            return result || this;
        };
       如何使用該插件的方法如下所示:
        首先在html中定義一個(gè)<div id="list1"></div>,然后這樣使用它:
        //創(chuàng)建一個(gè)Select包含三個(gè)options
    $('#list1').MyList(['Tom','Mary','Alice']);
    //添加新的option
    $('#list1').MyList('add', [['James','Richard']]);
    //刪除option
    $('#list1').MyList('remove', [['Alice']]);
        最后我們可以在以上例子中發(fā)現(xiàn)創(chuàng)建jQuery插件的總體思路:
    •     自定義對象,對象中包含數(shù)據(jù)和jQuery對象本身
    •     定義對象的方法,并且根據(jù)對象中數(shù)據(jù)的變化渲染Dom對象(通過jQuery對象獲得Dom對象)
    •     將該自定義對象方法擴(kuò)展到j(luò)Query原型對象中
    •     創(chuàng)建自定義對象,并綁定到j(luò)Query中Dom對象的data屬性
        通過以上實(shí)現(xiàn),我們便可以像使用jQuery對象一樣的方式使用控件,屏蔽對Dom元素的操作,簡單又方便
    posted on 2017-04-05 17:35 Gavin Li 閱讀(129) 評論(0)  編輯  收藏 所屬分類: JavaScript

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产偷窥女洗浴在线观看亚洲| 全免费a级毛片免费看不卡| 7x7x7x免费在线观看| 99爱在线精品视频免费观看9| 三年片在线观看免费大全电影| 在线观看免费中文视频| 久久经典免费视频| 国产一级特黄高清免费大片| 伊人久久大香线蕉亚洲五月天| 亚洲国产一区二区a毛片| 亚洲永久在线观看| 窝窝影视午夜看片免费| 一区二区三区四区免费视频| 欧美男同gv免费网站观看| 免费大黄网站在线看| 亚洲大成色www永久网站| 精品日韩99亚洲的在线发布| 成人久久久观看免费毛片| 免费高清国产视频| 成人免费毛片观看| 亚洲一区二区三区影院| 亚洲国色天香视频| 日韩免费码中文在线观看| 99久久免费精品视频| 国产午夜免费秋霞影院| 亚洲s色大片在线观看| 亚洲日本一线产区和二线产区对比| 一级毛片aaaaaa视频免费看| 222www免费视频| 免费一级毛片在线播放| 亚洲无线电影官网| 国产精品亚洲综合网站| 免费精品无码AV片在线观看| 国产美女被遭强高潮免费网站| 久久亚洲伊人中字综合精品| 一本色道久久综合亚洲精品蜜桃冫| 男女一边摸一边做爽的免费视频| 成人黄18免费视频| 久久精品国产亚洲AV麻豆王友容| 亚洲丁香婷婷综合久久| 鲁大师在线影院免费观看|