<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          也許跟大家不太一樣,我是這么用TypeScript來寫前端的

          共 7834字,需瀏覽 16分鐘

           ·

          2023-08-24 14:23

          點(diǎn)擊上方  前端Q ,關(guān)注公眾號

          回復(fù) 加群 ,加入前端Q技術(shù)交流群

          一、當(dāng)前一些寫前端的騷操作

          先羅列一下見到過的一些寫法吧:)

          1. interface(或Type)一把梭

          掘金上很多文章,一提到 TypeScript,那不得先用 interface 或者 type 來聲明個(gè)數(shù)據(jù)結(jié)構(gòu)嗎?像這樣:

                
                type User = {
              nickname: string
              avatar?: string
              age: number
          }

          interface User {
              nickname: string
              avatar?: string
              age: number
          }

          然后其他方法限制下入?yún)㈩愋?,搞定,我掌握?TypeScript 了,工資不得給我漲3000???

          這里說明一下, 我司 不允許 直接使用 interface type 來定義非裝飾器參數(shù)和配置性參數(shù)之外其他 任何數(shù)據(jù)類型

          2. 類型體操整花活

          要么把屬性整成只讀了,要么豬狗類型聯(lián)合了,要么豬尾巴搞丟了,要么牛真的會(huì)吹牛逼了。

          類型體操確實(shí)玩出了很多花活。昨天說過了:TypeScript最好玩的就是類型體操, 也恰好是最不應(yīng)該出現(xiàn)的東西

          3. hook 的無限神話

          不知道什么時(shí)候開始,hook 越來越流行。聽說不會(huì)寫 hook 的前端程序員,已經(jīng)算不上高階程序員了, 不 use 點(diǎn)啥都展示不出牛逼的水平。

          4. axios 攔截大法好

          隨便搜索一下 axios 的文章, 沒有 攔截器 這個(gè)關(guān)鍵詞的文章都算不上 axios 的高端用法了。

          二、 我們一些不太一樣的前端騷操作

          昨天的文章有提到一些關(guān)于在前端使用 裝飾器 來實(shí)現(xiàn)一些基于配置的需求實(shí)現(xiàn), 今天其實(shí)想重點(diǎn)聊一聊如何在前端優(yōu)雅的面向?qū)ο蟆?/p>

          寫過 Java、SpringBootJPA 等代碼的后端程序員應(yīng)該非常熟悉的一些概念:

          • 抽象:萬物都可抽象成相關(guān)的類和對象
          • 面向?qū)ο螅豪^承、封裝、多態(tài)等特性的面向?qū)ο笤O(shè)計(jì)思維
          • 切面:沒有什么是切一刀解決不了的,如果一刀不行, 那就多來幾刀。
          • 注解:沒有什么常量是不能使用注解來配置的, 也沒有什么注解是切面想切還能躲得掉的
          • 反射:沒有什么是暴力拿取會(huì)失敗的, 即使失敗也沒有異常是丟不出來的
          • 實(shí)體:沒有什么是不能抽象到實(shí)體上的, 萬物皆唯一。
          • 很多:還有很多,以上描述比較主觀和隨意。

          于是我們開始把后端思維往前端來一個(gè)個(gè)的轉(zhuǎn)移:)

          1. 抽象和面向?qū)ο?/span>

          與后端的交互數(shù)據(jù)對象、 請求的API接口都給抽象到具體的類上去,于是有了:

          • Service API請求類
                
                abstract class AbstractService{
              // 實(shí)現(xiàn)一個(gè)抽象屬性 讓子類們實(shí)現(xiàn)
              abstract baseUrl!: string
              
              // 再實(shí)現(xiàn)一些通用的 如增刪改查之類的網(wǎng)絡(luò)請求
              // save()
              
              // getDetail()
              
              // deleteById()
              
              // select()
              
              // page()
              
              // disabled()
              
              // ......
          }

          • Entity 數(shù)據(jù)實(shí)體基類
                
                abstract class AbstractBaseEntity<S extends AbstractService> {
              abstract service!: AbstractService

              // 任何數(shù)據(jù)都是唯一的 ID
              id!: number
              
              // 再來實(shí)現(xiàn)一些數(shù)據(jù)實(shí)體的更新和刪除方法
              save(){
                  await service.save(this.toJson())
                  Notify.success("新增成功")
              }
              
              delete(){
                  service.deleteById(this.id)
                  Notify.success("刪除成功")
              }
              
              async validate(scene: EntityScene):Promise<void>{
                  return new Promise((resolve,reject)=>{
                      // 多場景的話 可以Switch
                      if(...){
                          Notify.error("XXX校驗(yàn)失敗")
                          reject();
                      }
                      resove();
                  })
              }
              // ......
          }

          • 子類的實(shí)現(xiàn):)
                
                class UserEntity extends AbstractUserEntity<UserService>{
              service = new UserService()
              
              nickname!: string
              age!: number
              avatar?: string
              
              // 用戶是否成年人
              isAdult(): boolean{
                  return this.age >= 18
              }
              
              async validate(scene: EntityScene): Promise<void> {
                  return new Promise((resove,reject)=>{
                      if(!this.isAdult()){
                          Notify.error("用戶未成年, 請確認(rèn)年齡")
                          reject();
                      }
                      await super.validate(scene)
                  })
              }
              
          }

          • View 視圖調(diào)用
                
                <template>
              <el-input v-model="user.nickname"/>
              <el-button @click="onUserSave()">創(chuàng)建用戶</el-button>
          </template>
          <script setup lang="ts">
          const user = ref(new UserEntity())
          async function onUserSave(){
              await user.validate(EntityScene.SAVE);
              await user.save()
          }
          </script>

          2. 裝飾器/切面/反射

          裝飾器部分的話,昨天的文章有提到一些了,今天主要所說反射和切面部分。

          TypeScript 中, 其實(shí)裝飾器本身就可以理解為一個(gè)切面了, 這里與 Java 中還是有很多不同的, 但概念和思維上是基本一致的。

          反射 ReflectTypeScript 中比較坑的一個(gè)存在, 目前主要是依賴 reflect-metadata 這個(gè)第三方庫來實(shí)現(xiàn), 將一些元數(shù)據(jù)存儲到 metadata 中, 在需要使用的時(shí)候通過反射的方式來獲取??梢詤⒖歼@篇文章:TypeScript 中的元數(shù)據(jù)以及 reflect-metadata 實(shí)現(xiàn)原理分析[1]

          在實(shí)際使用中, 我們早前用的是 class-transformer 這個(gè)庫, 之前我對這個(gè)庫的評價(jià)應(yīng)該是非常高的: “如果沒有 class-transformer 這個(gè)庫, TypeScript 狗都不寫?!?/code>

          確實(shí)很棒的一個(gè)庫,但是在后來,我們寫了個(gè)通用的內(nèi)部框架, 為了適配 微信小程序端 以及 uniapp 端, 再加上有一些特殊的業(yè)務(wù)功能以及 class-transfromer 的寫法和命名方式我個(gè)人不太喜歡的種種原因, 我們放棄了這個(gè)庫, 但我們仿照了它的思想重新實(shí)現(xiàn)了一個(gè)內(nèi)部使用的庫,做了一些功能的閹割和新特性的添加。

          核心功能的一些說明

          • 通過反射進(jìn)行數(shù)據(jù)轉(zhuǎn)換

          如將后端API返回的數(shù)據(jù)按照前端的數(shù)據(jù)結(jié)構(gòu)強(qiáng)制進(jìn)行轉(zhuǎn)換, 當(dāng)后端數(shù)據(jù)返回亂七八糟的時(shí)候,保證前端數(shù)據(jù)在使用中不會(huì)出現(xiàn)任何問題, 如下 demo

                
                class UserEntity {
          @Type(String) phone!: string;
          @Type(RoleEntity) roleInfo!: RoleEntity:
          @Type(DeptEntity) @List @Default([]) deptInfoList!: DeptEntity[]
          @Type(Boolean) @Default(false) isDisabled!: boolean
          }
          • 通過反射進(jìn)行配置的存儲和讀取

          這個(gè)在昨天的文章中有講到一部分, 比如配置表單、表格、搜索框、權(quán)限 等

          3. 再次強(qiáng)調(diào)面向?qū)ο?/span>

          為了整個(gè)前端項(xiàng)目的工程化、結(jié)構(gòu)化、高度抽象化,這里不得不再次強(qiáng)調(diào)面向?qū)ο蟮脑O(shè)計(jì):)

          • 這是個(gè)拼爹的社會(huì)

          一些通用的功能,一旦有復(fù)用的可能, 都可以考慮和嘗試讓其父類進(jìn)行實(shí)現(xiàn), 如需要子類傳入一些特性參數(shù)時(shí), 可以使用抽象方法或抽象屬性(這可是Java中沒有的)來傳入父類實(shí)現(xiàn)過程中需要的特性參數(shù)。

          • 合理的抽象分層

          將一些特性按照不同的抽象概念進(jìn)行組合與抽離,實(shí)現(xiàn)每個(gè)類的功能都是盡可能不耦合,實(shí)現(xiàn)類的單一職責(zé)。如存在多繼承, 在考慮實(shí)現(xiàn)類的實(shí)現(xiàn)成本前提下,可考慮抽象到接口 interface 中。

          • 還有很多,有空再一一列舉

          4. 嚴(yán)格但又有趣的 tsdoc

          我們先來看一些注釋的截圖吧:)

          6a125f5f3425e70aa81b6f2e2ab6ab95.webpimage.png fb677f28870aaa52a2ff293a37846855.webpimage.png 7b15331ba6f3f0f5c0b931fba478f707.webpimage.png

          一些詳細(xì)的注釋、棄用的方法、選填的參數(shù)、傳入?yún)?shù)后可能影響或依賴的其他參數(shù),在注釋里寫好玩的 emoji或者圖片,甚至是 直接在注釋里寫調(diào)用 demo, 讓調(diào)用方可以很輕松愉快的對接調(diào)用, 玩歸玩, 確實(shí)對整體項(xiàng)目的質(zhì)量有很大的幫助。

          三、 寫在最后

          中午跟同事吃飯聊了聊現(xiàn)在國內(nèi)大前端的一個(gè)狀態(tài), 當(dāng)時(shí)聊到一個(gè)關(guān)鍵詞 舒適區(qū), 還有前端整個(gè)技術(shù)棧過于靈活的一些優(yōu)缺點(diǎn), 幾個(gè)大老爺們都發(fā)出了一些感慨, 如果前端能夠更標(biāo)準(zhǔn)化一些, 像 Java 一樣, 說不定前端還能上升幾個(gè)高度。

          是的, 我還是那個(gè) Java 仔, 是, 也不僅僅是。

          That's all, 今天水的文章到此結(jié)束。

          2023-07-26 17:28:28 更新

          代碼已經(jīng)在Github開源:github.com/HammCn/AirP…[2]

          參考資料

          [1]

          https://juejin.cn/post/7255561917682991163?searchId=202307251249318EA324C7464742541CBF

          [2]

          https://github.com/HammCn/AirPower4T

          [3]

          https://juejin.cn/column/7249148919505682491


          關(guān)于本文

          作者:Hamm

          https://juejin.cn/post/7259562014417813564

          ffb92af35021374eeacb9d5d2b6b0d84.webp

          往期推薦


          寫給5年前端妹子的三萬字腳手架教程
          dc53eac9131884858bc0cb87c5edd78f.webpVue3寫了hook三天,治好了我的組件封裝強(qiáng)迫癥
          8a4713fac16adc02a2e354e63a039c0c.webp抖音前端團(tuán)隊(duì)的設(shè)計(jì)稿轉(zhuǎn)代碼 — Semi D2C 實(shí)踐方案
          8a4713fac16adc02a2e354e63a039c0c.webp
          最后

          • 歡迎加我微信,拉你進(jìn)技術(shù)群,長期交流學(xué)習(xí)...

          • 歡迎關(guān)注「前端Q」,認(rèn)真學(xué)前端,做個(gè)專業(yè)的技術(shù)人...

          ad04d301c54271510192c00568f20e67.webp點(diǎn)個(gè)在看支持我吧 1f4c1823d247dcdd4cbe108aa62ba5c0.webp
          瀏覽 30
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉久久久久 | 久久久久久久国产精品 | 国产成人精品AV在线观 | 久久久久无码精品国产sm大站 | 色老板视频凹凸精品视频 |