国产另类ts人妖一区二区_欧美肥老太做爰视频_快穿高h肉_国产欧美综合在线

當(dāng)前位置: 首頁 / 技術(shù)干貨 / 正文
JavaScript 模塊化

2022-12-02

模塊 js require module

  模塊化簡介

  JavaScript 最初的目的是為了解決用戶交互頁面的問題;但是隨著互聯(lián)網(wǎng)技術(shù)的發(fā)展,瀏覽器性能大大提升,很多用戶交互頁面也隨之復(fù)雜起來,更是隨著 Web2.0 的發(fā)展,頁面異步交互,前端代碼庫層出不窮,前端代碼日益膨脹;此時(shí) Js 方便就會去考慮使用代碼模塊規(guī)范去管理。

  而在項(xiàng)目開發(fā)中我們常把一個(gè)功能歸類為一個(gè)模塊,多個(gè)程序員去負(fù)責(zé)不同的模塊。 js也不例外,然而 js 早期通過閉包的方式去實(shí)現(xiàn)模塊化的方式存在很多的問題,隨著 js 的發(fā)展中, 很多人為 js 提供了各種出色的模塊化方案。 其中代表有requirejs ,seajs,commonjs,es6 的模塊化方案。(其中 es6 的模塊化方案必定是將來的主流,這也是至今官方提出唯一的規(guī)范)。

  模塊化初級

  什么是模塊

  將一些復(fù)雜的程序代碼根據(jù)制定的規(guī)則封裝成幾個(gè)塊(文件), 并進(jìn)行組合在一起

  塊(文件)的內(nèi)部數(shù)據(jù)是私有的, 只向外部暴露部分接口(方法)與其它模塊進(jìn)行通信

  模塊化的進(jìn)化

  原始寫法

  模塊就是實(shí)現(xiàn)特定功能的一組方法。只要把不同的函數(shù)(以及記錄狀態(tài)的變量)簡單地放在一起,就算是一個(gè)模塊。

  function m1(){

  //...

  }

  function m2(){

  //...

  }

  上面的函數(shù) m1()和 m2(),組成一個(gè)模塊。使用的時(shí)候,直接調(diào)用就行了。這種做法的缺點(diǎn)很明顯:"污染"了全局變量,無法保證不與其他模塊發(fā)生變量名沖突,而且模塊成員之間看不出直接關(guān)系。

  對象寫法

  為了解決上面的缺點(diǎn),可以把模塊寫成一個(gè)對象,所有的模塊成員都放到這個(gè)對象里面。

  var module1 = {

  count : 0.

  m1: function (){

  //...

  },

  m2: function (){

  //...

  }

  };

  上面的函數(shù) m1()和 m2(),都封裝在 module1 對象里。使用的時(shí)候,就是調(diào)用這個(gè)對象的屬性。module1.m1();但是,這樣的寫法會暴露所有模塊成員,內(nèi)部狀態(tài)可以被外部改寫。比如,外部代碼可以直接改變內(nèi)部計(jì)數(shù)器的值。module1.count = 5;

  匿名函數(shù)自調(diào)用(閉包)

  將數(shù)據(jù)和行為封裝到一個(gè)函數(shù)內(nèi)部, 通過給 window 添加屬性來向外暴露接口

  // module.js 文件

  (function(window,$) {

  var data = '1000phone.com'

  //操作數(shù)據(jù)的函數(shù)

  function foo() {//用于暴露有函數(shù)

  console.log("foo()"+data);

  }

  function bar() {//用于暴露有函數(shù)

  console.log("bar()"+data);

  $('body').css('background', 'red');

  otherFun(); //內(nèi)部調(diào)用

  }

  function otherFun() {

  //內(nèi)部私有的函數(shù)

  console.log('otherFun()');

  }

  //暴露行為

  window.myModule = {

  foo: foo,

  bar: bar

  }

  })(window, $)

  使用閉包的方式, 可以達(dá)到不暴露私有成員的目的, 外部通過暴露的方法操作私有成員

  案例中通過 jquery 方法將頁面的背景顏色改成紅色, 所以必須先引入 jQuery 庫,就把這個(gè)庫當(dāng)作參數(shù)傳入。 這樣做除了保證模塊的獨(dú)立性,還使得模塊之間的依賴關(guān)系變得明顯。

  模塊化的好處

  減少命名空間污染

  更好的分離, 按需加載

  更高復(fù)用性

  高可維護(hù)性

  引入多個(gè)模塊后出現(xiàn)的問題

  請求過多

  首先我們要依賴多個(gè)模塊,那樣就會發(fā)送多個(gè)請求,導(dǎo)致請求過多

  依賴模糊

  我們不知道他們的具體依賴關(guān)系是什么,也就是說很容易因?yàn)椴涣私馑麄冎g的依賴關(guān)系導(dǎo)致加載先后順序出錯(cuò)。

  難以維護(hù)

  前兩個(gè)原因就導(dǎo)致了很難維護(hù),很可能出現(xiàn)牽一發(fā)而動全身的情況導(dǎo)致項(xiàng)目出現(xiàn)嚴(yán)重的問題。

  模塊化固然有多個(gè)好處,然而一個(gè)頁面需要引入多個(gè) js 文件,就會出現(xiàn)以上這些問題。而這些問題可以通過模塊化規(guī)范來解決

  CommonJS

  09 年, Ryan Dahl 創(chuàng)造了 node.js 項(xiàng)目,將 JavaScript 語言用于服務(wù)器端編程。這也標(biāo)志著"JavaScript 模塊化編程"正式誕生。因?yàn)槔蠈?shí)說,在瀏覽器環(huán)境下,沒有模塊也不是特別大的問題,畢竟網(wǎng)頁程序的復(fù)雜性有限;但是在服務(wù)器端,一定要有模塊, 與操作系統(tǒng)和其他應(yīng)用程序互動,否則根本沒法編程。

  node.js 的模塊系統(tǒng),就是參照 CommonJS 規(guī)范實(shí)現(xiàn)的。在 CommonJS 中,有一個(gè)全局性方法 require(),用于加載模塊。假定有一個(gè)文件模塊 fs.js,就可以像下面這樣加載,并調(diào)用模塊提供的方法

  const fs = require('fs');

  fs.writeFileSync('./test.js'.'hello node');

  //require()用于加載模塊

  上面的代碼中有一個(gè)問題,fs.writeFileSync('./test.js'.'hello node')代碼的運(yùn)行是在載入 fs.js 之后; 即文件的同步加載還是異步加載, 這對于服務(wù)端不是問題,但是對于瀏覽器端就是大問題;瀏覽器端如果是同步加載模塊, 則載入的模塊的等待時(shí)間取決于網(wǎng)速的快慢,可能需要等待很長時(shí)間, 這對用戶體驗(yàn)是一個(gè)很大的考驗(yàn)。 由此而來 AMD 規(guī)范誕生的背景。

  AMD 異步模塊定義

  目前,主要有兩個(gè) Javascript 庫實(shí)現(xiàn)了 AMD 規(guī)范: require.js 和 curl.js。

  我們主要介紹require.js

  require.js 的誕生,就是為了解決這兩個(gè)問題:

  實(shí)現(xiàn) js 文件的異步加載,避免網(wǎng)頁失去響應(yīng);

  管理模塊之間的依賴性,便于代碼的編寫和維護(hù)。

  require.js 的加載

  使用 require.js 的第一步,是先去官方網(wǎng)站下載最新版本。https://requirejs.org/docs/download.html#latest,下載后,假定把它放在 js/libs 子目錄下面,就可以加載了。

  上面的 require.js 加載完畢后,會首先檢查script標(biāo)簽中的 data-main 屬性, 加載 data-main 屬性值中所定義的 js 文件;如:data-main='js/libs/main',將在 require.js 加載完畢后第一個(gè)加載 js/libs 路徑下的main.js注意: require.js 后綴名是 js,所以 main 的后綴名省略)

  使用案例(引入第三方庫)

  創(chuàng)建 js/libs 目錄存放 require.js 及第三方庫文件

  將下載的 require.js 文件及需要用到的第三方庫文件放入 js/libs 目錄下

  編寫自定義模塊

  編寫自定義功能模塊(網(wǎng)址大寫轉(zhuǎn)換)

  // js/modules/dataService.js 文件

  // 定義沒有依賴的模塊

  define(function() {

  var msg = 'www.1000phone.com';

  function getMsg() {

  return msg.toUpperCase();

  }

  return { getMsg } // 暴露模塊

  })

  編寫自定義功能模塊(控制臺輸出,改變網(wǎng)頁背景顏色)

  // js/modules/console.js 文件

  // 定義有依賴的模塊

  define(['dataService','jquery'], function(dataService,$) {

  var name = 'Leon';

  function showMsg() {

  console.log(dataService.getMsg() + ',' + name);

  $('body').css('background','skyblue');

  }

  // 暴露模塊

  return { showMsg }

  })

  語法解析: 定義暴露模塊:

  //定義沒有依賴的模塊

  define(function(){

  return 模塊

  })

  //定義有依賴的模塊

  define(['module1', 'module2'], function(m1. m2){

  return 模塊

  })

  // 其中 module1. module2 為依賴模塊

  定義入口模塊

  // js/main.js 文件

  (function() {

  require.config({

  baseUrl: 'js/', //基本路徑 出發(fā)點(diǎn)在根目錄下

  paths: {

  //映射: 模塊標(biāo)識名: 路徑

  // 自定義模塊

  console: './modules/console', //此處不能寫成 console.js,會報(bào)錯(cuò)

  dataService: './modules/dataService',

  // 第三方模塊

  jquery: './libs/jquery-1.11.3.min'

  }

  });

  require(['console'], function(console) {

  console.showMsg();

  });

  })()

  語法解析:

  引入使用模塊:

  require(['module1', 'module2'], function(m1. m2){

  // 使用 m1/m2

  })

  require——該函數(shù)用于讀取依賴。同樣它是一個(gè)全局函數(shù),不需要使用 requirejs 命名空間.

  config——該函數(shù)用于配置 RequireJS.

  require.config 配置參數(shù)選項(xiàng)

  baseUrl——用于加載模塊的根路徑。

  paths——用于映射存在根路徑下面的模塊路徑

  定義主頁面

  AMD module

  小結(jié):AMD 模塊定義的方法非常清晰,不會污染全局環(huán)境,能夠清楚地顯示依賴關(guān)系。 AMD 模式可以用于瀏覽器環(huán)境,并且允許非同步加載模塊,也可以根據(jù)需要動態(tài)加載模塊。

  CMD

  CMD 規(guī)范專門用于瀏覽器端,模塊的加載是異步的,模塊使用時(shí)才會加載執(zhí)行。 CMD 規(guī)范整合了 CommonJS 和 AMD 規(guī)范的特點(diǎn)。在 Sea.js 中,所有 JavaScript 模塊都遵循 CMD模塊定義規(guī)范。 Sea.js 可以實(shí)現(xiàn) JavaScript 的模塊化開發(fā)及加載機(jī)制。它應(yīng)用于早期的一些 js 項(xiàng)目中,是淘寶 js 工程師玉伯提出的一個(gè)方案。文檔

  CMD 規(guī)范基本語法

  define(function(require, exports, module){...});

  用來定義模塊。 Sea.js 推崇一個(gè)模塊一個(gè)文件,遵循統(tǒng)一的寫法

  define(function(require){var a = require("xModule"); ... });

  require 用來獲取指定模塊的接口,引入的是模塊, js 文件的后綴.js 可以不寫

  require.async

  用來在模塊內(nèi)部異步加載一個(gè)或多個(gè)模塊。 例如:

  define(function(require){

  require.async(['aModule','bModule'],function(a,b){

  // 異步加載多個(gè)模塊,在加載完成時(shí),執(zhí)行回調(diào)

  a.func();

  b.func();

  });

  });

  exports

  用來在模塊內(nèi)部對外提供接口。 例如:

  define(function(require, exports){

  exports.varName01 = 'varValue'; // 對外提供 varName01 屬性

  exports.funName01 = function(p1.p2){ // 對外提供 funName01 方法

  ....

  }

  });

  module.exports

  用來在模塊內(nèi)部對外提供接口。例如:

  define(function(require, exports, module) {

  module.exports = { // 對外提供接口

  name: 'a',

  doSomething: function() {...};

  };

  });

  seajs.config({...});

  用來對 Sea.js 進(jìn)行配置。

  seajs.use(['a','b'],function(a,b){...});

  用來在頁面中加載一個(gè)或多個(gè)模塊。

  定義暴露模塊:

  //定義沒有依賴的模塊

  define(function(require, exports, module){

  exports.xxx = value

  module.exports = value

  })

  //定義有依賴的模塊

  define(function(require, exports, module){

  //引入依賴模塊(同步)

  var module2 = require('./module2')

  //引入依賴模塊(異步)

  require.async('./module3', function (m3) {})

  //暴露模塊

  exports.xxx = value

  })

  引入使用模塊:

  define(function (require) {

  var m1 = require('./module1')

  var m4 = require('./module4')

  m1.show()

  m4.show()

  })

  創(chuàng)建 js/libs 目錄,

  將下載的 seajs 放在js/libs目錄下

  自定義模塊代碼并使用

  定義 module1 模塊,并暴露 show 方法

  // js/modules/module1.js 文件

  define(function (require, exports, module) {

  //內(nèi)部變量數(shù)據(jù)

  var data = '1000phone.com';

  //內(nèi)部函數(shù)

  function show() {

  console.log('module1 show() ' + data);

  }

  //向外暴露

  exports.show = show;

  })

  定義 module2 模塊,并暴露接口信息 msg

  // js/modules/module2.js 文件

  define(function (require, exports, module) {

  module.exports = {

  msg: '1000phone study'

  }

  })

  定義 module3 模塊,并暴露一個(gè)常量信息

  // js/modules/module3.js 文件

  define(function(require, exports, module) {

  const API_KEY = 'leon';

  exports.API_KEY = API_KEY

  })

  定義 module4 模塊, 同步引入 module2. 異步引入 module3 模塊

  // js/modules/module4.js 文件

  define(function (require, exports, module) {

  // 引入依賴模塊(異步)

  require.async('./module3', function (m3) {

  console.log('異步引入依賴模塊 3 ' + m3.API_KEY)

  });

  // 引入依賴模塊(同步)

  var module2 = require('./module2');

  function show() {

  console.log('module4 show() ' + module2.msg)

  }

  exports.show = show;

  });

  定義主文件 main 模塊,引入模塊 module1 和模塊 module4 并分別調(diào)用 show 方法

  // js/modules/main.js 文件

  define(function (require) {

  var m1 = require('./module1')

  var m4 = require('./module4')

  m1.show()

  m4.show()

  })

  創(chuàng)建主頁面,并在頁面中加載 main 模塊

  小結(jié):通過 Sea.js 可以將大量 javascript 代碼封裝成一個(gè)個(gè)小模塊,然后輕松實(shí)現(xiàn)模塊的加載和依賴管理

  ES6 的 Module

  在 ES6 之前,模塊加載方案主要還是使用 CommonJS 和 AMD 兩種。前者用于服務(wù)器,后者用于瀏覽器。 ES6 在語言標(biāo)準(zhǔn)的層面上,實(shí)現(xiàn)了模塊功能,而且實(shí)現(xiàn)得相當(dāng)簡單,完全可以取代 CommonJS 和 AMD 規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。ES6 模塊的設(shè)計(jì)思想是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。 CommonJS 和 AMD 模塊,都只能在運(yùn)行時(shí)確定這些東西。比如:CommonJS 模塊就是對象,輸入時(shí)必須查找對象屬性。ES6 的模塊自動采用嚴(yán)格模式,不管你有沒有在模塊頭部加上 "use strict";。

  模塊功能主要命令

  模塊功能主要由兩個(gè)命令構(gòu)成: export 和 import。

  export 命令用于規(guī)定模塊的對外接口,

  import 命令用于輸入其他模塊提供的功能。

  一個(gè)模塊就是一個(gè)獨(dú)立的文件。該文件內(nèi)部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內(nèi)部的某個(gè)變量,就必須使用 export 關(guān)鍵字輸出該變量。使用 export 命令定義了模塊的對外接口以后,其他 JS 文件就可以通過 import 命令加載這個(gè)模塊。

  /** 定義模塊 math.js **/

  var basicNum = 0;

  var add = function (a, b) {

  return a + b;

  };

  export { basicNum, add };

  /** 引用模塊 **/

  import { basicNum, add } from './math';

  function test(ele) {

  ele.textContent = add(99 + basicNum);

  }

  瀏覽器加載 ES6 模塊

  瀏覽器加載 ES6 模塊,也使用上面代碼在網(wǎng)頁中插入一個(gè)模塊 foo.js,由于 type 屬性設(shè)為 module,所以瀏覽器知道這是一個(gè) ES6 模塊。

  瀏覽器對于帶有 type="module"的

  使用 Web 服務(wù)器打開首頁 index.html 文件

圖片10

好程序員公眾號

  • · 剖析行業(yè)發(fā)展趨勢
  • · 匯聚企業(yè)項(xiàng)目源碼

好程序員開班動態(tài)

More+
  • HTML5大前端 <高端班>

    開班時(shí)間:2021-04-12(深圳)

    開班盛況

    開班時(shí)間:2021-05-17(北京)

    開班盛況
  • 大數(shù)據(jù)+人工智能 <高端班>

    開班時(shí)間:2021-03-22(杭州)

    開班盛況

    開班時(shí)間:2021-04-26(北京)

    開班盛況
  • JavaEE分布式開發(fā) <高端班>

    開班時(shí)間:2021-05-10(北京)

    開班盛況

    開班時(shí)間:2021-02-22(北京)

    開班盛況
  • Python人工智能+數(shù)據(jù)分析 <高端班>

    開班時(shí)間:2021-07-12(北京)

    預(yù)約報(bào)名

    開班時(shí)間:2020-09-21(上海)

    開班盛況
  • 云計(jì)算開發(fā) <高端班>

    開班時(shí)間:2021-07-12(北京)

    預(yù)約報(bào)名

    開班時(shí)間:2019-07-22(北京)

    開班盛況
IT培訓(xùn)IT培訓(xùn)
在線咨詢
IT培訓(xùn)IT培訓(xùn)
試聽
IT培訓(xùn)IT培訓(xùn)
入學(xué)教程
IT培訓(xùn)IT培訓(xùn)
立即報(bào)名
IT培訓(xùn)

Copyright 2011-2023 北京千鋒互聯(lián)科技有限公司 .All Right 京ICP備12003911號-5 京公網(wǎng)安備 11010802035720號