本文目錄一覽:
- 1、在node環境下怎麼使用commonjs模塊去使用require方法
- 2、如何理解前端模塊化
- 3、js代碼規範問題 JavaScript判斷語句規範
- 4、使用 MockJs — 實現真正的前後端分離
- 5、如何在html和JS中包含Javascript JS文件終極解決方案
在node環境下怎麼使用commonjs模塊去使用require方法
最初的 CommonJS 小組 的參與者們決定弄一份於時下的 JavaScript 編程語言有效,但不必束縛於瀏覽器 JS 環境的限制,的模塊規範。開始的願景是在瀏覽器里使用一些權宜之計, 並希望能藉此影響瀏覽器廠商,促使它們為這種模塊規範的原生支持提供解決方案。權宜之計有:
要麼使用一個服務來轉譯 CJS 模塊成瀏覽器中可用的代碼
要麼使用 XMLHttpRequest(XHR)以文本形式加載模塊,再在瀏覽器中做文本變換、解析的工作
CJS 模塊規範僅允許每文件一個模塊,所以為優化、打包,可使用某種“轉換格式”將多個模塊合併到單個文件。
通過這種方式,CommonJS 小組搞定了依賴引用、如何處理循環依賴,以及如何獲得當前模塊的某些屬性等問題。 但是,他們並沒能接納瀏覽器環境里不可改變、並且仍將影響模塊設計的某些特性:
網絡加載
異步繼承 … 這也同時意味着他們為了實現這個規範,將負擔更多地放到了 Web 開發者身上,而這些權宜之計也使調試變得更麻煩。 調試 eval 的代碼,或者調試多個文件合併之後的單個文件,都有實際使用時的壞處。 這些缺點或許在未來某天會被瀏覽器調試工具解決掉,但結論仍然是:在最普遍的 JS 環境,瀏覽器中,使用 CommonJS 模塊並不是最好的辦法。
如何理解前端模塊化
前端模塊化
在JavaScript發展初期就是為了實現簡單的頁面交互邏輯,寥寥數語即可;如今CPU、瀏覽器性能得到了極大的提升,很多頁面邏輯遷移到了客戶端(表單驗證等),隨着web2.0時代的到來,Ajax技術得到廣泛應用,jQuery等前端庫層出不窮,前端代碼日益膨脹
這時候JavaScript作為嵌入式的腳本語言的定位動搖了,JavaScript卻沒有為組織代碼提供任何明顯幫助,甚至沒有類的概念,更不用說模塊(module)了,JavaScript極其簡單的代碼組織規範不足以駕馭如此龐大規模的代碼
模塊
既然JavaScript不能handle如此大規模的代碼,我們可以借鑒一下其它語言是怎麼處理大規模程序設計的,在Java中有一個重要帶概念——package,邏輯上相關的代碼組織到同一個包內,包內是一個相對獨立的王國,不用擔心命名衝突什麼的,那麼外部如果使用呢?直接import對應的package即可
import java.util.ArrayList;
遺憾的是JavaScript在設計時定位原因,沒有提供類似的功能,開發者需要模擬出類似的功能,來隔離、組織複雜的JavaScript代碼,我們稱為模塊化。
一個模塊就是實現特定功能的文件,有了模塊,我們就可以更方便地使用別人的代碼,想要什麼功能,就加載什麼模塊。模塊開發需要遵循一定的規範,各行其是就都亂套了
規範形成的過程是痛苦的,前端的先驅在刀耕火種、茹毛飲血的階段開始,發展到現在初具規模,簡單了解一下這段不凡的歷程
函數封裝
我們在講函數的時候提到,函數一個功能就是實現特定邏輯的一組語句打包,而且JavaScript的作用域就是基於函數的,所以把函數作為模塊化的第一步是很自然的事情,在一個文件裡面編寫幾個相關函數就是最開始的模塊了
function fn1(){
statement
}
function fn2(){
statement
}
這樣在需要的以後夾在函數所在文件,調用函數就可以了
這種做法的缺點很明顯:污染了全局變量,無法保證不與其他模塊發生變量名衝突,而且模塊成員之間沒什麼關係。
對象
為了解決上面問題,對象的寫法應運而生,可以把所有的模塊成員封裝在一個對象中
var myModule = {
var1: 1,
var2: 2,
fn1: function(){
},
fn2: function(){
}
}
這樣我們在希望調用模塊的時候引用對應文件,然後
myModule.fn2();
這樣避免了變量污染,只要保證模塊名唯一即可,同時同一模塊內的成員也有了關係
看似不錯的解決方案,但是也有缺陷,外部可以隨意修改內部成員
myModel.var1 = 100;
這樣就會產生意外的安全問題
立即執行函數
可以通過立即執行函數,來達到隱藏細節的目的
var myModule = (function(){
var var1 = 1;
var var2 = 2;
function fn1(){
}
function fn2(){
}
return {
fn1: fn1,
fn2: fn2
};
})();
這樣在模塊外部無法修改我們沒有暴露出來的變量、函數
上述做法就是我們模塊化的基礎,目前,通行的JavaScript模塊規範主要有兩種:CommonJS和AMD
CommonJS
我們先從CommonJS談起,因為在網頁端沒有模塊化編程只是頁面JavaScript邏輯複雜,但也可以工作下去,在服務器端卻一定要有模塊,所以雖然JavaScript在web端發展這麼多年,第一個流行的模塊化規範卻由服務器端的JavaScript應用帶來,CommonJS規範是由NodeJS發揚光大,這標誌着JavaScript模塊化編程正式登上舞台。
定義模塊
根據CommonJS規範,一個單獨的文件就是一個模塊。每一個模塊都是一個單獨的作用域,也就是說,在該模塊內部定義的變量,無法被其他模塊讀取,除非定義為global對象的屬性
模塊輸出:
模塊只有一個出口,module.exports對象,我們需要把模塊希望輸出的內容放入該對象
加載模塊:
加載模塊使用require方法,該方法讀取一個文件並執行,返迴文件內部的module.exports對象
js代碼規範問題 JavaScript判斷語句規範
規範性要參考幾個點:
1.是否影響效率
2.是否方便解讀
3.是否便於以後維護
針對這三點去做分析就行了,如樓上所說,沒有哪個人敢站出來說他寫的就是規範的,但是可以通過研究一些js庫去學習以形成習慣。
使用 MockJs — 實現真正的前後端分離
前言: 剛剛看了下的後台,發現我技術文章中,閱讀留言最多的是關於移動端的文章,甚至還有人付費讚賞或諮詢。關於 PC 端的技術文章就顯得比較冷清了,唉,廢了好大勁寫的,沒人看。 和我想的一樣,移動端才是王道,下次找工作我也搞移動端? 。
背景: 去年我寫了一篇 學習使用 json-server 和 mockjs 的文章,當時沒有仔細研究,文章只提到了 MockJs 其中一個 Random 的用法,關於 MockJs 攔截器和另一個很常用的 Mock.mock 函數都沒有提及。這次來搞一下。
唉!以前我也是經常會聽到 前後端分離 這個名詞,只模糊的知道它最重要的一個作用就是,大大的提升了 前端的地位。 但是平時在開發的時候,我也會想奶奶的,沒有接口這前端不就寫了一個破頁面,後期還的和後端對接口,對接口的時候花費的時間,肯定是不比前端開發的時候短,工期上最起碼一半一半吧, 這也就前後端分離 ,我這個小腦袋就不是太明白了。
不過我現在是終於搞明白這個問題了, 對於前端來講,真正的前後端分離,標誌是不依賴後端的前端工作開發完成,項目基本宣告結束。 後端開發完接口,只需要提換一個 URL 就行了,這也意味着前端需要去寫一些接口。
除了帶來開發任務稍微重點外,我至少看到了兩個最大的優點:
我體會最深就是這兩點。
插曲 :對了,今天中午我撿到一個手機,我必須要用一張動圖來描述下:
這個經典的 GIF ,來自鄭伊健的恐怖電影「第一誡」,清涼一冬,絕對值得一看,雖然劇情有很大的 bug ,但是港片就這點好,它有很抓人的地方,讓你覺得特別好看。
正文由此開始:
待續~~~
上面三種方案都可以,但你要知道接口很多,需要支持批量引入,所以 使用 Axios 響應攔截器 就不太可取,只能在這簡單的造些假數據。
著名開源項目 vue-element-admin 開發環境下模擬假接口使用的是 在 webpack-dev-server 的 before 處攔截。生產環境下是在項目入口文件( index,js )使用 Mock.mock 模擬的。
攔截請求的步驟如下,根據 devserverbefore 配置的栗子?:
可知道 before 接收一個函數,函數的第一個參數一般叫 app ,因為它的作用和 express 的 app 是等效的。也就是說這個 app 自帶路由, 正好解決接口批量引入的問題。
在項目中,一般都是這麼寫,把邏輯提出去:
./mock/mock-server.js 文件的內容為:
./mock/index.js 文件的內容為:
mockXHR 不用看,因為這是給線上環境用的,所以可以簡單的改寫為:
隨便找一個,例如 user 看下接口怎麼寫的:
完美,到此結束。
我想你一定對更改文件的時候,為什麼要 清路由和清緩存感興趣。
如果熟悉 express 框架,看到 app._router.stack 你就知道了。不知道也沒關,我演示給你看,新建一個JS 文件,文件內容為:
執行結束,看在 test.js 文件的內容:
發現沒,重複被添加的路由,不是覆蓋而是擴展。
這個涉及到 CJS 模塊的運行機制, 記住 require 的文件會被加到 require.cache 裡面,當文件改變讀的是緩存,而不是最新更改的文件。
項目結構過大,如果只在 mock 文件夾裡面管理有點麻煩,我就想在頁面所在目錄直接寫接口,怎麼辦?沒錯使用 require.context 來批量引入。但是 NodeJs 是沒有批量引入的 API 的。找遍了 npm 也沒發現一個 package 和 require.context 長得像的。
難道沒辦法了嗎?當然不是,自己動手豐衣足食。 依照 vue-cli 插件的命名規範,我給寫的 package 取名 node-plugin-require-context ,簡單講下實現原理:
其實還有一個缺點,如果你看過 Antd-Pro 項目,你就會發現它模擬數據,模塊化採用的是 ESModule ,而不是 CJS。保持編碼模塊化風格一致確實也是需要優化的一個地方,不管了,反正我不幹。
官網本來就是中文的,我在使用中發現寫的賊好,我就不用畫蛇添足了。建議每次使用前:
如何在html和JS中包含Javascript JS文件終極解決方案
現在常用的一種javascript的方法是在當前的html文檔中插入一個script標籤,在標籤中引入script腳本Js代碼var__includes__=newArray;Array.prototype.indexOf=function(obj){for(vari=0;ithis.length;i++){if(this[i]==obj)returni;}return-1;}Array.prototype.add=function(obj){this[this.length]=obj;}functioninclude_js(js){if(__includes__.indexOf(js)-1)return;__includes__.add(js);varhead=document.getElementsByTagName(‘head’)[0];script=document.createElement(‘script’);script.src=js;script.type=’text/javascript’;head.appendChild(script);}當你只是在你的htmlw文檔中使用這個方法的時候,一切OK,這其實是script的標籤的一種快捷的寫法而已。但是,如果你在一個javascript使用這個方法,問題就來了,比如我在test.js中使用include_js(“test1.js”),在test1.js中有一個變量test1是在test.js中要使用的,在webkit中盡然出現了test1變量未定義的錯誤,我不知道ie和firefox是否有這種問題,我想可能是include_js本身不是同步執行導致的,所以我只好使用以下方法來完善inlcude_jsJs代碼var__includes__=newArray;Array.prototype.indexOf=function(obj){for(vari=0;ithis.length;i++){if(this[i]==obj)returni;}return-1;}Array.prototype.add=function(obj){this[this.length]=obj;}functionxhttp(url,callback){varrequest=null;if(typeofXMLHttpRequest!=’undefined’){request=newXMLHttpRequest();}elseif(typeofActiveXObject!=’undefined’){request=newActiveXObject(‘Microsoft.XMLHTTP’);}request.open(‘GET’,url,true);request.onreadystatechange=function(){if(request.readyState==4){callback(request.responseText);}};request.send(null);}functionadd_scripts(jss,callback){varfunc=function(jss,idx,callback){if(idx==jss.length){callback();return};add_script(jss[idx],function(){func(jss,++idx,callback);});}func(jss,0,callback);}functionadd_script(js,callback){if(__includes__.indexOf(js)-1){callback();return;}__includes__.add(js);xhttp(js,function(js_content){varhead=document.getElementsByTagName(‘head’)[0];script=document.createElement(‘script’);head.appendChild(script);// script.innerHTML=js_content; //原帖是這個…本人測試這行..無效 必須用text屬性賦值script.defer=true; script.type=’text/javascript’;script.language=’javascript’;//本人測試修正..添加script.text=js_content;//本人測試修正..添加//zfrong 09.5.20callback();});}functioninclude_js(js){if(__includes__.indexOf(js)-1)return;__includes__.add(js);varhead=document.getElementsByTagName(‘head’)[0];script=document.createElement(‘script’);script.src=js;script.type=’text/javascript’;head.appendChild(script);}當我在html文檔中引入的時候,我用 include_js,當我在js文件中引入js時候,我使用add_scripts,add_scriptJs代碼add_scripts([‘test1.js’,’test2.js’]),add_scripts方法使用了xmlhttp來讀入js內容,並把讀入的內容的寫到一個新的script標籤內,讀入是異步執行的,當執行完畢後,會調用callback、
原創文章,作者:XBCI,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/133934.html