将jquery插件配置存储在数据中是一个好习惯吗?

时间:2013-03-21 09:35:31

标签: javascript jquery plugins

我想用config创建jQuery插件(例如插件myplugin)。 比调用$(elem).myplugin(config);之后我想调用此插件中的方法,如已存储配置的$(elem).myplugin().method()

我的提议是这样的:

(function($) {
    $.fn.myplugin = function(options) { 
        var $this = $(this);

        var getOptions = function() {
            return $this.data('myplugin');
        };

        var initOptions = function(opt) {
            $this.data('myplugin', opt);
        };

        var setOption = function(key, value) {
            $this.data('myplugin')[key] = value;
        }

        var updateBorderWidth = function() {  
            $this.css('border-width', 
                      getOptions().borderWidth * getOptions().coeficient);
        };

        var init = function(opt) {
            initOptions(opt);
            updateBorderWidth();
        }        

        function changeBorder(width) {            
            setOption('borderWidth', width)
            updateBorderWidth();
        }

        if(options) {
            init(options);            
        }        

        return {
            changeBorder : changeBorder
        };
    }        
})(jQuery);

用法:

 $(function() {
     var item1 = $('#test1').myplugin({ coeficient: 1, borderWidth: 1 });
     var item1 = $('#test2').myplugin({ coeficient: 2, borderWidth: 1 });

     $('#btn').click(updateBorder);     
});

function updateBorder() {
    $('#test1').myplugin().changeBorder($('#inpt').val());
    $('#test2').myplugin().changeBorder($('#inpt').val());
}

示例:http://jsfiddle.net/inser/zQumX/4/

我的问题:做这件事是一种好习惯吗?

可能是不正确的做法。你能提供更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

通过数据属性将参数传递给javascript是一个很好的模式,因为它有效地解耦了Javascript代码和服务器端代码。它也不会对Javascript代码的可测试性产生负面影响,这是许多其他方法解决问题的副作用。

我甚至可以说这是服务器端代码与Web应用程序中的客户端代码进行通信的最佳方式。

答案 1 :(得分:2)

编辑:

jQuery plugin template上搜索线程后,我发现这些Boilerplate templates比我在下面提供的更多功能和广泛的设计。最终你选择的一切取决于你的需求。 Boilerplate模板涵盖了比我的产品更多的用例,但每个都有自己的好处和注意事项,具体取决于要求。


通常,jQuery插件在将值传递给它们时返回jQuery对象,如:

.wrap(html) // returns a jQuery object

或者在

中没有传递参数时返回值
.width() // returns a value

.height() // also returns a value

阅读你的示例调用约定:

  

$('#test1').myplugin().changeBorder($('#inpt').val());

对于任何使用jQuery的开发人员来说,似乎是两个单独的插件串联使用,首先.myplugin(),人们会假设将返回一个jQuery对象,并在{{1上执行一些默认的DOM操作然后跟着#test1,它也可能返回一个jQuery对象,但在你的例子中,整行没有分配给变量,所以不使用任何返回值 - 再次看起来像DOM操作。但是你的设计并没有遵循我所描述的标准调用约定,所以如果他们不熟悉你的插件,那么任何看你的代码的人都可能会感到困惑,知道它实际上做了什么。


过去,我曾经考虑过类似的问题和用例,并且我喜欢使用一个方便的约定来调用与插件相关的单独函数。选择完全取决于你 - 它是你的插件,你需要根据谁将使用它来决定,但我已经解决的方法是简单地传递函数的名称和它的参数作为一个单独的.changeBorder($('#inpt').val()).myplugin(name, parameters)中的对象。

我通常这样做:

.myplugin(object)

用法:

(function($) {
    $.fn.myplugin = function(fn, o) { // both fn and o are [optional]
        return this.each(function(){ // each() allows you to keep internal data separate for each DOM object that's being manipulated in case the jQuery object (from the original selector that generated this jQuery) is being referenced for later use
            var $this = $(this); // in case $this is referenced in the short cuts

            // short cut methods
            if(fn==="method1") {
                if ($this.data("method1"))  // if not initialized method invocation fails
                    $this.data("method1")() // the () invokes the method passing user options
            } else if(fn==="method2") {
                if ($this.data("method2"))
                    $this.data("method2")()
            } else if(fn==="method3") {
                if ($this.data("method3"))
                    $this.data("method3")(o) // passing the user options to the method
            } else if(fn==="destroy") {
                if ($this.data("destroy"))
                    $this.data("destroy")()
            }
            // continue with initial configuration

            var _data1,
                _data2,
                _default = { // contains all default parameters for any functions that may be called
                    param1: "value #1",
                    param2: "value #2",
                },
                _options = {
                    param1: (o===undefined) ? _default.param1 : (o.param1===undefined) ? _default.param1 : o.param1,
                    param2: (o===undefined) ? _default.param2 : (o.param2===undefined) ? _default.param2 : o.param2,

                }
                method1 = function(){
                    // do something that requires no parameters
                    return;
                },
                method2 = function(){
                    // do some other thing that requires no parameters
                    return;
                },
                method3 = function(){
                    // does something with param1
                    // _options can be reset from the user options parameter - (o) - from within any of these methods as is done above
                    return;
                },
                initialize = function(){
                    // may or may not use data1, data2, param1 and param2
                    $this
                        .data("method1", method1)
                        .data("method2", method2)
                        .data("method3", method3)
                        .data("destroy", destroy);
                },
                destroy = function(){
                    // be sure to unbind any events that were bound in initialize(), then:
                    $this
                        .removeData("method1", method1)
                        .removeData("method2", method2)
                        .removeData("method3", method3)
                        .removeData("destroy", destroy);
                }
            initialize();
        }) // end of each()
    } // end of function        
})(jQuery);

或者你可以说:

var $test = $('#test').myplugin(false, {param1: 'first value', param2: 'second value'}); // initializes the object
$test.myplugin('method3', {param1: 'some new value', param2: 'second new value'}); // change some values (method invocation with params)