【问题标题】:Is it a good practice to store jquery plugin configuration in data?将 jquery 插件配置存储在数据中是一种好习惯吗?
【发布时间】:2013-03-21 09:35:30
【问题描述】:

我想创建带有配置的 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/

我的问题:这样做是个好习惯吗?

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

【问题讨论】:

    标签: javascript jquery plugins


    【解决方案1】:

    编辑:

    在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 对象,并在 #test1 上执行一些默认的 DOM 操作,然后接下来是.changeBorder($('#inpt').val()),它也可能返回一个 jQuery 对象,但在您的示例中,整行没有分配给变量,因此不使用任何返回值 - 再次看起来像 DOM 操作。但是您的设计不遵循我所描述的标准调用约定,因此如果不熟悉您的插件,任何查看您的代码的人可能会对代码的实际作用感到困惑。


    过去,我考虑过与您描述的问题和用例类似的问题和用例,我喜欢有一个方便的约定来调用与插件关联的单独函数的想法。选择完全取决于你——它是你的插件,你需要根据谁将使用它来决定,但我决定的方式是简单地传递函数的名称和它的参数作为单独的.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)
    

    或者你可以说:

    $('#test').myplugin(); // assume defaults and initialize the selector
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2020-09-10
        • 1970-01-01
        • 2021-08-17
        • 2011-07-17
        • 2019-06-29
        • 2018-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多