TypeScript編寫Vue項目結構解析


使用TypeScript編寫Vue項目也已經有了一段時間,筆者在剛剛使用TypeScript時候也是很茫然,不知道從何下手,感覺使用TypeScript寫項目感覺很累贅並不像JavaScript那么靈活,因為TypeScript對於代碼限制太多,在寫代碼的過程中時不時的就會拋出一個令你意想不到的錯誤,這一點筆者也是爬了不小的坑。可以使用了TypeScript一段時間之后,才知道TypeScript那是真的香(誰都逃不過的真香定理,O(∩_∩)O)。

筆者在之前使用Vue的時候,曾經提到過如何在項目中使用依賴注入的概念,使用依賴注入主要有兩個目的:

  1. 解放Vuex
  2. 將頁面表現與業務邏輯相互拆分

同樣在使用TypeScript編寫項目的過程中同樣也是使用了這種思路,但是也有些許的不一樣的地方,筆者對於項目結構是這樣划分的:

├─api           //  請求數據接口
├─assets        //  靜態資源
├─components    //  組件
│  ├─base           //  基礎組件
│  └─business       //  業務組件
├─domain        //  業務邏輯
├─interface     //  接口
│  ├─other          //  其他接口
│  ├─public         //  公用接口
│  └─views          //  頁面接口
├─middleware    //  中間件
├─mixins        //  混入層
├─router        //  路由層
├─store         //  全局狀態管理
├─style         //  樣式
│  ├─components     //  組件  
│  │  ├─base            // 基礎組件樣式 
│  │  └─business        // 業務組件樣式
│  ├─public         //  公用樣式
│  └─views          //  頁面樣式
└─views         //  頁面

這樣看上去,每一層都有其自己的職責不會項目影響只是相互依賴,對於項目的維護來說是很友好的,這里會出現一個問題,為什么要對項目結構進行划分呢?筆者所理解的是:

  1. 降低各個功能之間的耦合
  2. 靈活調配各個模塊之間的依賴
  3. 每個模塊各盡其責
  4. 使項目有利於維護以及團隊協作

也已經說過各個分層之間有依賴關系,他們之間如何依賴又應該如何調配呢?對於前端來講無論是什么項目,都是依賴於頁面展開工作的,那么必定是以views層為中心,views又需要依賴於routerrouter需要注入到vue實例當中。

上圖中assets沒有提及到,對於assets用來存儲一些靜態文件,這一層盡量不要去與基礎組件之間耦合在一起,這樣做的話若其他項目用到該組件的時候,該組件就變了味道。

其實這里筆者想着重說的一點是,domainviews之間的引用,對於我來說業務層是用來拆分業務,使viewsdomain之間各做自己的事情,views更加的去關注頁面該如何去展示數據,然而domain更加的關注業務邏輯部分。

domeDomain.ts

//  引入api
import domeAPI from "@/api/domainAPI.ts";
//  引入intaerface
import {tableItemInterface,queryDataInterface} from "@/interface/domeInterface.ts";

class DomeDomain {

    public async getTableList (target: Object, propertyName: string, propertyDescriptor: PropertyDescriptor):PropertyDescriptor{
        const data:queryDataInterface = propertyDescriptor.value();
        propertyDescriptor.value = async function ():Promise<tableItemInterface[]>{
            //  這里是業務邏輯
            const {result:tableItemInterface[]} = await domeAPI.getTableList(data);
            return result as Promise<tableItemInterface[]>;
            
        }
        return propertyDescriptor;
    }
}
export default DomeDomain;

dome.vue

<template>
  <div>
    <el-table :data="list"/>
  </div>
</template>

<script lang="ts">
import { Component, Vue} from 'vue-property-decorator';

//  引入intaerface
import {tableItemInterface,queryDataInterface} from "@/interface/domeInterface.ts";

//  引入業務類
import DomeDomain from "@/domain/DomeDomain.ts";
const domeDomain = new DomeDomain();

@Component()
export default class AddChargesButton extends Vue {

    private tableList:tableItemInterface[] = [];
    private queryData:queryDataInterface = {};
    private pageInfo:{page:number,size:number}:{ page:1,
                                                 size:20};
    
    @domeDomain.getTableList
    private async getTableList(data:queryDataInterface):Promise<{pageInfo:any,query:queryDataInterface}>{
        let {queryData:query,pageInfo} = this;
        return {query,pageInfo};
    }
    
    private async queryTableList():Promise<void>{
        try{
            this.pageInfo.page = 2;
            let {list} = await this.getTableList();
            this.tableList = list;
        }catch(error){
            this.$message.error(error.message || error);
        }
    }
    
}
</script>

在上面的代碼中,domeDomain中定義了一個getTableList的方法,因為這個地方需要使用修飾符的形式去修飾方法,用於去請求數據,然而在頁面中的方法,可以無限次的復用,調用該方法的時候也可以對其參數進行調整之后再進行數據請求。

不用再去擔心參數的的傳遞,只需要把所有的參數整合好,調用其對應的獲取數據的方法就行了很方便。同樣也達到了業務和頁面表現的拆分。然而好處並不僅僅只有這些。相對應的在項目中同樣解脫了store。讓store做應該做的事情。

如果只是為了拆分業務的話不僅僅只限定於這一中方法,同樣也可以直接再頁面中使用domain業務類的實例,去調用實例的方法,或者是使用混入把業務部分使用混入的形式混入到對應的頁面中。

對於裝飾器還有很多更高深的用法,我也在不斷的摸索中,個人覺得這些東西都是有利於項目的開發的。寫這篇文章只是想和更多同學一起交流學習,若文章中又什么不對的地方,可以在下方留言討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM