2009-10-08 39 views
25

Làm cách nào để tạo plugin jQuery để tôi có thể sử dụng không gian tên trong plugin của mình?Không gian tên Plugin jQuery

$("#id1").amtec.foo1(); 
$("#id1").amtec.foo2(); 

Không có cách nào trong số này có hiệu quả.

(function($) { 
    var amtec = { 
     $.fn.foo1 : function(){ return this.each(function(){}); }, 
     $.fn.foo2 : function(){ return this.each(function(){}); } 
     }; 

    })(jQuery); 
(function($) { 
    $.fn.amtec = function(){ 
     var foo1 = function(){ return this.each(function(){}); }; 
     var foo2 = function(){ return this.each(function(){}); }; 
     } 
    })(jQuery); 
+0

bạn vui lòng xem giải pháp của mình. nó chính xác hơn với những gì bạn đang cố gắng đạt được. –

Trả lời

21
(function($) { 
    $.fn.amtec = function() { 
     var jq = this; 
     return { 
      foo1: function(){ 
       return jq.each(function(){}); 
      }, 

      foo2: function(){ 
       return jq.each(function(){}); 
      } 
     } 
    }; 
})(jQuery); 
+0

Alexander, bảng điều khiển lỗi trong FireBug cho thấy: this.each không phải là một chức năng – MotionGrafika

+0

Tôi đoán tôi đã làm rối tung mọi thứ - Tôi đã cập nhật câu trả lời của mình. –

+4

Cảm ơn rất nhiều Alexandar! Nó hoạt động nhưng là $ ("# id1"). Amtec(). Foo1(); và không phải là $ ("# id1"). Amtec.foo2(); – MotionGrafika

3
(function($){ 
    $.namespace = function(ns, functions){ 
    $.fn[ns] = function() {return this.extend(functions)}; 
    }; 
    $.namespace('$', $.fn); // the default namespace 
})(jQuery); 

Vì vậy, bây giờ bạn có thể có một plugin:

$.fn.func = function(){alert('plugin'); return this'}; 

và tạo plugins trong một không gian tên:

$.namespace ('mynamespace', { 
    func: function() {alert('namespaced plugin'); return this;}, 
    otherfunc: function() {return this.css('color', 'yellow');} 
}); 

Và nếu bạn làm

$('div').func(); // alerts 'plugin' -- no namespace 

Nhưng

$('div').mynamespace().func(); // alerts 'namespaced plugin' 

$('div').mynamespace().func().$().func(); // alerts 'namespaced 

Plugin', sau đó reset đến jquery bình thường và cảnh báo 'cắm'

+1

Để gọi khácFunc nó sẽ jsut được $ (div) .mynamespace.otherFunc(); ? – Chris

+1

Hãy cẩn thận với điều này. Câu trả lời thông minh nhưng cư xử giống như [Decorator Pattern] (http://en.wikipedia.org/wiki/Decorator_pattern) hơn là không gian tên. Điều đó có thể khiến bạn gặp rắc rối nếu bạn không quen với những ưu điểm và nhược điểm thông thường của mẫu đó. – colllin

2

Tôi biết đó là một câu hỏi cũ ... Nhưng tại sao viết tất cả mã phụ này khi bạn chỉ có thể thay thế . bằng _?

$.fn.amtec_foo1 = function(){ return this.each(function(){}); } 
$.fn.amtec_foo2 = function(){ return this.each(function(){}); } 

Tốt hơn, hãy đặt tên cho plugin của bạn là tên gốc & dự báo bất khả tri.

$.fn.fooize = function(){ return this.html('Element has been Fooized!'); } 
+0

Điều đó ngăn cách không gian tên và không nhìn tốt. – WhyNotHugo

+0

làm mới thực dụng. cảm ơn! – colllin

12

Tôi biết tôi đã trễ gần ba năm, nhưng hy vọng các độc giả tương lai của câu hỏi này có thể hưởng lợi từ câu trả lời của tôi. Câu trả lời của GSto trông tuyệt vời từ quan điểm thiết kế plugin jQuery, nhưng có một vấn đề nhỏ: gọi mynamespace() ghi đè trường hợp jQuery đã trả về bằng các phương thức mới. Dưới đây là một ví dụ về điều đó trở thành một vấn đề:

$myDiv = $('.mydiv'); 
$myDiv.mynamespace().height(); // this will be `height' from mynamespace 
$myDiv.height();    // this will STILL be `height' from mynamespace 
           // because it has overwritten $myDiv.height 

Câu trả lời được lựa chọn không có vấn đề này bởi vì có amtec() không phải là một trường hợp jQuery và là thay vì một đối tượng mà các cuộc gọi phương thức của nó với các trường hợp jQuery như bối cảnh. Tôi đã lấy khái niệm của cả hai câu trả lời và viết các plugin không gian tên dưới đây:

(function($) { 
    $.namespace = function(namespaceName, closures) { 

    if ($.fn[namespaceName] === undefined) { 
     $.fn[namespaceName] = function executor(context) { 
     if (this instanceof executor) { 
      this.__context__ = context; 
     } 
     else { 
      return new executor(this); 
     } 
     }; 
    } 

    $.each(closures, function(closureName, closure) { 
     $.fn[namespaceName].prototype[closureName] = function() { 
     return closure.apply(this.__context__, arguments); 
     }; 
    }); 

    }; 
})(jQuery); 

Ví dụ sử dụng:

$.namespace('milosz', { 
    redify: function() { 
     $(this).css('color', '#ff0000'); 
    }, 
    greenify: function() { 
     $(this).css('color', '#00ff00'); 
    } 
}); 

$.namespace('milosz', { 
    blueify: function() { 
     $(this).css('color', '#0000ff'); 
    } 
}); 

$('.mydiv').milosz().redify(); // The HTML elements with class `mydiv' are now red 

Mã này sử dụng một số chi tiết ở mức độ thấp khá JavaScript đều được giải thích bởi John Resig's Advanced JavaScript tutorial, nhưng nói một cách lỏng lẻo những gì đang xảy ra trong ví dụ này là:

Khi milosz (nội bộ $.fn[namespaceName]) được gọi, this trỏ đến trường hợp jQuery được trả về b y $('.mydiv').Do đó, câu lệnh if rơi qua khối else và phiên bản hàm xây dựng của milosz được gọi (được gọi nội bộ là executor vì các lý do sắp trở nên rõ ràng). Hàm khởi tạo được chuyển một tham số duy nhất: this, một con trỏ đến jQuery trường hợp sẽ là ngữ cảnh thực thi cho tất cả các thành viên của không gian tên milosz. Chúng ta nhập trở lại câu lệnh if, lần này thực hiện khối đầu tiên, trong đó phiên bản jQuery được chuyển vào được lưu trữ trong biến thành viên được gọi là __context__ (hy vọng có khả năng bị ghi đè thấp). Đối tượng được xây dựng được trả lại, hoàn chỉnh với tham chiếu đến phiên bản gốc jQuery và bất kỳ trình bao bọc nào được thêm vào mẫu thử nghiệm của nó bằng cách gọi số $.namespace. Những trình bao bọc này chỉ thực hiện các phương thức được truyền vào không gian tên milosz với đối tượng jQuery gốc dưới dạng ngữ cảnh, như xảy ra khi redify được thực hiện.

Bah, tôi biết nó là một ngụm, dù sao vấn đề là nó hoạt động giống như câu trả lời được chấp nhận nhưng trông giống như câu trả lời jQueryish, mà với tôi là tốt nhất của cả hai thế giới.

+1

Cách tiếp cận tuyệt vời, cảm ơn từ một năm sau, ba năm sau bữa tiệc. – cmsjr

+1

Tôi sẽ sử dụng kỹ thuật này trong thư viện nhà máy sản xuất plugin jQuery mới của tôi. Làm cho đầu tôi đau, nhưng nó hoạt động! –

+0

Tôi biết nó đã được một thời gian, nhưng phương pháp này không cho phép tôi gọi một hàm là $ .myNamespace(). Function() - nhưng nó hoạt động như $(). MyNamespace(). Function() - ai cũng có một giải pháp cho điều này? –

1
$.cg = { 
    foo1: function(weq){ 
     return console.log(weq); 
    }, 
    foo2: function(rw){ 
     return console.log(rw); 
} 
}; 
$.cg = { // will result in error because $.cg is already declared above 

    foo4: function(rw){ // will result in error 
     return console.log(rw); // will result in error 
} // will result in error 
}; // will result in error 

$.cg.foo3 = function(weq){ //to add anything new to $.cg , you have to do it this way. 
     return console.log(weq); 
    } 

$.cg.foo1("12"); 
$.cg.foo2("22"); //works fine. 
$.cg.foo3("112"); //works fine. 
+0

Vấn đề với điều này là các hàm sẽ không nhận được bộ chọn jQuery bên trong ngữ cảnh 'this' này. –

Các vấn đề liên quan