關於 JavaSrcipt 前端開發的建議:模塊化開發

JavaScript 是一種優秀的腳本語言。

在 JavaScript 的誕生之初,便於 瀏覽器 密不可分,現在它更是到了服務器中大展身手。javascript

可是這裏不敘述服務端的開發建議。html

Script 翻譯過來就是 腳本,而前面所加入 Java 則是指現現在仍然流行的開發語言:Java。前端

 

在 Java 平常開發中,常使用 MVC 的模式進行開發,那麼使用 JavaScript,不借助任何前端框架,咱們可使用這個模式編寫出執行高效的前端頁面腳本代碼嗎?java

答案是 OK 的,如何作到?數據庫

 

瞭解 MVC 的一些常識:

MVC的全稱是: Model(模型)、View(視圖)、Controller(控制器)編程

它們各司其職,也爲協同辦公提供了底層上的支持:好比有的開發者負責模型搭建,有的則是開發視圖(也就是咱們所說的前端)、以及後臺業務處理的控制層。瀏覽器

這是最基礎的分工模式,還延伸了 Dao 層,也就是單純與數據庫打交道的。緩存

 

各種原理圖片網上亦有不少,這裏就很少說了。前端框架

 

 

 

 

延伸:如何 JavaScipt 能夠像 Java 開發後臺那樣遊刃有餘的開發前端?

 

前端腳本所須要實現的主要功能大體以下:服務器

  • 處理與服務器交互的數據的
  • 處理與用戶交互的數據的
  • 處理界面點擊響應的
  • 處理緩存的
  • 處理頁面效果的

它們之間的依賴我大體整理了一下:

    界面點擊響應 -> 頁面效果 -> 用戶交互 ->  服務器交互

    頁面效果 -> 緩存 -> 服務器交互

 

簡單梳理以後就能夠發覺原來前端也能夠高效開發!比方說,頁面效果指的是用戶所看到的,屬於視覺層

而有些內容則是動態生成的,這就意味着須要與服務器進行交互拿到數據。

可是服務器若是同時在線的人數過多,那麼每初始化一次就須要拿取數據,顯然可能會不堪重負,因此加入了緩存

 

界面初始化後,用戶會進行操做(界面點擊響應),點擊後的視覺會發生變化(頁面效果)以讓用戶知道他已經成功操做,須要等待。

以後將用戶交互產生的數據進入服務器交互區,上傳給服務器處理。

 

就這樣,一個前端的基本功能互相依賴,就變成了咱們平常所看到的網站。

 

如何細分爲腳本區域?讓分段開發更有效?

我所建議的是,前期先分爲多個文件進行開發,注意文件之間的順序引入:由於HTML的解析是由上而下,上方的腳本是沒法訪問下方腳本的API的,除非有全局變量

 

<script type="text/javascript" src="/xx.js"></script>
<script type="text/javascript" src="./xxx.js"></script>

 

若果是按上述代碼所寫,基本上 xx.js 的代碼初始化中帶有 xxx.js 的API,則會報 define 錯誤。

誰讓 xxx.js 還沒加載呢,因此起初分爲多個文件開發,必定要注意順序問題,或者都不進行初始化,等到最後一個文件加載時才進行初始化便不會報錯。

 

好了,問題稍微注意下就好,這是針對剛進行開發的開發者提供的注意事項。

 

分爲多個文件:

  1. 異常處理.js
  2. 緩存讀寫.js
  3. 數據庫交互.js
  4. 數據服務.js
  5. 實體類.js(參考Java的編程模式)
  6. 界面效果.js
  7. 界面事件處理.js

 

大體分爲七個文件,順序亦按照上述所佈置。

異常處理是處理如同斷網、或者被某個擴展腳本阻攔產生的錯誤等處理,以便讓用戶明確地知道當前操做失敗。一般有效的方式是發出一個彈窗(視狀況發出不一樣類型的模態窗體)。

其它再也不敘述。

後續編寫完成後,能夠容納成單個文件,能夠更好的節省HTTP鏈接數。

 

數據庫交互文件無非是使用 Ajax 的方式進行提交,收取數據,關於 Ajax 的資料網絡上很是多,JQuery 框架也集成了功能。

這裏指的注意的是,要劃分好後臺提供的API,比方說:

後臺提供了初始化頁面的 JSON 數據,而且是一天才更新一次,並且參數是根據登陸 Cookie 決定的,那麼能夠根據這樣進行開發:

 

class Database extends Cache{   constructor() {
    super();     
// 只初始化一次,且當天數據保持不變 this.INIT_PAGE_DATA = null;
  }   initPage( cookie ){     
// 查詢是否有緩存的 Cookie 當前頁面數據 -> 繼承了緩存 API,可直接使用 this 關鍵字     this.queryCookie( init_page_data );     // 沒有緩存 -> 進行 Ajax 操做拿到 數據:data     this.INIT_PAGE_DATA = data;     // 進行緩存到 Cookie 的操做 -> time : 時間,這裏配置爲 一天     this.cacheCookie( data, time );   } }

 

如此一來,就算是後臺開發人員,只須要稍微瞭解 JavaScript 的常識,就能夠開發本身擅長領域的腳本!

數據庫編寫者能夠根據字段,寫出嚴謹的前端實體類(好吧其實Java後臺的實體類一般也是根據數據庫字段而開發編寫的)

 

在擔憂 class 關鍵字沒有太多瀏覽器支持嗎?其實那已經成爲過去式了。

使用 function 關鍵字雖好,可是 class 操做價更高呀

至於原型鏈等深層的原理,這裏再也不概述,之後有時間再出相關的隨筆吧。

 

那麼實體類該怎樣寫才能作更多的事情,不至於產生貧血模型呢?

答案是讓它們各司其職,數據寫入前進行檢查,順道操做一下相關的API,這樣界面事件處理的開發人員就不用寫太多行來實現某個業務了。

 

比方我只須要一個實體類,載入全部數據後,將其提交給後臺,保存在數據庫裏:

class entity_user{   constructor() {     // 用戶的名稱
    this.name = null;     // 用戶的年齡
    this.age = null;     // 不寫太多了
  }      getName(){     return this.name;   }   setName( name ){
    // 若是傳入產生爲空,那麼實際上是真的想設置爲空     i
f (null == name ) { this.name = null; return; }
    // 查查類型是否是 String,不是便拋出異常
if (typeof name !== "string") {
      // 長度是否大於 1,也就是傳入的是否是空字符串,是的話再拋出異常
if (name.length >= 1) { this.name = name ; return; } throw new Error("the parameter is incorrect"); } throw new Error("parameter not a string");   }

  // someting code... }

 

這樣一來,咱們僅須要實例化這個實體類,插入用戶交互產生的數據,而後將數據直接導入:

// 某業務方法內 Start

    try{ let user = new entity_user(); // 假設用戶藉助了某種工具就是要給你空字符串
        user.setName(""); // 使用數據服務API將其提交給數據庫交互處理
    } catch(e){ // 其實能夠自定義異常
 } // 某業務方法內 End 

 

沒必要擔憂會將空字符串傳給服務器,由於在這裏咱們已經攔截了。

而自定義異常可使咱們像 Java 那樣一層層的進行捕獲,意味着能夠更精準的處理某個異常。

異常處理中,則能夠調用最頂層的 異常處理API ,根據不一樣級別,給用戶傳達不一樣級別的錯誤信息。

 

哦,對了,數據服務API 是區別於 數據庫交互 的,它們的關係爲:

 

    數據服務   繼承   數據交互  繼承  緩存 

 

也就是說,其實業務層(界面事件處理)根本不去想數據要通過怎樣的流程,要怎樣進行 Ajax 交互。

只須要簡單的一行代碼,塞入對應的實體類,就能夠將實體類的數據提交給後臺服務器。

 

這樣一來,不以爲開發效率提升了不少不少嗎?重要的是,它能夠多人協做,各自編寫各自的代碼。

我老是說各司其職,也只有這樣,才能讓人更專一於某一件事。

 

其實這樣分段編寫,也便於擴展程序的新功能,而不是說:咱們須要新增某個頁面上的功能。就大費周章的重構原先的代碼。。

 

關於異常處理API

全部的代碼必定會發生沒法處理的錯誤,所以異常處理是一個健壯程序所必備的編寫環節。

可是遺憾的是,JavaScript 彷佛對自定義異常並無太大的支持

不過經過不斷迭代,今天的 JavaScript 也已經能夠勝任更加複雜的操做任務。

而自定義異常,我亦想出了一個辦法,以下:

 

class Exception extends Error{ constructor( message ){ super(); this.name = "Exception"; this.message = message || ""; } } /* 空指針異常 */ class NullException extends Error{ constructor( message ){ super(); this.name = "NullException"; this.message = message || ""; } }

 

這是一個簡單的自定義異常編寫方式,參考了 Java 的異常類設計。

咱們能夠看到,Exception 繼承了 Error 類,由於 JavaScript 的機制,咱們只能讓「子異常」也都繼承 Error 類。

如此一來,自定義異常就算完成了。在程序中若是檢測到某種錯誤,可使用下方的方式進行拋出:

throw new NullException();

 

在實際中的效果是這樣的:

 

你能夠將拋出異常的代碼寫在任何函數裏,以後遇到沒法處理的錯誤,即可以拋出了。

而調用的一方則須要對拋出異常的函數進行捕獲,而且進行精確處理。

好比 NullException(空指針異常)、NetWorkException(網絡錯誤)等

 

看到這裏,你可能會有一個疑問:怎麼樣才能精確處理?代碼以下:

try{ throw new NullException(); } catch (e){ if ( e instanceof NullException ) { console.log("發生了空指針異常"); } }

 

 讓咱們再看看若是有多種異常時,代碼可否按所想的如期執行

 

 

利用 instanceof 關鍵字,確實實現了精確捕獲異常的操做。

雖然可能不是最優解,後期若是有更好的方式,我會進行更新並從新寫一篇隨筆,敬請關注吧

 

哦,對了,附上一張事件處理層上的幾行代碼拿到後臺數據的截圖吧:

 

 

 

這個是在控制檯上直接進行編寫的,實際上可能稍微複雜,但也差不到那裏去,大概下方這樣:

 

 DBAPI 使用了自定義異常,這些異常包括了參數異常,網絡異常,空指針異常,未知異常等多種經常使用異常,若是由於網絡問題,那麼 DBAPI 將會拋出如下異常:

 

 這樣能夠清晰的看見觸發的是網絡異常:NetWorkException。

500 狀態碼標示是服務器錯誤,這個錯誤緣由是後臺的數據交互部分未捕獲數據庫交互產生的未知異常而致使。

 

從圖片上能夠看見,事件處理層所作的事情大大減小到了五行代碼。

而 DBService 是我所寫的回調處理的幫助類,能夠認爲這個幫助類屬於視覺層,由於其中的回調函數大都是須要直接渲染 DOM 樹的操做

比方:success 是當 DBAPI 拿到數據成功時所回調的一個函數,所以 success 的回調函數必然須要處理相關的數據渲染進 document 中

因此 DBService 屬於視覺層的幫助類,我想也無可厚非。

 

大概就寫到這裏了。

注:DBAPI 後續可能開源至 前端工具庫 

 

2020/2/6 下午 寫於揭陽

轉載請附上本文博客地址!

相關文章
相關標籤/搜索