代码之家  ›  专栏  ›  技术社区  ›  Rob

Creating methods on the fly

  •  10
  • Rob  · 技术社区  · 14 年前

    嗨,我正在尝试编写一个jquery插件,我需要在将元素初始化为此类对象之后,让它们可以访问这些方法,例如:

    $('.list').list({some options}); //This initializes .list as a list
    
    //now I want it to have certain methods like:
    $('.list').find('List item'); //does some logic that I need
    

    我尝试过

    $.fn.list = function (options) {
        return this.each(function() {
            // some code here
            this.find = function(test) {
                //function logic
            }
        }
    }
    

    and several other different attempts, I just can't figure out how to do it.

    编辑:

    我会更好地解释这个。

    我试图把一张表转换成一个列表,基本上就像计算机上的一个列表,其中有列标题、可排序的项目以及其中的所有内容。您可以使用如下命令初始化表

    $(this).list({
        data: [{id: 1, name:'My First List Item', date:'2010/06/26'}, {id:2, name:'Second', date:'2010/05/20'}]
    });
    

    .list 将使 <tbody> sortable and do a few other initial tasks, then add the following methods to the element:
    .findItem(condition) 将允许您按条件查找某个项目(如 findItem('name == "Second"')
    .list(condition) will list all items that match a given condition
    .sort(key) will sort all items by a given key
    等。

    What's the best way to go about doing this?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Anurag    14 年前

    如果希望这些方法在任何jquery对象上都可用,则必须将它们中的每一个都添加到jquery的原型中。原因是每次你打电话 $(".list") 创建一个新的新对象,并且您连接到以前的对象的任何方法都将丢失。

    将每个方法分配给jquery的原型,如下所示:

    jQuery.fn.extend({
        list: function() { .. },
        findItem: function() { .. },
        sort: function() { .. }
    });
    

    这个 list 这里的方法是特殊的,因为它可以在两种情况下调用。第一,初始化列表时,第二,通过条件查找特定项时。您必须以某种方式区分这两种情况——要么按参数类型,要么按其他参数。

    您也可以使用 data 如果为尚未用列表插件初始化的对象调用这些方法,则将引发异常的API。什么时候? ('xyz').list({ .. }) 首先,在该对象的数据缓存中存储一些状态变量。稍后调用任何其他方法-“list”、“finditem”或“sort”时,请检查对象在其数据缓存中是否包含该状态变量。

    一个更好的方法是你的插件的命名空间 list() 将返回扩展对象。可以对其返回值调用三个扩展方法。接口如下:

    $('selector').list({ ... });
    $('selector').list().findOne(..);
    $('selector').list().findAll(..);
    $('selector').list().sort();
    

    Or save a reference to the returned object the first time, and call methods on it directly.

    var myList = $('selector').list({ ... });
    myList.findOne(..);
    myList.findAll(..);
    myList.sort();
    
        2
  •  2
  •   Rob    14 年前

    I found this solution here: http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html

    This seems to do exactly what I need.

    (function($) {
        var TaskList = function(element, options)
        {
            var $elem = $(element);
            var options = $.extend({
                tasks: [],
                folders: []
            }, options || {});
    
            this.changed = false;
            this.selected = {};
    
            $elem.sortable({
                revert: true,
                opacity: 0.5
            });
    
            this.findTask = function(test, look) {
                var results = [];
    
                for (var i = 0,l = options.tasks.length; i < l; i++)
                {
                    var t = options['tasks'][i];
                    if (eval(test))
                    {
                        results.push(options.tasks[i]);
                    }
                }
                return results;
            }
    
            var debug = function(msg) {
                if (window.console) {
                    console.log(msg);
                }
            }
        }
    
        $.fn.taskList = function(options)
        {
            return this.each(function() {
                var element = $(this);
    
                if (element.data('taskList')) { return; }
    
                var taskList = new TaskList(this, options);
    
                element.data('taskList', taskList);
    
            });
        }
    
    })(jQuery);
    

    然后我有

        $('.task-list-table').taskList({
            tasks: eval('(<?php echo mysql_real_escape_string(json_encode($tasks)); ?>)'),
            folders: eval('(<?php echo mysql_real_escape_string(json_encode($folders)); ?>)')
        });
        var taskList = $('.task-list-table').data('taskList');
    

    我可以用 taskList.findTask(condition);

    由于构造函数 $elem I can also edit the jQuery instance for methods like list(condition) 这是完美的。

        3
  •  0
  •   James    14 年前

    this.each 不需要。应该这样做:

    $.fn.list = function (options) {
        this.find = function(test) {
            //function logic
        };
        return this;
    };
    

    注意,您将重写jQuery的本机。 find method, and doing so isn't recommended.


    而且,就其价值而言,我认为这不是一个好主意。jQuery instances are assumed to only have methods inherited from jQuery's prototype object, and as such I feel what you want to do would not be consistent with the generally accepted jQuery-plugin behaviour -- i.e. return the this object (the jQuery instance) unchanged.