實戰Dojo與RequireJS整合 之二

來源:互聯網
上載者:User

Dojo 和requireJS 整合之二

 

作者: feijia (tiimfei@gmail.com)

 

在成功了配置了dojo和requireJS之後,我們要仔細分析一下這個模板項目的原始碼, 看看Ben提供的程式架構究竟是怎麼實現的。

首先我們會注意到 index.html

<!DOCTYPE html><br /><html lang="en-us"><br /><head><br /><meta charset="utf-8" /><br /><title>dojo with requirejs test page</title><br /><link rel="stylesheet" href="dojo/resources/dojo.css" mce_href="dojo/resources/dojo.css" type="text/css"><br /><mce:script type="text/javascript"><!--<br />// configure require.js<br />require = {<br />// point to the dojo and dijit packages<br />packages: [<br />{<br />name: 'dojo',<br />location: 'dojo/dojo',<br />main:'lib/main-browser',<br />lib: '.'<br />},<br />{<br />name: 'dijit',<br />location: 'dojo/dijit',<br />main:'lib/main',<br />lib: '.'<br />}<br />],<br />// set the path for the require plugins<br />paths: {<br />require: 'requirejs/require'<br />},<br />ready: function () {<br />require(['app/App', 'app/config'], function (App, config) {<br />var app = new App(config, 'app');<br />app.startup();<br />});<br />}<br />};</p><p>// --></mce:script><br /><mce:script type="text/javascript" src="requirejs/require.js" mce_src="requirejs/require.js"></mce:script><br /></head><br /><body><br /><h1>dojo with requirejs test page</h1><br /><div id="app"><p>if you're seeing this - it didn't work</p></div><br /></body><br /></html><br />

這是整個應用的入口。 在這裡首先會看到一段JavaScript

// configure require.js<br /> require = {<br /> // 設定dojo和dijit兩個模組的相對路徑資訊,以及每個模組中的主入口<br /> packages: [<br /> {<br /> name: 'dojo',<br /> location: 'dojo/dojo',<br /> main:'lib/main-browser',<br /> lib: '.'<br /> },<br /> {<br /> name: 'dijit',<br /> location: 'dojo/dijit',<br /> main:'lib/main',<br /> lib: '.'<br /> }<br /> ],<br /> // 設定依賴路徑上的名字的映射<br /> paths: {<br /> require: 'requirejs/require'<br /> },<br /> //當DOM裝載完成後執行的回呼函數。 在這個回呼函數中,我們會調用require 來裝入並執行我們的app</p><p> ready: function () {<br /> require(['app/App', 'app/config'], function (App, config) {<br /> var app = new App(config, 'app');<br /> app.startup();<br /> });<br /> }<br /> };<br />

這段指令碼主要做了兩個動作:

1. 配置reuqireJS 所要載入的包的名稱路徑 (有點類似於配置Java的classpath,告訴載入器 模組的位置)

2. 核心邏輯是在ready:function()  它指定了requireJS在整個頁面DOM裝載完成後要執行的邏輯。 這裡就是裝入app的相依模組('app/App'和‘app/config' 。 ),並啟動app.startup。

在requireJS 被載入後,它會解析我們這裡定義的require對象。並在頁面DOM裝入完畢後執行ready屬性所指定的回呼函數。

 

除了這段指令碼, index.html 中還有一段HTML定義了一個名為"app" 的div節點。這個節點就是將由App所建立的Widget所用的節點。 如果App成功運行,則這個Div中的html代碼將會替換成由Widget定義的內容。如果App裝入失敗,使用者就會看到寫在index.html中的這段靜態內容。"        if you're seeing this - it didn't work"

 

下面我們就來看一下app/App是什麼內容。 從路徑上可以判斷,這個模組指向我們項目中的app/App.js

===App.js
define([<br /> 'dojo',<br /> 'dijit/_Widget',<br /> 'dijit/_Templated',<br /> 'i18n!./nls/App',<br /> 'text!./templates/App.html',<br /> 'dojo/date/locale',<br /> 'i18n!dojo/cldr/nls/fr-ch/gregorian'<br />], function (d, Widget, Templated, i18n, template, locale) {<br /> return d.declare([<br /> Widget,<br /> Templated<br /> ], {<br /> templateString: template,<br /> i18n: i18n,<br /> buildRendering: function () {<br /> // this is just to test some locale specific stuff with dojo<br /> this.defaultMonths = locale.getNames('months', 'wide', 'standAlone', d.locale).join(', ');<br /> this.frchMonths = locale.getNames('months', 'wide', 'standAlone', 'fr-ch').join(', ');<br /> this.inherited(arguments);<br /> },<br /> startup: function () {<br /> this.inherited(arguments);<br /> if (this.alertWhenStarted) {<br /> alert('App is started!');<br /> }<br /> }<br /> });<br />});<br />

App.js 中,它先聲明了自己的相依模組,包括了dojo, dijit/_widget dojo/date/locale 等。 要特別注意的是,它還有一些特別的依賴 例如 'i18n!.nls/App'  這是requireJS的外掛程式定義的格式。 表示這個依賴需要由一個名為i18n的requireJS外掛程式去載入,而所載入的資源的路徑為./nsl/App.js 

requireJS 的plugin其實本身也是一個標準AMD模組。 ! 之前的部分就是這個模組的名字。 因為這裡我們使用的是i18n,因此requireJS會試圖先去載入一個名為i18n的模組。 預設的,它會在項目根目錄去尋找名為i18n.js的檔案載入。 如果我們希望把這個外掛程式的位置移動一下到requirejs目錄中,可以這樣寫

requirejs/i18n!.nls/App

類似的,我們看到另一個'text!./templates/App.html'依賴, text也是一個requireJS的標準外掛程式, 這個外掛程式的作用很簡單就是把 一個檔案作為字串載入進來。 這裡就是用來載入了一個我們接下來會用到的widget 模板:./templates/App.html

使用requireJS text外掛程式的樣本:
require(["some/module", "text!some/module.html", "text!some/module.css"],<br /> function(module, html, css) {<br /> //參數HTML中將會包含some/module.html的文本<br /> //of the some/module.html file<br /> //參數css中將會包含some/module.css的文本<br /> //of the som/module.css file.<br /> }<br />);<br />

分析完了該程式的依賴,我們再來看App的邏輯是什麼。 它只有一個return 語句, 內容是一個d.declare調用. 參數d就是dojo。我們知道

dojo.declare 是用來建立類的。 這裡我們建立了一個基於widget和Templated的子類. 而參數Widget 對應 dijit/_Widget, Templated 對應 dijit/_Templated , 因此該類繼承自dijit/_Widget 和dijit/_Templated。 該類還自

定義了一個模板字串,和一個i18n 包。 buildRendering 是複寫dojo._Widget基類的方法。主要就是擷取了2個字串。一個是用當前預設locale 的月份字串,另一個是用法語的。 然後就執行父類的方法 this.inherited(arguments)

startup也是dijit._Widget 的基類方法,在一個Widget啟動時調用。這裡也直接調用了父類的方法,並彈出對話方塊(App is Started)

所以App實際就是聲明了一個新的Widget類並指定了Widget的模板。 那麼這個模板是怎麼樣的?

<div>

    <h1>${i18n.heading}</h1>

    <p>${i18n.welcome}</p>

    <ul>

        <li>default locale: ${defaultMonths}</li>

        <li>locale 'fr-ch': ${frchMonths}</li>

    </ul>

</div>

稍微瞭解一下dijit的模板機制就可以看懂這個非常簡單的Widget模板了。  所有${xxx}的內容都會被相應的變數值替換。 我們在前面dojo.declare 中看到, ${defaultMonths} 和 ${frchMonths} 是自訂的兩個字串. 而i18n.heading 和 i18n.welcome 是從    'i18n!./nls/App 得來的值。

到這裡我們已經看完了所有的代碼。 下面是該程式的架構:

 

這個例子看起來有些複雜,其實如果你只是想用requireJS 和dojo 可以非常簡單。 幾行代碼就可以了,但是我們要反問自己AMD的優勢究竟是什嗎?那就是更清晰的模組化代碼結構和解藕。 因此這個應用程式模板提供了一個很好的例子,你可以在它的基礎上進一步去搭建自己的前端應用。

在架構圖中你可以看到它清晰的把載入器,程式入口和配置,程式的主要商務邏輯,以及應用所依賴的類庫和資源都做了清晰的隔離. 而所有這些模組和資源全部都是使用requireJS來統一管理和載入的。當應用程式的邏輯逐漸層得複雜,使用各種的本地化資源和第三方類庫時,這樣模組化的優勢就會體現出來.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.