<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                剛才的示例很簡單?實際上Sea.js本身小巧而不失靈活,讓我們再來深入地了解下如何使用Sea.js! ## 定義模塊 Sea.js是[CMD](https://github.com/cmdjs/specification/blob/master/draft/module.md)這個模塊系統的一個運行時,Sea.js可以加載的模塊,就是CMD規范里所指明的。那我們該如何編寫一個CMD模塊呢? Sea.js提供了一個全局方法——`define`,用來定義一個CMD模塊。 #### `define(factory)` ~~~ define(function(require, exports, module) { // 模塊代碼 // 使用require獲取依賴模塊的接口 // 使用exports或者module來暴露該模塊的對外接口 }) ~~~ `factory`是這樣一個函數`function (require?, exports?, module?) {}`,如果模塊本身既不依賴其他模塊,也不提供接口,`require`、`exports`和`module`都可以省略。但通常會是以下兩種形式: ~~~ define(function(require, exports) { var Vango = require('vango') exports.drawCircle = function () { var vango = new Vango(document.body, 100, 100) vango.circle(50, 50, 50, { fill: true, styles:{ fillStyle:"red" } }) } }) ~~~ 或者: ~~~ define(function(require, exports, module) { var Vango = require('vango'); module.exports = { drawCircle: function () { var vango = new Vango(document.body, 100, 100); vango.circle(50, 50, 50, { fill: true, styles:{ fillStyle:"red" } }); } }; }); ~~~ > **注意**:必須保證參數的順序,即需要用到require, exports不能省略;在模塊中exports對象不可覆蓋,如果需要覆蓋請使用`module.exports`的形式(這與node的用法一致,在后面的原理介紹會有相關的解釋)。你可以使用`module.exports`來export任意的對象(包括字符串、數字等等)。 #### `define(id?, dependencies?, factory)` **id**:String 模塊標識 **dependencies**:Array 模塊依賴的模塊標識 這種寫法屬于[Modules/Transport/D](http://wiki.commonjs.org/wiki/Modules/Transport/D)規范。 ~~~ define('drawCircle', ['vango'], function(require, exports) { var Vango = require('vango'); exports.drawCircle = function () { var vango = new Vango(document.body, 100, 100); vango.circle(50, 50, 50, { fill: true, styles:{ fillStyle:"red" } }); }; }) ~~~ 與CMD的`define`沒有本質區別,我更情愿把它稱作“具名模塊”。Sea.js從用于生產的角度來說,必須支持具名模塊,因為開發時模塊拆得太小,生產環境必須把這些模塊文件打包為一個文件,如果模塊都是匿名的,那就傻逼了。([為什么會傻逼?](https://github.com/seajs/seajs/issues/930)) > 所以Sea.js支持具名模塊也是無奈之舉。 #### `define(anythingelse)` 除去以上兩種形式,在CMD標準中,可以給define傳入任意的字符串或者對象,表示接口就是對象或者字符串。不過這只是包含在標準中,在Sea.js并沒有相關的實現。 ## 配置Sea.js Sea.js為了能夠使用起來更靈活,提供了配置的接口。可配置的內容包括靜態服務的位置,簡化模塊標識或路徑。接下來我們來詳細地了解下這些內容。 #### seajs.config(config) **config**:Object,配置鍵值對。 Sea.js通過`.config`API來進行配置。你甚至可以在多個地方調用seajs.config來配置。Sea.js會mix傳入的多個config對象。 ~~~ seajs.config({ alias: { 'jquery': 'path/to/jquery.js', 'a': 'path/to/a.js' }, preload: ['seajs-text'] }) ~~~ ~~~ seajs.config({ alias: { 'underscore': 'path/to/underscore.js', 'a': 'path/to/biz/a.js' }, preload: ['seajs-combo'] }) ~~~ 上面兩個配置會合并為: ~~~ { alias: { 'jquery': 'path/to/jquery.js', 'underscore': 'path/to/underscore.js', 'a': 'path/to/biz/a.js' }, preload: ['seajs-text', 'seajs-combo'] } ~~~ `config`可以配置的鍵入下: #### base **base**:String,在解析絕對路徑標識的模塊時所使用的base路徑。 默認地,在不配置base的情況下,base與sea.js的引用路徑。如果引用路徑為`http://example.com/assets/sea.js`,則base為`http://example.com/assets/`。 > 在閱讀Sea.js這份文檔時看到: > _當 sea.js 的訪問路徑中含有版本號時,base 不會包含 seajs/x.y.z 字串。 當 sea.js 有多個版本時,這樣會很方便。_ > 即如果sea.js的引用路徑為[http://example.com/assets/1.0.0/sea.js,則base仍為http://example.com/assets/。這種方便性,我覺得過了點。](http://example.com/assets/1.0.0/sea.js%EF%BC%8C%E5%88%99base%E4%BB%8D%E4%B8%BAhttp://example.com/assets/%E3%80%82%E8%BF%99%E7%A7%8D%E6%96%B9%E4%BE%BF%E6%80%A7%EF%BC%8C%E6%88%91%E8%A7%89%E5%BE%97%E8%BF%87%E4%BA%86%E7%82%B9%E3%80%82) 使用base配置,根本上可以分離靜態文件的位置,比如使用CDN等等。 ~~~ seajs.config({ base: 'http://g.tbcdn.cn/tcc/' }) ~~~ > 如果我們有三個CDN域名,如何將靜態資源散列到這三個域名上呢? #### paths **paths**:Object,如果目錄太深,可以使用paths這個配置項來縮寫,可以在require時少寫些代碼。 如果: ~~~ seajs.config({ base: 'http://g.tbcdn.cn/tcc/', paths: { 'index': 's/js/index' } }) ~~~ 則: ~~~ define(function(require, exports, module) { // http://g.tbcdn.cn/tcc/s/js/index/switch.js var Switch = require('index/switch') }); ~~~ #### alias **alias**:Object,本質上看不出和paths有什么區別,區別就在使用的概念上。 ~~~ seajs.config({ alias: { 'jquery': 'jquery/jquery/1.10.1/jquery' } }) ~~~ 然后: ~~~ define(function(require, exports, module) { // jquery/jquery/1.10.1/jquery var $ = require('jquery'); }); ~~~ > 看出使用概念的區別了么? #### preload `preload`配置項可以讓你在加載普通模塊之前提前加載一些模塊。既然所有模塊都是在use之后才加載的,preload有何意義?然,看下面這段: ~~~ seajs.config({ preload: [ Function.prototype.bind ? '' : 'es5-safe', this.JSON ? '' : 'json' ] }); ~~~ preload比較適合用來加載一些核心模塊,或者是shim模塊。這是一個全局的配置,使用者無需關系核心模塊或者是shim模塊的加載,把注意力放在核心功能即可。 還有一些別的配置,比如`vars`、`map`等,可以參考[配置](https://github.com/seajs/seajs/issues/262)。 ## 使用模塊 #### `seajs.use(id)` Sea.js通過use方法來啟動一個模塊。 ~~~ seajs.use('./main') ~~~ 在這里,`./main`是main模塊的id,Sea.js在main模塊LOADED之后,執行這個模塊。 Sea.js還有另外一種啟動模塊的方式: #### seajs.use(ids, callbacks) ~~~ seajs.use('./main', function(main) { main.init() }) ~~~ Sea.js執行ids中的所有模塊,然后傳遞給callback使用。 ## 插件 Sea.js官方提供了7個插件,對Sea.js的功能進行了補充。 * seajs-text:用來加載HTML或者模板文件; * seajs-style:提供了`importStyle`,動態地向頁面中插入css; * seajs-combo:該插件提供了依賴combo的功能,能把多個依賴的模塊uri combo,減少HTTP請求; * seajs-flush:該插件是對seajs-combo的補充,或者是大殺器,可以先hold住前面的模塊請求,最后將請求的模塊combo成一個url,一次加載hold住的模塊; * seajs-debug:Fiddler用過么?這個插件基本就是提供了這樣一種功能,可以通過修改config,將線上文件proxy到本地服務器,便于線上開發調試和排錯; * seajs-log:提供一個seajs.log API,私覺得比較雞肋; * seajs-health:目標功能是,分析當前網頁的模塊健康情況。 由此可見,Sea.js的插件主要是解決一些附加問題,或者是給Sea.js添加一些額外的功能。私覺得有些功能并不合適讓Sea.js來處理。 #### 插件機制 總結一下,插件機制大概就是兩種: * 使用Sea.js在加載過程中的事件,注入一些插件代碼,修改Sea.js的運行流程,實現插件的功能; * 給seajs加入一些方法,提供一些額外的功能。 > 私還是覺得Sea.js應該保持純潔;為了實現插件,在Sea.js中加入的代碼,感覺有點不值;combo這種事情,更希望采取別的方式來實現。 Sea.js應該做好運行時。 ## 構建與部署 很多時候,某個工具或者類庫,玩玩可以,但是一用到生產環境,就感覺力不從心了。就拿Sea.js來說,開發的時候根據業務將邏輯拆分到很多小模塊,邏輯清晰,開發方便。但是上線后,模塊太多,HTTP請求太多,就會拖慢頁面速度。 所以我們必須對模塊進行打包壓縮。這也是SPM的初衷。 SPM是什么? 使用者認為SPM是Sea.js Package Manager,但是實際上代表的是Static Package Manager,及靜態包管理工具。如果大家有用過npm,你可以認為SPM是一個針對前端模塊的包管理工具。當然它不僅僅如此。 SPM包括: * 源服務:類似于npm源服務器的源服務; * 包管理工具:相當于npm的命令行,安裝、發布模塊,解決模塊依賴; * 構建工具:模塊CMD化、合并模塊、壓縮等;都是針對我們一開始提到的問題; * 配置管理:管理配置; * 輔助功能:比較像Yeoman,以插件提供一些便于平時開發的組件。 > SPM心很大,SPM囊括yo、bower和grunt這三個工具。 ### spm > spm is a package manager, it is not build tools. 這句話來自github上[spm2](https://github.com/spmjs/spm2)的README文件。`spm是一個包管理工具,不是構建工具!`,它與npm非常相似。 #### spm的包規范 一個spm的模塊至少包含: ~~~ -- dist -- overlay.js -- overlay.min.js -- package.json ~~~ ##### package.json 在模塊中必須提供一個package.json,該文件遵循[Common Module Definition](https://github.com/cmdjs/specification)模塊標準。與node的`package.json`兼容。在此基礎上添加了兩個key。 * family,即是包發布者在spmjs.org上的用戶名; * spm,針對spm的配置。 一個典型的`package.json`文件: ~~~ { "family": "arale", "name": "base", "version": "1.0.0", "description": "base is ....", "homepage": "http://aralejs.org/base/", "repository": { "type": "git", "url": "https://github.com/aralejs/base.git" }, "keywords": ["class"], "spm": { "source": "src", "output": ["base.js", "i18n/*"], "alias": { "class": "arale/class/1.0.0/class", "events": "arale/events/1.0.0/events" } } } ~~~ ##### dist `dist`目錄包含了模塊必要的模塊代碼;可能是使用spm-build打包的,當然只要滿足兩個條件,就是一個spm的包。 #### 安裝 `$ npm install spm -g` 安裝好了spm,那該如何使用spm呢?讓我們從help命令開始: #### help 我們可以運行`spm help`查看`spm`所包含的功能: ~~~ $ spm help Static Package Manager Usage: spm <command> [options] Options: -h, --help output usage information -V, --version output the version number System Commands: plugin plugin system for spm config configuration for spm help show help information Package Commands: tree show dependencies tree info information of a module login login your account search search modules install install a module publish publish a module unpublish unpublish a module Plugin Commands: init init a template build Build a standar cmd module. ~~~ `spm`包含三種命令,**系統命令**,即與`spm`本身相關(配置、插件和幫助),**包命令**,與包管理相關,**插件命令**,插件并不屬于`spm`的核心內容,目前有兩個插件`init`和`build`。 也可以使用`help`來查看單個命令的用法: ~~~ $ spm help install Usage: spm-install [options] family/name[@version] Options: -h, --help output usage information -s, --source [name] the source repo name -d, --destination [dir] the destination, default: sea-modules -g, --global install the package to ~/.spm/sea-modules -f, --force force to download a unstable module -v, --verbose show more logs -q, --quiet show less logs --parallel [number] parallel installation --no-color disable colorful print Examples: $ spm install jquery $ spm install jquery/jquery arale/class $ spm install jquery/jquery@1.8.2 ~~~ #### config 我們可以使用`config`來配置用戶信息、安裝方式以及源。 ~~~ ; Config username $ spm config user.name island205 ; Or, config default source $ spm config source.default.url http://spmjs.org ~~~ #### search `spm`是一個包管理工具,與`npm`類似,有自己的源服務器。我們可以使用`search`命令來查看源提供的包。 > 由于`spm`在包規范中加入了`family`的概念,常常想運行`spm install backbone`,發現并沒有backbone這個包。原因就是`backbone`是放在`gallery`這族下的。 ~~~ $ spm search backbone 1 result gallery/backbone keys: model view controller router server client browser desc: Give your JS App some Backbone with Models, Views, Collections, and Events. ~~~ #### install 然后我們就可以使用`install`來安裝了,注意我們必須使用包的全名,即`族名/包名`。 ~~~ $ spm install gallery/backbone install: gallery/backbone@stable fetch: gallery/backbone@stable download: repository/gallery/backbone/1.0.0/backbone-1.0.0.tar.gz save: c:\Users\zhi.cun\.spm\cache\gallery\backbone\1.0.0\backbone-1.0.0.tar.gz extract: c:\Users\zhi.cun\.spm\cache\gallery\backbone\1.0.0\backbone-1.0.0.tar.gz found: dist in the package installed: sea-modules\gallery\backbone\1.0.0 depends: gallery/underscore@1.4.4 install: gallery/underscore@1.4.4 fetch: gallery/underscore@1.4.4 download: repository/gallery/underscore/1.4.4/underscore-1.4.4.tar.gz save: c:\Users\zhi.cun\.spm\cache\gallery\underscore\1.4.4\underscore-1.4.4.tar.gz extract: c:\Users\zhi.cun\.spm\cache\gallery\underscore\1.4.4\underscore-1.4.4.tar.gz found: dist in the package installed: sea-modules\gallery\underscore\1.4.4 ~~~ `spm`將模塊安裝在了`sea_modules`中,并且在`~/.spm/cache`中做了緩存。 ~~~ `~sea-modules/ `~gallery/ |~backbone/ | `~1.0.0/ | |-backbone-debug.js | |-backbone.js | `-package.json `~underscore/ `~1.4.4/ |-package.json |-underscore-debug.js `-underscore.js ~~~ `spm`還加載了`backbone`的依賴`underscore`。 當然,Sea.js也是一個模塊,你可以通過下面的命令來安裝: ~~~ $ spm install seajs/seajs ~~~ `seajs`的安裝路徑為`sea_modules/seajs/seajs/2.1.1/sea.js`,看到這里,結合seajs頂級模塊定位的方式,對于seajs在計算base路徑的時,去掉了`seajs/seajs/2.1.1/`的原因。 #### build `spm`并不是以構建工具為目標,它本身是一個包管理器。所以`spm`將構建的功能以插件的功能提供出來。我們可以通過plugin命令來安裝`build`: ~~~ $ spm plugin install build ~~~ 安裝好之后,如果你使用的是標準的`spm`包模式,就可以直接運行`spm build`來進行標準的打包。 **SPM2的功能和命令就介紹到這里,更多的命令在之后的實踐中介紹。** ### spm與spm2 #### spm與spm2 其實之前介紹的spm是其第二個版本[spm2](https://github.com/spmjs/spm2)。spm的第一個版本可以在[這里](https://github.com/spmjs/spm)找到。 spm與spm2同樣都是包管理工具,那它們之間有什么不同呢? * 從定位上,spm2更加強調該工具是一個CMD包管理工具; * 從提供的用戶接口(cmd命令)spm2比起spm更加規范,作為包管理工具,在使用方式和命令都更趨同于npm; * 在spm2中,構建命令以插件的方式獨立出來,并且分層清晰;Transport和Concat封裝成了grunt,便于自定義build方式;基于基礎的grunt,構建了一個標準的spm-build工具,用于構建標準的CMD模塊; * 與此類似,deploy和init的功能都是以插件的形式提供的; * 修改了package.json規范。 為什么作者對spm進行了大量的重構? 之所以進行大量的重構,就是為了保持spm作為包管理工具的特征。如npm一般,只指定最少的規范(package.json),提供包管理的命令,但是這個包如何構建,代碼如何壓縮并不是spm關心的事情。 只有規則簡單合理,只定義接口,不關心具體實現,才有更廣的實用性。 > spm本身是從業務需求成長起來的一個包管理工具,spm1更多的是一些需求功能的堆砌,而spm2就是對這些功能的提煉,形成一套適用于業界的工具。 #### apm apm的全稱是: > Alipay package manager 即支付寶的包管理工具。 apm是基于spm的一套專門為支付寶開發的工具集。我們可以這么看,spm2和apm是spm升級后的兩個產物,spm2更加專注于包管理和普適性,而apm更加專注于支付寶業務。由于業務細節和規模的不同,apm可能并不適合其他公司所用,所以需要spm2,而又因為支付寶業務的特殊性和基因,必須apm。 謝謝 @lepture 的指正: > 不一定要用 apm,只是 apm 把所有要用到的插件都打包好了,同時相應的默認配置也為支付寶做了處理,方便內部員工使用,不用再配置了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看