【Typescript+Vue】01. easy

01. 声明 vue 和 window 的全局属性和方法

  • import Vue from 'vue';
    
    declare module 'vue/types/vue' {
      import { Maps } from '@/maps';
      import { Utils } from '@/utils';
    
      interface Vue {
        $utils: Utils;
        query: any;
        $MAPS: Maps;
    
        $ROLE: string;
        $USER_NAME: string;
        $PERMISSION: string[];
        $HAS_PERMISSION: (key: string | RegExp) => boolean;
      }
    }
    
    declare global {
      import dayjs from 'dayjs';
      import { AxiosInstance } from 'axios';
    
      interface Window {
        axios: AxiosInstance;
        ga: any;
        dayjs: typeof dayjs;
        GoogleAnalyticsObject: any;
        MS_PER_DAY: number;
        UUAP: string;
      }
    }

 

02. 基本 vue 组件 111

  • <!--
    @file: App.vue
    @author: xxx
    @description: 根组件
     -->
    <template>
      <div id="app">
        <main class="main-container">
          <div class="__inner">
            <router-view></router-view>
          </div>
        </main>
        <base-aside></base-aside>
        <base-footer></base-footer>
      </div>
    </template>
    
    <script lang="ts">
    import Vue from 'vue'
    
    import BaseFooter from '@/components/BaseFooter.vue'
    import BaseAside from '@/components/BaseAside.vue'
    
    export default Vue.extend({
      name: 'App',
      components: {
        BaseAside,
        BaseFooter
      },
      props: {},
      data () {
        return {}
      },
      watch: {},
      computed: {},
      methods: {},
    
      created () {},
      mounted () {},
      destroyed () {}
    })
    </script>

 

03. 单 mixin 组件使用

  • ... ...
        
    <script lang="ts">
    import clipboard from '@/mixins/clipboard'
    
    export default generalCRUD.extend({
        name: 'VideoManage',
    components: { ... ...},
    data () {
    ... ...

 

04. 多 mixin 组件使用

  • ... ...
        
    <script lang="ts">
    import clipboard from '@/mixins/clipboard'
    
    export default generalCRUD.extend(clipboard).extend({
        name: 'AudioManage',
    components: { ... ...},
    data () {
    
    
    ... ...

 

05. 计算属性【computed】必须声明返回值类型

  • ......

    export default generalCRUD.extend(clipboard).extend({ name: 'SandboxAudios', components: { CategorySelector }, data () { return { loading: false } }, computed: { writeAble (): boolean { return this.$HAS_PERMISSION('mango:video:sandbox:audios:w') } },

    ......

    每一个计算属性都声明类型以后,会发现解决了很多声明问题

 

06. 如果找不到 this 的某个 state 则需要显示声明 data 的返回值类型

  •  

     

07. 经常需要用到 for of 遍历对象,但是编辑器报错

  • export interface KeyValue {
      [key: string]: any;
    }

    可以定义类型 继承这个 KeyValue 类解决

 

08. 全局常量声明

  •   

09. 类型声明

  •  

     

10. 在用的 .eslintrc.js 配置

- 不用 tslint,官方都倾向 eslint 了。

tslint 已经被标记弃用了

- 不用分号了

其实用不用分号我都行。个人倾向于使用分号。因为我发现在有些情况,不用的话 ts 会报错

  • module.exports = {
      root: true,
      env: {
        node: true
      },
      extends: [
        'plugin:vue/essential',
        'eslint:recommended',
        '@vue/typescript/recommended'
      ],
      parserOptions: {
        parser: '@typescript-eslint/parser',
        ecmaVersion: 2020
      },
      globals: {
        MS_PER_DAY: true
      },
      rules: {
        'no-console': process.env.NODE_ENV === 'production' ? 1 : 0,
        'no-debugger': process.env.NODE_ENV === "production" ? 1 : 0,
        'semi': [2, 'never'],
        'indent': [2, 2],
        'quotes': [2, 'single'],
        'no-empty': 0,
        'prefer-const': 0,
        'comma-dangle': [2, 'never'],
        'prettier/prettier': 0,
        'space-before-function-paren': [0, 'always'],
    
        '@typescript-eslint/space-before-function-paren': [
          2,
          {
            asyncArrow: 'always',
            anonymous: 'always',
            named: 'always'
          }
        ],
        '@typescript-eslint/no-unused-vars': 0,
        '@typescript-eslint/no-empty-function': 0,
        '@typescript-eslint/no-var-requires': 0,
        '@typescript-eslint/no-explicit-any': 0,
        '@typescript-eslint/camelcase': 0,
        '@typescript-eslint/semi': [2, 'never']
      }
    }

 

11. Vuex 全局状态管理 Store

  • 一个全局 store + 若干模块化 store
  • 每个 store 都分为四个文件
  •  
  • 一个全局store

index.ts

  • import Vue from 'vue'
    import Vuex, { StoreOptions } from 'vuex'
    
    import getters from './getters'
    import actions from './actions'
    import mutations from './mutations'
    import sMenu from './module/sMenu'
    
    import { RootState, RootStore } from '@/entities/store'
    
    Vue.use(Vuex)
    
    const state: RootState = {
      userInfo: {}
    }
    
    export default new Vuex.Store({
      state,
      getters,
      actions,
      mutations,
      modules: {
        sMenu
      }
    } as StoreOptions<RootStore>)

getter.ts

  • import { GetterTree } from 'vuex'
    
    import { RootState } from '@/entities/store'
    
    export default {} as GetterTree<RootState, RootState>

actions.ts

  • import { ActionContext, ActionTree } from 'vuex'
    
    import { RootMutation, RootState } from '@/entities/store'
    import userApi from '@/api/user'
    import { AxiosError, AxiosResponse } from 'axios'
    
    export default {
      async getUserInfo (actionContext: ActionContext<RootState, RootState>) {
        return new Promise((resolve, reject) => {
          userApi
            .getUserInfo()
            .then((res: AxiosResponse) => {
              actionContext.commit(RootMutation.setUserInfo, res)
              resolve(res)
            })
            .catch((e: AxiosError) => {
              reject(e)
            })
        })
      },
      
    } as ActionTree<RootState, RootState>

mutations.ts

  • import { MutationTree } from 'vuex'
    
    import { RootMutation, RootState } from '@/entities/store'
    
    export default {
      [RootMutation.setUserInfo] (state: RootState, payload) {
        state.userInfo = payload
      }
    } as MutationTree<RootState>
  • 其中一个 模块化 store

index.ts

  • import { Module } from 'vuex'
    
    import actions from './actions'
    import mutations from './mutations'
    import getters from './getters'
    
    import { RootState } from '@/entities/store'
    import { MenuState } from '@/entities/store/sMenu'
    
    const state: MenuState = {
      menuId: localStorage.getItem('menuId') || '',
      menuList: []
    }
    
    export default {
      state,
      actions,
      mutations,
      getters
    } as Module<MenuState, RootState>

getters.ts

  • import { GetterTree } from 'vuex'
    
    import { RootState } from '@/entities/store'
    import { MenuState } from '@/entities/store/sMenu'
    
    export default {} as GetterTree<MenuState, RootState>

actioins.ts

  • import { ActionContext, ActionTree } from 'vuex'
    
    import api from '@/api/menu'
    import maps from '@/maps'
    
    import { KeyValue } from '@/entities'
    import { RootState } from '@/entities/store'
    import { MenuMutation, MenuState } from '@/entities/store/sMenu'
    
    export default {
      getMenuList ({ commit }, { pkg }) {
        return new Promise((resolve) => {
          api.requestMenuList({ pkg })
            .then((res: KeyValue) => {
              commit('setMenuList', res)
              const menuIdToName: KeyValue = {}
              res.forEach((v: KeyValue) => {
                menuIdToName[v.id] = v.name
              })
              maps.menu.menuIdToName = menuIdToName
              resolve(res)
            })
            .catch(() => {
              commit('setMenuList', [])
              resolve([])
            })
        })
      },
      setMenu (actionContext: ActionContext<MenuState, RootState>, { menuId }) {
        actionContext.commit(MenuMutation.setMenu, menuId)
      }
    } as ActionTree<MenuState, RootState>

mutations.ts

  • import { MutationTree } from 'vuex'
    import { MenuMutation, MenuState } from '@/entities/store/sMenu'
    
    export default {
      [MenuMutation.setMenuList] (state: MenuState, payload) {
        state.menuList = payload
      },
      [MenuMutation.setMenu] (state: MenuState, menuId) {
        state.menuId = menuId
        localStorage.setItem('menuId', menuId)
      }
    } as MutationTree<MenuState>

所有的 mutation 都应该只在 action 中调用,对 state 进行集中操作

 

12. ing

13. ing

posted @ 2021-04-19 10:08  耶梦加德  阅读(87)  评论(0编辑  收藏  举报