zoukankan      html  css  js  c++  java
  • Vue3结合TS项目开发实践:Composition API的风格理念、关注点分离、如何组织TS进行项目开发(采用声明文件来管理接口及所需类型/目录结构推荐)

    一、composition Api

      compositon Api的本质体现在代码里面,也就是一个setup函数,在这个setup函数中,返回的数据,会用到该组件的模板中。return的这个对象,一定程度上,代表了之前vue2中的data属性。

      这时候,对于大多数初学者来说,可能存在的疑惑就是,那么我能不能定义options Api的写法,比如data、computed、watch、methods等等。这里我需要明确的是,Vue3是完全兼容Vue2的这种options Api的写法,但是从理念上来说,更加推荐setup的方式,来写我们的组件。

      原因如下:Vue3的存在,本身是为了解决Vue2的问题的,Vue2的问题就是在于,聚合性不足,会导致代码越来越臃肿!setup的方式,能够让data、方法逻辑、依赖关系等聚合在一块,更方便维护。

      也就是说,以后我们尽量不要写单独的data、computed、watch、methods等等,不是Vue3不支持,而是和Vue3的理念违背

      components属性,也就是一个组件的子组件,这个配置在Vue2和3的差异不大,Vue2怎么用,Vue3依然那么用。

      缺点:从options api切换到composition api最大的问题就是没有强制的代码分区,如果书写的人没有很好的代码习惯,那么后续的人将会看的十分难受。所以在写代码时需要注意做到很好的“关注点分离”:

    1、自我代码分区并且尽量抽离方法(写好注释),分区如下:

    (1)相关引入

    (2)响应式数据、props、emit 定义

    (3)生命周期以及 watch 书写

    (4)方法定义

    (5)方法、属性暴露

    2、组件抽离:将页面拆成两个文件夹,一个为 views,一个为 components

      views 和 components 文件夹下有各自的文件。views 文件夹中为页面入口,掌管数据,而 components 则为页面中一些组件抽离。如果是公共组件,再抽离到 components 文件夹下其他位置。

    3、hook 抽离:尽可能将逻辑抽离,并不一定要进行复用。

    二、关注点分离

      关注点分离,应该分两层意思:第一层意思就是,Vue3的setup,本身就把相关的数据,处理逻辑放到一起,这就是一种关注点的聚合,更方便我们看业务代码。

      第二层意思,就是当setup变的更大的时候,我们可以在setup内部,提取相关的一块业务,做到第二层的关注点分离

    import { useStore } from "vuex";
    import { useRouter } from "vue-router";
    import { defineComponent, ref, computed } from 'vue';
    import useMerchantList from './merchant.js';
    export default defineComponent({
        name: 'Gift',
        setup() {
            const counter = ref(0);
            const router = useRouter();   // router 的使用
            const onClick = () => {
                router.push({ name: "AddGift" });
            }
            // 在该示例中,我们把获取商家列表的相关业务分离出去。也就是下面的merchant.ts
            const {merchantList} = useMerchantList();
            return {
                counter,
                onClick,
                merchantList
            }
        }
    })
    
    // merchant.ts
    import { getMerchantlist } from "@/api/rights/gift";
    import { ref, onMounted } from "vue";
    export default function useMerchantList(): Record<string, any> {
      const merchantList = ref([]);
      const fetchMerchantList = async () => {
        let res = await getMerchantlist({});
        merchantList.value = res?.data?.child;
      };
      onMounted(fetchMerchantList);  // 周期函数的使用
      return {
        merchantList
      };
    }

    三、TypeScript支持

      TS与Vue3项目开发息息相关,所以真的想用Vue3,我们还是得了解TS的使用。下面我们主要了解在业务场景中如何组织TS。

      使用TS进行业务开发,一个核心的思维是,先关注数据结构,再根据数据结构进行页面开发。以前的前端开发模式是,先写页面,后关注数据。

      比如要写一个礼品列表的页面,我们可能要定义这么一些interface。总而言之,我们需要关注的是:页面数据的interface、接口返回的数据类型、接口的入参类型等等。

    // 礼品创建、编辑、列表中的每一项,都会是这个数据类型。
    interface IGiftItem {
      id: string | number;
      name: string;
      desc: string;
      [key: string]: any;
    }
    // 全局相应的类型定义
    // 而且一般来说,我们不确认,接口返回的类型到底是什么(可能是null、可能是对象、也可能是数组)
    所以使用范型来定义interface
    interface IRes<T> { code: number; msg: string; data: T } // 接口返回数据类型定义 interface IGiftInfo { list: Array<IGiftItem>; pageNum: number; pageSize: number; total: number; }

      在一个常见的接口请求中,我们一般使用TS这么定义一个数据请求,数据请求的req类型,数据请求的res类型

    export const getGiftlist = (
      params: Record<string, any>
    ): Promise<IRes<IGiftInfo>> => {
      return Http.get("/apis/gift/list", params);
    };

      目录结构:在你编写大型前端项目时,推荐使用声明文件(Declaration Files)来管理接口或其他自定义类型。声明文件一般是 <module_name>.d.ts 的形式,在这类文件中只定义模块中的类型,没有任何实际的实现逻辑。声明文件可以单独放在一个目录里,我喜欢命名为 interfaces,意思就是接口。这样,就可以充分将抽象类型、方法、属性等与实际内容分开。以下例子是一个集成了 TS 的 Vue 项目目录。

    .
    ├── babel.config.js   // Babel 编译配置文件
    ├── jest.config.ts   // 单元测试配置文件
    ├── package.json    // 项目配置文件
    ├── public       // 公共资源
    ├── src         // 源代码目录
    │   ├── App.vue     // 主应用
    │   ├── assets     // 静态资源
    │   ├── components   // 组件
    │   ├── constants    // 常量
    │   ├── i18n      // 国际化
    │   ├── interfaces   // 声明文件目录
    │   │   ├── components  // 组件声明
    │   │   ├── index.d.ts  // 主声明
    │   │   ├── layout   // 布局声明
    │   │   ├── store    // 状态管理声明
    │   │   └── views    // 页面声明
    │   ├── layouts     // 布局
    │   ├── main.ts     // 主入口
    │   ├── router     // 路由
    │   ├── shims-vue.d.ts // 兼容 Vue 声明文件
    │   ├── store      // 状态管理
    │   ├── styles     // CSS/SCSS 样式
    │   ├── test      // 测试
    │   ├── utils      // 公共方法
    │   └── views      // 页面
    └── tsconfig.json    // TS 配置文件

      其中可以看到,interfaces 这个目录跟其他模块在同一级,而其子目录则是其他模块所对应的类型声明。编写代码前,尽量先创建并设计声明文件内容,设计好之后再到实际的模块下完成实现。当然,这个 “定义 -> 实现“ 是一个不断迭代的过程,可能实现过程中发现有类型设计问题,可以回到声明文件中完善定义,再到实现代码里进行优化。

  • 相关阅读:
    sfs2x 连接 mongodb
    java websocket
    webstorm 4.0 注册码
    解决 sfs2 admin tool 找不到扩展
    window 注册表五大类
    opengl 学习第二日
    java google Protobuf
    扩展 java sencha touch PhonegapPlugin
    sencha touch2 kryonet socket phonegap 通信 作者:围城
    sencha touch2 layout 笔记
  • 原文地址:https://www.cnblogs.com/goloving/p/15418547.html
Copyright © 2011-2022 走看看