談談「數據模型」是如何助力前端開發的

1、定義

數據模型是數據特徵的抽象,用來抽象定義一個業務對象。假如如今有一個用戶模型,若是要抽象的描述這個用戶對象,能夠按照以下來定義:前端

const UserModel = {
    name:{
        type:String,
        property:'name',
        value:'zhangshang'
    },
    age:{
        type:Number,
        property:'age',
        value:26
    }
}

複製代碼

其中,type聲明數據的類型,property指明映射路徑,value是默認值。這裏先有個大概的概念就行,後面我會經過實例來詳細展開。vue

2、動機

前面介紹了數據模型的定義,那和前端開發又有什麼關係呢?前端又不須要和數據庫打交道,前端開發主要就是拿到數據顯示就完了,那爲何須要數據模型呢?它是怎麼助力前端開發的呢?咱們先來看一下如下幾個場景。ios

場景一

咱們在前端開發中,經過ajax請求拿到服務端數據,而後將數據顯示在視圖上,常常會寫以下代碼:git

如示例,假如咱們要顯示用戶頭像,經過取到headUrl的值綁定在src屬性上便可。由於是異步加載獲取的數據,在最終獲取到headUrl的值以前,咱們須要先判斷cardData.buyerExperienceInfo的存在性,而後才能取值,不然在視圖初次渲染以前會報以下錯誤:github

在這種場景下,咱們在開發中就不得不寫一些防護性的代碼,長此以往,項目中相似代碼會愈來愈多,碰到層級深的,防護性代碼就會寫的愈來愈噁心。另外還有的就是,若是服務端在這中間某個字段刪掉了,那就又得特殊處理了,不然會有一些未知的非空錯誤報錯,這種編碼方式會致使前端嚴重依賴服務端定義的數據結構,很是不利於後期維護。ajax

場景二

平時開發中,咱們拿到了服務端返回的數據,有些不是標準格式的,是沒法直接在視圖上直接使用的,是須要而外格式化處理的,好比我司服務端返回的的價格字段單位統一是,跟時間相關的字段統一是毫秒值,這個時候咱們在組件的生命週期內,就不得不而外增長一些對數據處理的邏輯,還有就是這部分處理在不少組件都是公用的,咱們就不得不頻繁編寫相似的代碼,數據處理邏輯沒有獲得複用數據庫

場景三

在用戶作了一些交互後,須要將一些數據存儲到服務端,這個時候咱們拿到的數據每每也是非標準的,就好比你要提交個表單,其中有個價格字段,你拿到價格單位多是百位的,而服務端須要的單位必須是分位的,這個時候在提交數據以前,你又得對這部分數據進行處理,還有就是有些接口的參數是json字符串形式的,多是多級嵌套的,你還要須要特地構造這樣的參數數據格式,致使開發中編寫了太多與業務無關的邏輯,隨着項目逐漸擴大或者維護人員更迭,項目會愈來愈很差維護。json

3、數據模型

在碰到這麼多痛點以後,我就在想如何解決,回顧以上場景,總結下來存在如下幾個問題:axios

  1. 先後端數據結構沒有解耦,前端在應對不定的服務端數據結構前提下,須要編寫過多的保護性代碼,不利於維護的同時,代碼健壯性也不高。
  2. 基礎數據邏輯處理沒有和UI視圖解耦,容易阻塞視圖渲染,同時,在視圖組件上存在太多的基礎數據邏輯處理,沒有有效複用。

因此,這裏我引入了數據模型的概念,那經過數據模型如何解決這類問題呢?下面我將經過兩個實際案例來進一步呈現上述場景,以及引入了數據模型以後是如何解決的。後端

4、案列功能

這個案例使用Vue開發,功能很簡單,就是經過ajax請求從服務端拿到數據,而後經過vue視圖進行展示,效果以下:

5、常規實現

代碼只展現主要功能代碼,非完整實現

1.請求數據

created生命週期內,向服務端請求數據。

2.數據處理

獲取到數據以後,由於拿到的數據和最終UI上顯示的格式不一致,須要轉化一下數據格式。

3.渲染數據

給當前Vue實例賦值,而後在template裏經過模板語法進行渲染

能夠看到常規寫法,模板語法裏面的寫法特別不優雅,各類保護性代碼(條件判斷)

6、經過數據模型方式處理

1.定義數據模型

首先,咱們能夠專門建一個名叫model的文件夾,專門用來存放模型,而後定義卡片模型cardModel,其中數據定義格式以下:

  1. type 必填,用來描述該字段的類型,支持String、Number、Date等類型
  2. property 必填,數據路徑,對應服務端數據結構的取值路徑
  3. value 選填,數據默認值,可不填

經過new Model()進行初始化,後續只須要經過model.parse(data)或者model.traverse(data)這個兩個方法就能夠完成正向映射和反向映射的過程。

具體的使用方式能夠查看API

2.請求數據

經過axios請求接口,在拿到數據以後,調用parse方法解析數據,在解析的過程當中會去作賦值操做以及數據格式化。

3.數據渲染

拿到數據,賦值給vue組件實例後,在template模板裏面直接使用咱們事先定義好的數據字段,不須要再去寫相似a&a.b&a.b.c這樣的代碼,且無論服務端數據字段如何變化,視圖渲染都不受影響,從而實現和服務端數據結構進行解耦。

與此同時,針對相似價格、時間等須要格式化的數據,咱們能夠直接使用,不須要再去寫對應的格式化處理邏輯,從而專一於視圖組件渲染處理。

經過引入數據模型,咱們能夠看到在模板裏面引入變量的時候不須要進行各類判斷,寫法很是優雅,並且健壯性很強,即便服務端某個字段沒有返回,咱們這裏也不會所以存在報錯的可能性。且在腳本里面沒有了數據格式化處理代碼,從而不會由於數據處理邏輯代碼可能存在的錯誤,打斷UI的渲染。從而帶來的更大好處是,隨着項目的不斷迭代,數據和視圖有着清晰的劃分,前端和後端進行了解耦,項目的可維護性獲得保證。

4.反向映射

在庫裏面,還提供了traverse方法,和parse方法相似,區別是traverse是反向數據生成以及格式還原。

7、模型庫的原理

最後,我來說講這個數據模型庫(ducker-model)的實現原理,源碼總共不到200行,仍是簡單的,能夠經過這裏下載查看,主要實現邏輯以下:

  1. 聲明一個名叫Model的類。
  2. 經過new Model(options),傳入模型結構,初始化數據模型屬性,對外主要使用的是parsetraverse方法,
  3. parse方法的實現過程就是遍歷模型數據結構,拿到每一個屬性的數據路徑,而後根據這個路徑去取傳入的的數據裏面的數據,最後給事先定義好的屬性賦值,在賦值的過程當中,能夠根據type格式化一些相似時間、價格類型的數據。
  4. traverse方法恰好和parse相反,一樣是遍歷數據模型結構,拿到每一個屬性的數據路徑,而後根據這個數據路徑去設置一個新對象的值,這期間,反向格式化數據類型,最後返回這個新對象。

8、更進一步

目前這個庫還很基礎,只支持了一些常規的功能,能作的事情還不少,好比:

  1. 目前每次拿到請求一次數據以後都須要解析一次,那是否有個緩存機制,在數據沒有變更的時候,直接從緩存取數據呢,或者能夠直接watch這個解析以後的數據,作到數據變更,視圖變更呢?
  2. 現有支持的類型還不夠多,能夠根據具體業務狀況增長一些類型,以應對更多場景,提供可擴展的機制。
  3. 插件機制,好比表單處理,咱們是否能夠在數據模型定義的時候就定義好字段格式,在提交的時候就能夠直接進行格式檢測,拋出提醒呢?
  4. 目前的操做方式還比較適合純粹的渲染式組件,如何和複雜的攜帶業務交互的組件融合也是須要考慮的。
  5. ... ...

文章末尾會提供模型庫下載地址,有須要的能夠在此基礎上進行擴展,歡迎一塊兒完善這個庫,另外,案例demo的地址也提供了,歡迎下載學習理解。

9、源碼下載

案例:ducker-model-demo

模型庫:ducker-model

相關文章
相關標籤/搜索