2012-02-15 25 views
32

Kiedy tworzę nowy plik coffeescript, nie mogę uzyskać dostępu do kodu w skompilowanym kodzie z innego pliku, ponieważ jest on zawijany w pewnym zakresie funkcji. Na przykład:Komunikacja wielu plików z coffeescript

coffeescript:

class ChatService 
    constructor: (@io) -> 

Generated javascript:

(function() { 
    var ChatService;  
    ChatService = (function() {  
    function ChatService(io) { 
     this.io = io; 
    }  
    return ChatService;  
    })();  
}).call(this); 

podczas próby wywołania ChatService w innym pliku, to nie jest zdefiniowane. Jak obsługiwać wiele plików za pomocą coffeescript?

+0

Jeśli używasz Railsów, musisz upewnić się, że jakikolwiek zależny plik coffeescript jest wywoływany * przed * spróbujesz i odwołać się do niego. Po ustawieniu dyrektyw "wymagaj" w plikach, które faktycznie potrzebują innych, uzyskasz dostęp do zmiennych itp. –

Odpowiedz

56

W zależności od tego, czy jest to kod klienta, czy po stronie serwera, istnieją dwa nieco inne podejścia.

po stronie klienta: Tutaj przywiązujemy rzeczy, które powinny być dostępne w plikach do globalnej przestrzeni nazw (window) w następujący sposób:

class window.ChatService 
    constructor: (@io) -> 

Następnie w innym pliku zarówno ChatService i window.ChatService umożliwi dostęp do klasy .


po stronie serwera: Tutaj musimy użyć exports i require. W pliku ChatService.coffee, trzeba wykonać następujące czynności:

class exports.ChatService 
    constructor: (@io) -> 

Następnie, aby dostać się na nią z innego pliku można użyć:

ChatService = require('ChatService.coffee').ChatService 

Uwaga: Jeśli istnieje wiele klas, które otrzymujesz od ChatService.coffee, to jest jedno miejsce, gdzie DICT coffeescript za rozpakowywanie naprawdę błyszczy, takich jak:

{ChatService, OtherService} = require('ChatService.coffee') 

Obie: Zasadniczo, decydujemy, czy uruchomić kod po stronie serwera, czy po stronie klienta, w zależności od tego, w którym środowisku się znajdujemy.Powszechnym sposobem, aby to zrobić:

class ChatService 
    constructor: (@io) -> 

if typeof module != "undefined" && module.exports 
    #On a server 
    exports.ChatService = ChatService 
else 
    #On a client 
    window.ChatService = ChatService 

Aby go:

if typeof module != "undefined" && module.exports 
    #On a server 
    ChatService = require("ChatService.coffee").ChatService 
else 
    #On a client 
    ChatService = window.ChatService 

Klauzula else drugiego bloku może zostać pominięta, ponieważ ChatService już odnosi się do odniesienia dołączonym do window.

Jeśli masz zamiar zdefiniować wiele klas w tym pliku, może łatwiej będzie je zdefiniować następująco:

self = {} 

class self.ChatService 

a następnie dołączyć je jak module.exports = self na serwerze i na kliencie _.extend(window, self) (zamień _.extend z inną funkcją extend, stosownie do potrzeb).

+1

+1 dla strony rzeczy node.js. –

+2

Dzięki za podanie zarówno metody node.js, jak i po stronie klienta, potrzebowałem obu. –

+0

Podobnie jak w przypadku odpowiedzi "mu jest za krótka", możliwe jest również wywołanie funkcji exports.App.ClassName. Domyślam się, że możesz nazwać część App tego "obszaru nazw". Proszę popraw mnie jeżeli się mylę. – Chris

23

Zwykle podejście jest zdefiniowanie nazw globalnych w window:

window.App = { } 

To pójdzie gdzieś w kodzie inicjującym swojej aplikacji zanim cokolwiek innego się dzieje. A potem, dla swojej klasy:

class App.ChatService 
    constructor: (@io) -> 

który pozwala odwołać swoją klasę przez App gdziekolwiek chcesz i nie musisz się martwić o zanieczyszczanie globalnej przestrzeni nazw:

chatter = new App.ChatService 

Jeśli chciał aby Twój globalny numer był naprawdę globalny, mógłbyś użyć numeru class window.ChatService, ale zaleciłbym, żeby nie odpowiadał za to, z wyjątkiem najbardziej banalnych aplikacji.

AFAIK, node.js ma coś podobnego do window, ale nie jestem dostatecznie znany w pliku node.js, aby powiedzieć, co to jest.

+1

W pliku node.js wyeksportujesz symbole, dołączając je do "eksportowania". W jednym module: exports.ChatService = ChatService; W drugim: ChatService = require ("./ chat"). ChatService. –

+0

@Linus: Dzięki, myślę, że Aaron Dufour omówił to zanim doszłam do tego. –

0

Oddziel klasy za pomocą przestrzeni nazw i użyj cake, aby skompilować je wszystkie w jednym (lub więcej) wynikowych plikach .js. Cakefile jest używany jako konfiguracja, która kontroluje, w jakiej kolejności są kompilowane skrypty do kawy - całkiem poręczna przy większych projektach.

Ciasto jest dość łatwy w instalacji i konfiguracji, powołując się na ciasto z vim podczas edytowania projektu jest po prostu

:!cake build 

i można odświeżyć przeglądarkę i zobaczyć wyniki.

Ponieważ jestem również zajęty, aby nauczyć się najlepszego sposobu strukturyzowania plików i korzystania z coffeescript w połączeniu ze szkieletem i ciastem, utworzyłem small project on github, aby zachować go jako punkt odniesienia dla siebie, może to też pomoże tobie ciasto i kilka podstawowych rzeczy. Wszystkie skompilowane pliki są w folderze www, dzięki czemu można je otworzyć w przeglądarce, a wszystkie pliki źródłowe (z wyjątkiem konfiguracji ciasta) znajdują się w folderze src. W tym przykładzie wszystkie pliki .coffee są kompilowane i łączone w wyjściowym pliku .js , który jest następnie dołączany do html.