jQuery插件扩展

2019-04-10  本文已影响0人  小丘啦啦啦

一、jQuery的扩展性
jQuery,除了对JavaScript进行封装让写法、功能实现更简单,特别是选择器抓取DOM元素(虽然有了vue等插件会减少操作dom的需求)和ajax调用;而且,它的可扩展性也是受众多开发者青睐的,从而可以建立起自己公司的生态系统。
二、扩展方式
1、通过$.extend()扩展
仅仅是在jQuery命名空间或者说是jQuery身上添加了一个静态方法而已。
通过调用$.extend()添加的函数直接通过$符号调用($.func()),不需要抓取DOM元素($('#id').func())。

<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <script>
            $.extend({
                sayHello(name){
                    console.log(`Hello ${name}`);
                }
            });
            $.sayHello('qiurx');   //Hello qiurx
        </script>
    </body>
</html>

这种方法可以简单的添加一个jQuery插件,通常用来定义一些辅助方法,例如console.log打印自定义日志。用另一种写法:

<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <script>
            $.logDate = function(msg){
                var now = new Date();
                var y = now.getFullYear();
                var m = now.getMonth()*1+1;
                var d = now.getDate();
                var hh = now.getHours();
                var mm = now.getMinutes();
                var ss = now.getSeconds();
                console.log(`${y}-${m}-${d} ${hh}:${mm}:${ss}————${msg}`);
            }
            $.logDate('异步调用开始');   //2019-4-8 19:46:8————异步调用开始
        </script>
    </body>
</html>

但这种方法无法利用jQuery强大的选择器带来的便利。
2、通过$.fn扩展
jQuery扩展最常用的一种方法。
$.fn的插件执行函数中,this指向jQuery选择器选中的元素,是一个jQuery类型的集合。集合已经是jQuery包装类型了,可以直接调用jQuery的其他方法,也不需要用$重新包装了。

<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <a href="http://baidu.com">百度</a>
        <script>
            $.fn.colorRed = function(){
                this.css('color','red');
            }
            $('a').colorRed();   //此插件内部的this即为$('a')
        </script>
    </body>
</html>

$.fn添加的插件内部this指向jQuery选择器返回的集合,可以通过$.each()操作集合中的每个元素。注意,$.each()方法内部,this指向集合中的每个元素,是普通的DOM元素,这时候要调用jQuery的方法需要用$重新包装下。
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <li><a href="http://baidu.com">百度</a></li>
        <li><a href="https://www.json.cn/">JSON解析</a></li>
        <script>
            $.fn.showHref = function(){
                this.each(function(){
                    //此处this指向每个普通的DOM元素,要重新$获取
                    $(this).append($(this).attr('href'));   
                });
            }
            $('a').showHref();   
        </script>
    </body>
</html>

3、通过$.widget()应用jQuery UI的部件工厂方式创建扩展
略。
三、$.fn的链式调用
jQuery一个很好的地方就是支持链式调用,选择器抓取DOM元素后可以不断的调用其他方法。要让插件支持这种调用,只需要return一下。
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <li><a href="http://baidu.com">百度</a></li>
        <li><a href="https://www.json.cn/">JSON解析</a></li>
        <script>
            $.fn.colorRed = function(opt) {
                var defaults = {
                    'color' : 'red',
                    'fontSize' : '12px'
                }
                $.extend(defaults,opt);   //让插件接收参数,有则合并取参数内容,没有则用默认值
                return this.css(defaults);
            }
            $.fn.showHref = function() {
                this.each(function() {
                    $(this).append($(this).attr('href'));
                });
                return this;
            }
            $('a').colorRed({'color':'blue'}).showHref();
        </script>
    </body>
</html>

四、面向对象思维开发插件
首先为什么要有面向对象思维。需要一个方法,就去定义一个function;需要一个变量,就随意在代码各处定义全局变量。这种做法不方便维护,也不清晰,虽然在代码规模小的时候体现不明显。
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <li><a href="http://baidu.com">百度</a></li>
        <li><a href="https://www.json.cn/">JSON解析</a></li>
        <script>
            var Beautiful = function(ele, opt) { //定义一个专门用来美化的类(构造函数)
                this.$ele = ele;
                var defaults = {
                    'color': 'red',
                    'fontSize': '12px',
                    'textDecoration': 'none'
                }
                this.options = $.extend({}, defaults, opt);
            }
            Beautiful.prototype = {   //定义原型方法
                beautify(){
                    return this.$ele.css({
                        'color': this.options.color,
                        'fontSize': this.options.fontSize,
                        'textDecoration': this.options.textDecoration
                    });
                }
            }
            $.fn.myPlugin = function(opt) {   //定义一个插件
                var beautifier = new Beautiful(this,opt);   //调用构造函数创建对象
                return beautifier.beautify();   //调用对象方法
            }
            $('a').myPlugin({
                'color': 'yellow',
                'fontSize': '20px',
            });
        </script>
    </body>
</html>

像这样改造,以后需要新属性方法时就直往构造函数添加,然后在插件里实例化后调用。
五、自调用匿名函数包裹代码
为了避免污染全局命名空间,不到万不得已尽量不把变量定义成全局的;还有一个方法,用自调用匿名函数包裹代码,这样可以安全的用于任何地方,绝对不会冲突。
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <li><a href="http://baidu.com">百度</a></li>
        <li><a href="https://www.json.cn/">JSON解析</a></li>
        <script>
            //避免前面的代码没有加(;)结尾,与自调用匿名函数相连报错
            ;(function (){   //定义一个匿名函数
                    var Beautiful = function(ele, opt) { //定义一个专门用来美化的类(构造函数)
                    this.$ele = ele;
                    var defaults = {
                        'color': 'red',
                        'fontSize': '12px',
                        'textDecoration': 'none'
                    }
                    this.options = $.extend({}, defaults, opt);
                }
                Beautiful.prototype = {   //定义原型方法
                    beautify(){
                        return this.$ele.css({
                            'color': this.options.color,
                            'fontSize': this.options.fontSize,
                            'textDecoration': this.options.textDecoration
                        });
                    }
                }
                $.fn.myPlugin = function(opt) {   //定义一个插件
                    var beautifier = new Beautiful(this,opt);   //调用构造函数创建对象
                    return beautifier.beautify();   //调用对象方法
                }
            }   
            )();   //定义函数后自调用
            $('a').myPlugin({
                'color': 'yellow',
                'fontSize': '20px',
            });
        </script>
    </body>
</html>

自调用匿名函数中的代码会在第一时间执行。
六、良好习惯
1、习惯性在代码开头加上分号(;),避免前面的代码没以分号结尾导致代码运行报错。

<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script typet="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <script>
            var foo = function() {
                //别人的代码
            } //注意这里没有用分号结尾

            //开始我们的代码。。。
            (function() {    
                alert('Hello!');
            })();
        </script>
    </body>
</html>

匿名函数的第一个括号与前面别人的函数相连导致了报错,所以习惯性在我们的代码前面加个分号。

;(function(){
    //我们的代码。。
    alert('Hello!');
})();

2、将系统变量以参数形式传递到插件内部也是个不错的实践。
window等系统变量在插件内部就有了一个局部的引用,可以提高访问速度,会有些许性能的提升。

;(function($,window,document,undefined){
    //我们的代码。。
    //blah blah blah...
})(jQuery,window,document);

至于这个undefined参数,为了得到没有被修改的undefined,我们并没有传递这个参数,但却在接收时接收了它,因为实际并没有传,所以‘undefined’那个位置接收到的就是真实的'undefined'了。

上一篇下一篇

猜你喜欢

热点阅读