2012-10-22 20 views
6

Tôi có một số plugin jQuery mà tôi muốn tải bằng cách sử dụng mẫu AMD trong TypeScript. Ví dụ: tôi có thể có cấu trúc này:Tải không đồng bộ các khai báo TypeScript không có xuất khẩu

/lib/jquery.myplugin.js 
/app.ts 

Plugin đơn giản mở rộng jQuery. Nó không cung cấp các hàm hoặc biến cấp cao nhất mới. Một ví dụ có thể là:

// jquery.myplugin.js 
jQuery.fn.myExample = function() { ... } 

Các jquery.myplugin.d.ts tập tin tương ứng trông giống như:

interface JQuery { 
    myExample(); 
} 

Vì vậy mà bây giờ trong app.ts tôi có thể gọi một cái gì đó giống như $('#my-element').myExample(). Lưu ý rằng điều này giả định rằng tôi đã có các khai báo jquery.d.ts từ Microsoft được nạp.

Câu hỏi của tôi là làm cách nào để tải thư viện này một cách không đồng bộ và tận dụng lợi thế của kiểu gõ tĩnh TypeScripts? Tôi có thể sử dụng nó như thế này:

/// <reference path="lib/jquery.myplugin.d.ts"/> 

nhưng điều đó đòi hỏi tôi phải thêm một thẻ <script> sang HTML của tôi, và thư viện không được tải không đồng bộ. Tôi muốn TypeScript tạo mã này:

define(["require", "exports", "lib/jquery.myplugin"], function (require, exports, __jquery.myplugin__) { 
    ... 
    // Use my plugin 
    $('#my-element').myExample(); 
} 

Tuy nhiên vì không có tệp xuất trong tệp .d.ts, tôi không thể viết import myplugin = module('lib/jquery.myplugin').

Gần nhất tôi nhận được là tạo một jquery.myplugin.d.ts tham chiếu tệp ts khác với khai báo giao diện và bao gồm ít nhất một lần xuất. Tuy nhiên không có gì để xuất khẩu trong thư viện này, và để có được đầu ra mong muốn, tôi không chỉ thêm một xuất khẩu mà còn phải gọi nó.

Cập nhật: Tôi đã mở một work item cho điều này trên typescript.codeplex.com

+0

Cách giải quyết hiện tại của tôi là gọi thủ công 'require ([...],() => {...}) 'trong mã TypeScript của tôi, tạo ra một cuộc gọi yêu cầu lồng nhau. Xa lý tưởng, nhưng nó hoạt động. – dcstraw

Trả lời

3

Loại bản ghi sẽ không nhập mô-đun trừ khi chúng xuất một cái gì đó và trừ khi bạn trực tiếp sử dụng những gì chúng đã xuất, nhưng những điều đó không đúng với những thứ như plugin JQuery chỉ đơn giản thêm phương thức mới vào $. Giải pháp là sử dụng cờ phụ thuộc amd theo tài liệu here.

Thêm một dòng như thế này ở trên cùng của tập tin của bạn:

///<amd-dependency path="jgrowl" /> 

Điều này sẽ buộc typescript để liệt kê nó trong define gọi trong javascript biên soạn. Bạn cũng sẽ cần thiết lập đường dẫn và shim cho plugin của mình trong require.config, như sau:

require.config({ 
    paths: { 
    jquery: "external/jquery-2.1.1", 
    jgrowl: "external/jquery.jgrowl-1.4.0.min", 
    }, 
    shim: { 
    'jgrowl': { deps: ['jquery'] }, 
    } 
}); 
+0

Tuyệt vời, cảm ơn rất nhiều. Tôi không nghĩ rằng tính năng này tồn tại khi tôi đặt câu hỏi. Điều này trông giống như những gì tôi đang tìm kiếm. – dcstraw

4

Kind của một hack nhưng đây là cách duy nhất tôi hiện biết.

myplugin.d.ts: mở rộng giao diện JQueryStatic bao gồm IntelliSense cho chức năng myplugin của

/// <reference path="../dep/jquery/jquery.d.ts" /> 

interface JQueryStatic { 
    myFunc(): string; 
} 

myplugin.ts: một tập tin dummy mà mục đích duy nhất là để có nguyên cảo tạo ra một định nghĩa module amd .

var test: number = 1; 

consumer.ts:

/// <reference path="myplugin.d.ts" /> 

import myplugin = module('myplugin'); 

// without this typescript knows you aren't actually using the module 
// and won't create the define block including your plugin 
var workaround = myplugin.test; 

$.myFunc(); 

consumer.js: tạo ra với tsc -c --module amd consumer.ts

define(["require", "exports", 'myplugin'], function(require, exports, __myplugin__) { 
    /// <reference path="myplugin.d.ts" /> 
    var myplugin = __myplugin__; 

    // without this typescript knows you aren't actually using the module 
    // and won't create the define block including your plugin 
    var workaround = myplugin.test; 
    $.myFunc(); 
}) 

Lưu ý rằng myplugin.d.ts sẽ kéo IntelliSense trong cho cả jQuery và các định nghĩa plugin của bạn. Nó là cần thiết để tạo cả myplugin.d.ts và myplugin.ts vì tôi không biết cách (nếu có thể) xuất một cái gì đó đồng thời mở rộng giao diện hiện có trong cùng một tệp mà không có lỗi.

+0

Dường như bạn cũng phải định nghĩa một đường dẫn trong cấu hình requirejs (hoặc bất kỳ bộ nạp AMD nào bạn đang sử dụng) liên kết 'myplugin' với đường dẫn đến plugin, đúng không? Nếu không, nếu bạn đặt myplugin.d.ts vào cùng một vị trí với plugin, tệp js đã biên dịch sẽ ghi đè thư viện plugin của bạn. – dcstraw

+0

Chỉ khi bạn chạy trình biên dịch có cờ định nghĩa và không chỉ định thư mục đầu ra thay thế. Nó sẽ chỉ xuất ra myplugin.js theo mặc định. – ryan

+0

Tôi đang nói rằng myplugin.js có lẽ là tên thư viện của bạn trong trường hợp này. Trong ví dụ của tôi, tôi đã nhập 'lib/jquery.myplugin'. Vì vậy, nếu không có bí danh tên phụ thuộc, tệp JavaScript được tạo của bạn sẽ ghi đè thư viện của bạn. – dcstraw

1

Ở dưới cùng của tập tin rằng giao diện được định nghĩa bên trong bạn có thể đặt:

export var JQuery: JQueryStatic; 

nào sẽ làm cho IntelliSense cho JQuery hiển thị trên bất kỳ tập tin được tải sử dụng import module.

Nếu tập tin của bạn đang được tải không đồng bộ và bạn đang thiết JQuery để biến khác (ví dụ myJQuery) bạn có thể tuyên bố rằng các tập tin đã được nạp bởi một điểm nhất định, ví dụ, nếu bạn có nộp tại của bạn ///<reference path=...> bạn sẽ có thể sử dụng:

declare var myJQuery: JQuery; 

để làm bạn myJQuery loại JQuery.

Hack khác là để chèn giao diện trực tiếp vào khu vực nơi mã đang được tải không đồng bộ:

interface JQueryStatic { 
    myFunc(): string; 
} 

Nếu bạn không nhớ chỉnh sửa JQuery.d.ts các tập tin, bạn có thể thêm chức năng của bạn với các giao diện được xác định trong đó.

liên quan trở lại ví dụ của bạn, bạn sẽ có thể làm điều gì đó như:

declare var __jquery : JQueryStatic; 

Ở phía trên của callback xác định của bạn; và miễn là bạn đã mở rộng giao diện cho JQueryStatic và bao gồm nó bằng cách sử dụng ///<reference path=...> đánh dấu sẽ hoạt động như mong muốn.

+0

Tôi đã không sử dụng AMD bản thân mình, nhưng tôi hy vọng rằng điều này sẽ giúp! – Griffork

+0

Khai báo các biến toàn cầu hoạt động tốt cho các thư viện mà bạn tải thông qua một số phương tiện khác, ví dụ: một thẻ tập lệnh trong HTML của bạn. Lợi ích của mẫu AMD là nó cho phép bạn khai báo sự phụ thuộc của bạn và nó được nạp khi cần thiết hoặc đi kèm trong lúc xây dựng, và không gian tên chung của bạn không bị ô nhiễm. Điều đó đặc biệt là những gì không được hỗ trợ tốt trong TypeScript cho các thư viện không có xuất khẩu cấp cao nhất. – dcstraw

+0

Tôi xin lỗi, tôi nghĩ rằng mô hình AMD đã làm việc ra khỏi một phong cách gọi lại? Nếu vậy thì sẽ không thể khai báo một biến với giao diện JQuery trong cuộc gọi lại? Sau đó, nó sẽ hiển thị cho intellisense chỉ trong vòng gọi lại và không phải trong phần còn lại của tập tin. – Griffork

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