2012-01-06 16 views
33

Tôi đã tạo một ứng dụng javascript với tất cả mã trong một tệp. Ứng dụng đã phát triển khá nhiều và tôi nghĩ đã đến lúc chia nhỏ thành nhiều tệp, nhưng tôi đang gặp khó khăn trong việc tìm ra cách để thực hiện điều này. Tôi nghĩ vấn đề nằm với cách tôi đã quyết định xây dựng các ứng dụng, trong đó sử dụng các mẫu sau:Làm cách nào để có thể chia ứng dụng javascript thành nhiều tệp?

var myApp = function(){ 

    //there are several global variables that all of the modules use; 
    var global1, global2, module1, module2; 

    global1 = { 
     prop1:1 
    }; 

    //There are also several functions that are shared between modules 
    function globalFunction(){ 

    } 

    var ModuleOne = function(){ 

     function doSomething(){ 
      //using the global function 
      globalFunction(); 
     } 

     return{ 
      doSomething:doSomething 
     } 
    }; 

    var ModuleTwo = function(){ 

     function doSomething(){ 
      //module 2 also needs the global function 
      globalFunction(); 

      //Use the functionality in module 1 
      //I can refactor this part to be loosely coupled/event driven 
      module1.doSomething(); 
     } 
    }; 

    module1 = new ModuleOne(); 
    module2 = new ModuleTwo(); 
}; 

Ngay cả khi tất cả các module được lỏng lẻo và sự kiện điều khiển, tôi vẫn không biết làm thế nào tôi sẽ đi về việc chia nhỏ nó thành nhiều tệp tin dựa trên sự phụ thuộc của mỗi module vào các hàm/biến được chia sẻ. Có ai có đề xuất?

+0

Nghiêm túc, các công cụ như [module8] (https://github.com/clux/modul8) giải quyết vấn đề của bạn – Raynos

+0

Hãy xem mẫu thiết kế trong bài viết này: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In- Độ sâu - bạn có thể tách định nghĩa mô-đun của bạn trên nhiều tệp theo cách cho phép chia sẻ các thuộc tính chung nhưng cũng cho phép bạn tạo các biến hoặc phương thức riêng tư chỉ với một tệp cụ thể. – nnnnnn

+0

@nnnnnn Cảm ơn. Tôi sẽ kiểm tra nó ngay bây giờ. –

Trả lời

34

Hãy nhìn vào các mẫu thiết kế trong bài viết này: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth - bạn có thể chia nhỏ định nghĩa module của bạn trên nhiều tập tin trong một đường cho phép các thuộc tính phổ biến được chia sẻ nhưng cũng cho phép bạn tạo các biến hoặc các phương thức riêng tư chỉ với một tệp cụ thể.

Ý tưởng cơ bản là các tập tin JS cá nhân bổ sung vào mô-đun cùng với mã như thế này:

var MODULE = (function (my) { 
    var privateToThisFile = "something"; 

    // add capabilities... 

    my.publicProperty = "something"; 

    return my; 
}(MODULE || {})); 

ở đâu trong mỗi tập tin JS nếu MODULE đã được xác định (từ tập tin JS khác) bạn thêm vào nó bằng không bạn tạo ra nó. Bạn có thể thiết lập để nó (chủ yếu) không quan trọng thứ tự các tập tin khác nhau được bao gồm trong.

Bài viết chi tiết một số biến thể, và tất nhiên bạn có thể sẽ đưa ra các tinh chỉnh của riêng bạn ...

1

Cung cấp cho require.js một shot. http://requirejs.org/

Ví dụ:

require(["dir/file"], function() { 
    // Called when file.js loads 
}); 
+0

Có, tôi đã xem xét, nhưng tôi vẫn không biết làm cách nào để giải quyết vấn đề với các chức năng được chia sẻ ... –

+0

Nhưng làm cách nào để chia nhỏ những gì hiện tại là một tệp lớn của mã phụ thuộc lẫn nhau? – nnnnnn

+0

Bạn tạo một tệp cho mỗi lớp (Do đó thẻ OOP) và tập lệnh chạy đơn giản kéo các lớp đó để sử dụng. Nếu bạn chỉ cho tôi mã, tôi có thể giúp bạn phân phối nó trên các tệp. –

2

Bạn có thể đặt các chức năng chia sẻ và các module được chia sẻ trên các đối tượng MyApp để họ không làm ô nhiễm không gian tên toàn cầu, nhưng có thể được truy cập bất cứ nơi nào mà không bị bên trong đóng cửa tương tự.

myApp.moduleOne = function() {...} 
myApp.moduleTwo = function() {...} 
myApp.globalFunction = function() {...} 

Sau đó, bạn có thể xác định chúng trong bất kỳ tệp nào và sử dụng chúng trong bất kỳ tệp nào.

Bạn cũng có thể chỉ chia nhỏ tệp thành nhiều tệp, nhưng yêu cầu chúng được bao gồm theo thứ tự cụ thể để duy trì đóng cửa của bạn. Nếu bạn chia nhỏ các tệp vì lý do chỉnh sửa thực tế, nhưng kết hợp lại và thu nhỏ chúng để triển khai thực tế thì điều này sẽ không làm bạn mất bất kỳ thứ gì về cách viết mã hoặc cách triển khai, nhưng sẽ cung cấp cho bạn nhiều tệp nhỏ hơn để chỉnh sửa tiện lợi.

+0

myApp không phải là tên thật, tôi chỉ sử dụng nó cho ví dụ. Với gợi ý của bạn, tôi sẽ cần phải thay đổi từng cuộc gọi đến globalFunction thành myApp.globalFunction() đúng không? –

+0

@MarkBrown - chính xác. Đó là một chút ít mong muốn khi viết mã, nhưng mang lại cho bạn sự linh hoạt hơn để phân đoạn mã của bạn thành các tệp hoàn toàn riêng biệt có thể độc lập hơn nhiều. Tôi cũng đã thêm một tùy chọn khác vào câu trả lời của mình. – jfriend00

0

Giải pháp yêu thích của tôi là sử dụng kịch bản lệnh phía máy chủ để bao gồm các tệp khác bên trong tệp "chính" của tôi. Ví dụ, sử dụng Template Toolkit Perl:

var myApp = function(){ 
    [% INCLUDE lib/module1.js %] 
    [% INCLUDE lib/module2.js %] 
    [% INCLUDE lib/module3.js %] 
} 

Hoặc PHP:

var myApp = function(){ 
    <?php 
    include 'lib/module1.js'; 
    include 'lib/module2.js'; 
    ?> 
} 
+1

Đó là động xây dựng javascript. Điều này nên tránh để ủng hộ việc biên dịch tĩnh thay vì bao gồm động. – Raynos

+0

Cả TT và PHP đều có thể chạy từ bảng điều khiển để bạn có thể dễ dàng viết kịch bản xây dựng nếu bạn muốn biên dịch tĩnh. Oh, cộng với TT có thể được cấu hình để lưu trữ các tập tin bộ nhớ cache để biên dịch chỉ cần xảy ra một lần. – slebetman

4

không để thêm vào sự nhầm lẫn, nhưng đến từ một nền C++, tôi đã cố gắng để xây dựng một cái gì đó giống như một cái gì đó giống như một C++ namespace theo cách mô tả dưới đây. nó hoạt động, nhưng tôi muốn biết nếu điều này là một mô hình được chấp nhận cho OP?

-------------------------------- tập tin chính.js: ----------------

var namespacename = function(){} 

namespacename.mainvalue = 5; 

namespacename.maintest = function() { 
    var cm = new namespacename.game(); 
    cm.callme(); 
} 

------------------------- ------- tệp game.js: ----------------

namespacename.gamevalue = 15; 

namespacename.game = function(){ 
    this.callme = function(){ 
     console.log("callme"); 
    } 
} 

namespacename.gametest = function() { 
    console.log("gametest:gamevalue:" + this.gamevalue); 
    console.log("gametest:mainvalue:" + this.mainvalue); 
} 

--------------- ----------------- tệp index.html: --------------

<html> 
    <head> 
     <title>testbed</title> 
    </head> 

    <body onload="init();"> 
    </body> 

    <script type="text/javascript" src="main.js"></script> 
    <script type="text/javascript" src="game.js"></script> 

    <script type="text/javascript"> 

     init = function() 
     { 
      namespacename.maintest(); 
      namespacename.gametest(); 

      console.log("html main:" + namespacename.mainvalue); 
      console.log("html game:" + namespacename.gamevalue); 
     } 

    </script> 
</html> 
+4

Tại sao khai báo _namespacename_ là một hàm trống không bao giờ được gọi? Bạn có thể khai báo nó như một đối tượng rỗng với _var namespacename = {} _ và phần còn lại của mã của bạn sẽ không cần thay đổi. – nnnnnn

+0

Giải pháp này phù hợp với tôi! –

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