typescript做界面-Vue+TypeScript+元素

2023-08-23 0 1,701 百度已收录

古语云:“工欲善其事,必先利其器”。 我们后端领域也是如此。 想要做好一个项目,就必须有一个完整的项目架构作为支撑,才能够更好的Teamwork,为业务做好嫁衣。

创建新项目时,通常需要一些基本配置。 当我们没有基础模板时,我们需要从其他项目中复制过来,甚至需要自己重新绘制一些工具类。 这个时候我们就急需这个基础模板。 。

源地址

有新项目的‍,并且想尝试 Vue + TypeScript 开发的可用这套模板

基本功能列表

【红色部分尚未完成】

创建项目

选择 [Vue Cli](https://cli.vuejs.org/zh/guide/) 脚手架 快速创建
`vue create xxx`

目录结构

mac 下安装 brew 

/bin/zsh -c "$(curl-fsSL)"

安装 tree

酿造安装树

typescript做界面-Vue+TypeScript+元素

树形列表目录结构

├── README.md			说明文件
├── babel.config.js		bable 配置文件
├── jest.config.js		单元测试配置文件
├── package.json		项目信息文件
├── public				
│   ├── favicon.ico
│   ├── index.html
│   ├── other.html
│   └── static			静态资源文件
│       ├── css			
│       │   └── reset.css
│       └── worker		Web Workers 文件夹(根据 Web Workers 的特殊性、需要放在在服务器)
│           └── test.worker.js
├── src
│   ├── api				api 管理,按多页面分文件夹
│   │   ├── default-page
│   │   │   ├── index.ts			导出 api
│   │   │   └── testModule.api.ts	页面下的小模块 api
│   │   └── other-page
│   │       ├── index.ts
│   │       └── newsModule.api.ts
│   ├── assets			静态资源文件,但会经过 webpack 进行编译,不需要编译的可以放到 public 目录下
│   │   └── styles		公共样式(基础样式、其它公用样式)
│   │       ├── common.scss
│   │       └── pageAnimate.scss
│   ├── components
│   │   ├── business	业务组件
│   │   │   └── xw-list
│   │   │       ├── index.ts
│   │   │       ├── index.type.ts
│   │   │       └── index.vue
│   │   ├── common		基础组件
│   │   │   ├── xw-pagination
│   │   │   │   ├── index.type.ts
│   │   │   │   └── index.vue
│   │   │   ├── xw-search
│   │   │   │   ├── generateEl.vue
│   │   │   │   ├── index.type.ts
│   │   │   │   └── index.vue
│   │   │   └── xw-table
│   │   │       ├── coustomColumn.vue
│   │   │       ├── generateElTable.ts
│   │   │       ├── generateElTableColumn.ts
│   │   │       ├── index.type.ts
│   │   │       └── index.vue
│   │   └── example		例子文件
│   │       ├── langExample.vue
│   │       ├── requestExample.vue
│   │       ├── vuexExample.vue
│   │       ├── workerExample.vue
│   │       └── wsExample.vue
│   ├── directive		指令
│   │   ├── animate.directive.ts
│   │   ├── copy.directive.ts
│   │   ├── debounce.directive.ts
│   │   ├── draggable.directive.ts
│   │   ├── emoji.directive.ts
│   │   ├── index.ts
│   │   ├── longpress.directive.ts
│   │   └── permissions.directive.ts
│   ├── i18n			国际化
│   │   ├── index.ts
│   │   └── lang
│   │       ├── en.ts
│   │       └── zh.ts
│   ├── layout			项目布局
│   │   ├── base.layout.vue
│   │   └── other.layout.vue
│   ├── mock			mock 数据
│   │   └── index.js
│   ├── plugins			项目插件
│   │   ├── config.ts
│   │   ├── index.ts
│   │   └── lazyLoad.plugin.ts
│   ├── router			路由管理,按多页面分文件夹
│   │   ├── config.ts
│   │   ├── default
│   │   │   └── module1.router.ts	页面下的小模块 api
│   │   ├── globalHook.ts			全局路由钩子
│   │   ├── index.ts				导出所有路由
│   │   └── other
│   │       └── module1.router.ts
│   ├── shims-tsx.d.ts
│   ├── shims-vue.d.ts
│   ├── store			Vuex管理,按多页面分文件夹
│   │   ├── common					基础的 Vuex 模块
│   │   │   ├── permissions.vuex.ts
│   │   │   └── user.vuex.ts
│   │   ├── default
│   │   │   └── home.vuex.ts
│   │   └── index.ts				导出基础的 Vuex 模块
│   ├── theme			主题
│   │   ├── fonts
│   │   │   ├── element-icons.ttf
│   │   │   └── element-icons.woff
│   │   └── index.css
│   ├── types			类型控制文件(提供语法提示)
│   │   └── vue.d.ts
│   ├── utils			工具函数文件夹
│   │   ├── common.ts				通用的 js 函数
│   │   ├── dom.ts					dom 操作相关的
│   │   ├── eventCenter.ts			发布订阅者模式(事件管理中心)
│   │   ├── progressBar.ts			页面进度条
│   │   ├── readyLocalStorage.ts	读取本地存储数据(用户信息、token、权限等)并存到 Vuex 中
│   │   ├── request					Ajax 请求封装
│   │   │   ├── index.ts
│   │   │   ├── index.type.ts
│   │   │   └── request.ts
│   │   ├── requestInstance.ts		Ajax 实例
│   │   ├── useElement.ts			按需使用 Element-ui
│   │   └── ws.ts					WebSocket 通讯
│   └── views			按多页面分文件夹
│       ├── 404.vue
│       ├── default-page	
│       │   ├── App.vue
│       │   ├── main.ts
│       │   └── test-module			小模块
│       │       ├── home			具体页面
│       │       │   └── index.vue
│       │       └── home2
│       │           └── index.vue
│       ├── login.vue
│       └── other-page
│           ├── App.vue
│           ├── main.ts
│           └── news-module			小模块
│               ├── news1			具体页面
│               │   ├── components	页面内组件
│               │   │   └── coustomColumnHeader.vue
│               │   └── index.vue
│               └── news2
│                   ├── components
│                   │   └── coustomColumnHeader.vue
│                   └── index.vue
├── tests
│   └── unit
│       └── example.spec.ts
├── tsconfig.json
├── vue.config.js		webpack 配置文件
├── yarn-error.log
└── yarn.lock
└── .env.development 	本地环境配置
└── .env.production		生产环境配置
└── .env.staging		测试环境配置

环境分辨率

通过webpack提供的模式来实现不同的

# 指定模式
NODE_ENV = "development"
# Ajax 地址
VUE_APP_REQUEST_URL = 'http://localhost:8080'

.env.生产

NODE_ENV = "production"
VUE_APP_REQUEST_URL = 'http://prod.com'

.env.staging

NODE_ENV = "production"
VUE_APP_REQUEST_URL = 'http://staging.com'

包.json

"scripts": {
  "serve": "vue-cli-service serve --mode development",		// 开发
  "build:stage": "vue-cli-service build --mode staging",	// 测试
  "build": "vue-cli-service build"							// 生产
}

路由手动管理、按需加载按需加载import()方法【推荐】

constApp=()=>import(/*webpackChunkName:app*/'./app.vue')

typescript做界面-Vue+TypeScript+元素

/*webpackChunkName:app*/组件分块

表单的异步组件

异步组件

constApp=resolve=>require(["./app.vue"],resolve)

手动路由

通过webpack的require.context引入递归模块

require.context(
  directory: String,
  includeSubdirs: Boolean /* 可选的,默认值是 true */,
  filter: RegExp /* 可选的,默认值是 /^./.*$/,所有文件 */,
  mode: String  /* 可选的, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once',默认值是 'sync' */
)

require.context 的参数不能接收变量

【好处:减少多人开发时的冲突,忘记引入新模块】

API管理

api统一管理。 项目中,我们其中一个页面的【增删改查】url都是统一的,只会改变请求的形式,所以url是集中管理的

typescript做界面-Vue+TypeScript+元素

Vuex/自定义状态管理 Vuex

自定义状态管理(发布-订阅者模式)

【思考:】不同类型的风暴函数存储在一个集合中,通过点击、取消、调度对集合进行处理。

其中,闭包用于处理单次监听,存储是否已经执行过

once(eventName: string, cb: CbType) {
    const { eventStack } = this
    const eventValue = eventStack[eventName]
    const tempCb = () => {
      let isOutOfDate = false
      return (data: object) => {
        if (isOutOfDate) return
        cb(data)
        isOutOfDate = true
      }
    }
    eventValue ? eventValue.push(tempCb()) : eventStack[eventName] = [tempCb()]
  }

axios 包

【功能列表】

  /**
   * token 处理
   * @param config 配置项
   * @param customConfig 自定义配置项
   */
  private addToken(config: AxiosRequestConfig, customConfig: CustomConfigType) {
    if (customConfig.isNeedToken) {
      config.headers = {
        token: store.getters['userStore/getToken'] || ''
      };
    } else {
      config.headers = {};
    }
  }

  /**
   * 发起请求
   * @param config 配置项
   * @param customConfig 自定义配置
   */
  private async transfromRquest(
    config: AxiosRequestConfig,
    customConfig: CustomConfigType = {}
  ): Promise<AxiosResponse> {
    customConfig = { ...this.defaultCustomConfig, ...customConfig };
    this.transformUrl(config.url);
    this.handleLoading(customConfig, true);
    this.addToken(config, customConfig);
		this.requestCount++
    try {
      const result = await this.axios.request(config);
      return result;
    } catch (error) {
      const { code, config } = error
      if (code === 401) {
        // 解决 token 失效的
        // 方案一 跳转至登录页
        // store.commit('userStore/setToken', '')
        // store.commit('permissionsStore/setPermissions', {})
        // router.replace({ path: '/login', query: {
        //   redirectUrl: router.currentRoute.fullPath
        // } })
        // 方式二 自动刷新 token 并重新发起失败的请求
        const res = await this.transfromRquest({
          method: 'post',
          url: '/refresh-token'
        })
        console.log(res, '/refresh-token')
        store.commit('userStore/setToken', res.data.token)
        return this.transfromRquest(config)
        // 方式三 在请求拦截里面先校验 token 是否过期 再发起请求
      }
      this.handleError(customConfig, error);
      return Promise.reject(error);
    } finally {
			this.requestCount--
      this.handleLoading(customConfig, false);
		}
  }

[缺点:]

与这些取消请求类似,服务器虽然收到了,但只是浏览器做了一层处理,无法等待响应。

当需要避免重复提交数据时typescript做界面,这些方法的实现是不准确的。 可以考虑聚焦、可变控制功能执行、可变控制按钮点击状态等。

WebWorkers简介

postMessage无法发送函数

WebSocket的嵌入

请参阅打包简单的 WebSocket 库

Element-ui列表组件的封装

[主意:]

    <header class="list-header animate__animated animate__fadeIn">
      <slot name="head" />
      <xw-search
        v-if="searchOption"
        :searchOption="searchOption"
        :searchParams="searchParams"
        @onSearch="getList"
      >
        <slot name="search" />
      </xw-search>
    </header>
    <main class="list-main">
      <slot name="main" />
      <xw-table :tableOption="tableOption" />
    </main>
    <footer class="list-footer">
      <slot name="footer" />
      <xw-pagination
        v-if="paginationOption"
        :paginationOption.sync="paginationOption"
        @onPagination="getList"
      />
    </footer>

import { Component } from 'vue'
export interface TableOption {
  // element-ui 表格的配置属性
  tableAttribute: TableAttribute
  // 列的配置属性
  tableColumn: TableColumn[]
}
export interface TableAttribute {
  // 属性
  props: {
    data: object[]
    [index: string]: any
  }
  // 事件
  on: { [key: string]: Function | Function[] }
}
export interface TableColumn {
  // 属性
  props: {
    label?: string
    prop?: string
    [index: string]: any
  },
  // 插槽
  slots?: {
    [index: string]: {
      // 属性
      options?: object
      // 自定义组件
      component: Component
    }
  }
  // 多级表头
  columnChild?: TableColumn[]
}

复杂的情况

编辑当前行,根据权限显示不同的按钮,加载和禁用按钮

typescript做界面-Vue+TypeScript+元素

gitcommit提交记录优化

使用commitizen代替你的gitcommit,commitizen还需要适配器的配合typescript做界面,官方推荐cz-conventional-changelog

"scripts": {
    "commit": "git-cz"
  },
"config": {
    "commitizen": {
      "path": "node_modules/cz-conventional-changelog"
    }
  }

"config": {
    "commitizen": {
      "path": "node_modules/cz-customizable"
    }
  }

同时在项目目录下创建.cz-config.js.commitlintrc.js文件

疗效如下:

指令封装

源地址

以上只是简单概述,详细内容请参考源码地址

博文推荐

【笔记不易,如果对您有帮助,请点赞,谢谢】

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 typescript typescript做界面-Vue+TypeScript+元素 https://www.wkzy.net/game/145237.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务