最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue3+ts+vite 项目配置

    正文概述 掘金(沐寒晚枫)   2021-01-25   1501

    项目初始化

    // 默认使用yarn
    yarn create @vitejs/app my-vue-ts-app --template vue-ts
    
    // 模板包括 vanilla, vue, vue-ts, react, react-ts ...
    

    ts配置项

    • tsconfig.json
    • 目前暂时采用项目构建后的默认配置
    {
      "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "moduleResolution": "node",
        "strict": true,
        "jsx": "preserve",
        "sourceMap": true,
        "lib": ["esnext", "dom"],
        "types": ["vite/client"],
        "plugins": [{ "name": "@vuedx/typescript-plugin-vue" }]
      },
      "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
      "exclude": ["node_modules", "dist"]
    }
    

    shim.d.ts配置

    • 解决找不到 .vue 模块的报错问题
    • 参考 juejin.cn/post/688923…
    // 在src目录下添加 shim.d.ts, 名称可以自定义 xxx.d.ts
    declare module '*.vue' {
      import { Component } from 'vue'
      const mod: Component
      export default mod
    }
    

    eslint集成配置

    • .eslintrc.js
    • yarn add -D eslint eslint-plugin-vue babel-eslint
    • 根据个人习惯配置就好~
    • === 总感觉对 ts 的支持不是很好,待完善 ===
    module.exports = {
      root: true,
      env: {
        node: true,
      },
      extends: [
        'plugin:vue/vue3-essential',
        'eslint:recommended',
        'plugin:prettier/recommended',
      ],
      parserOptions: {
        parser: 'babel-eslint',
      },
      plugins: ['prettier'],
      rules: {
        'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
        'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
        'no-unused-vars': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
      },
    }
    

    prettier集成配置

    • .prettierrc
    • yarn add -D prettier eslint-config-prettier eslint-plugin-prettier
    • 根据个人习惯配置就好~
    {
      "semi": false,
      "singleQuote": true,
      "tabWidth": 2,
      "arrowParens": "always",
      "trailingComma": "es5",
      "printWidth": 90,
      "useTabs": false
    }
    

    集成vue-router

    • yarn add vue-router@4
    • 参考 github.com/vuejs/vue-r…
    import {RouteRecordRaw, createRouter, createWebHashHistory} from 'vue-router'
    const routes:RouteRecordRaw[] = [
      { path: '/', name: 'Home', component: () => import('../views/home/home.vue') }
    ]
    
    const router = createRouter({
    	history: createWebHashHistory(),
      routes,
    })
    export default router
    
    // main.ts
    import router from './router'
    createApp(App).use(router)
    

    集成vuex

    • yarn add vuex@next
    • 参考 github.com/vuejs/vuex
    import { createStore } from 'vuex'
    
    export default createStore({
    	state: {},
      mutations: {},
      actions: {},
      modules: {},
    })
    
    // main.ts
    import store from './store'
    createApp(App).use(store)
    

    引入less

    • yarn add less less-loader
    • 暂无特殊配置

    引入UI组件库

    • 个人使用 element-plus,也可以选择使用 ant-design vue
    • yarn add element-plus
    • 可配置自定义主题颜色,参考 element-plus.gitee.io/#/zh-CN/com…
    • 个人使用在线主题生成工具实现,将其中 index.css 文件引入至 main.ts
    // main.ts
    import ElementPlus from 'element-plus'
    import './style/element-theme.css'
    
    createApp(App).use(ElementPlus)
    

    axios封装

    • yarn add axios @types/node @types/lodash
    • 参考 juejin.cn/post/690146…
    • === 可继续完善 ===
    /**
     * 创建实例, 添加拦截
     */
    
    import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
    import storage from '../utils/storage'
    import { get } from 'lodash'
    
    // 创建 axios 实例
    const request = axios.create({
      // API 请求的默认前缀
      baseURL: process.env.VUE_APP_BASE_URL,
      timeout: 10000, // 请求超时时间
    })
    
    // 异常拦截处理器
    const errorHandler = (error: any) => {
      const status = get(error, 'response.status')
      switch (status) {
        case 400:
          error.message = '请求错误'
          break
        case 401:
          error.message = '未授权,请登录'
          window.location.href = '/login' // FIXME: router.push
          storage().remove('ACCESS_TOKEN')
          break
        case 403:
          error.message = '拒绝访问'
          break
        case 404:
          error.message = `请求地址出错: ${error.response.config.url}`
          break
        case 408:
          error.message = '请求超时'
          break
        case 500:
          error.message = '服务器内部错误'
          break
        case 501:
          error.message = '服务未实现'
          break
        case 502:
          error.message = '网关错误'
          break
        case 503:
          error.message = '服务不可用'
          break
        case 504:
          error.message = '网关超时'
          break
        case 505:
          error.message = 'HTTP版本不受支持'
          break
        default:
          break
      }
      return Promise.reject(error)
    }
    
    // request interceptor
    request.interceptors.request.use((config: AxiosRequestConfig) => {
      // 如果 token 存在
      // 让每个请求携带自定义 token
      config.headers.Authorization = storage().get('ACCESS_TOKEN')
      return config
    }, errorHandler)
    
    // response interceptor
    request.interceptors.response.use((response: AxiosResponse) => {
      // 若返回的请求头中包含 authorization, 则存入到缓存中
      if (response.headers.authorization) {
        storage().set('ACCESS_TOKEN', response.headers.authorization)
      }
    
      const dataAxios = response.data
      // 获取返回的状态码
      const { code } = dataAxios
      // 根据 code 进行判断
      if (code === undefined) {
        // 如果没有 code 代表这不是项目后端开发的接口
        return dataAxios
      } else {
        // 有 code 代表这是一个后端接口 可以进行进一步的判断
        switch (code) {
          // 正确返回
          case 0:
            return dataAxios.data
          default:
            // 不是正确的 code
            return dataAxios.message
        }
      }
    }, errorHandler)
    
    export default request
    

    缓存封装

    • localstorage
    • sessionstorage
    • 参考 github.com/sunweijieMJ…
    /**
     * localstorage 封装
     */
    
    class localStorageAPI {
      set(key: string, value: string): void {
        try {
          localStorage.setItem(key, value)
        } catch (e) {
          if (e.name === 'QuotaExceededError') {
            throw new Error('Out of Memory Limit Localstorage')
          } else {
            throw new Error(e.name)
          }
        }
      }
    
      get(key: string): string {
        return localStorage.getItem(key) || ''
      }
    
      remove(key: string): void {
        localStorage.removeItem(key)
      }
    
      // 有时效的 localStorage
      setExpire(key: string, value: string, expire: number): void {
        const curTime = new Date().getTime()
        return this.set(key, JSON.stringify({ val: value, time: curTime + expire }))
      }
    
      getExpire(key: string): string {
        const val: string = this.get(key)
        const dataObj = JSON.parse(val)
        if (new Date().getTime() - dataObj.time < 0) {
          return dataObj.val
        } else {
          return ''
        }
      }
    }
    
    export { localStorageAPI }
    
    /**
     * sessionstorage 封装
     */
    
    class SessionstorageAPI {
      set(key: string, value: string): void {
        return sessionStorage.setItem(key, value)
      }
    
      get(key: string): string {
        return sessionStorage.getItem(key) || ''
      }
    
      remove(key: string): void {
        return sessionStorage.removeItem(key)
      }
    }
    
    export { SessionstorageAPI }
    
    /**
     * 封装对外接口
     */
    
    interface UseStoreType {
      set: Function
      get: Function
      remove: Function
      getExpire?: Function
      setExpire?: Function
    }
    
    export default (store?: string): UseStoreType => {
      let UseStore
      switch (store) {
        case 'localstorage':
          UseStore = require('./localstorage').localStorageAPI
          break
    
        case 'sessionstorage':
          UseStore = require('./sessionstorage').SessionstorageAPI
          break
    
        default:
          UseStore = require('./localstorage').localStorageAPI
          break
      }
      return new UseStore()
    }
    

    全局样式

    • /style/reset.less
    • 主要是滚动条样式
    html,
    body {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
      font-size: 14px;
    }
    
    div {
      box-sizing: border-box;
    }
    
    /**
     * 全局滚动条样式
    */
    // 滚动条背景,宽高
    ::-webkit-scrollbar {
      width: 6px;
      height: 6px;
      background-color: #f5f5f5;
    }
    
    // 滚动条轨道
    ::-webkit-scrollbar-track {
      border: none;
      background-color: #fff;
    }
    
    // 滚动条滑块
    ::-webkit-scrollbar-thumb {
      border-radius: 4px;
      background-color: rgba(144, 147, 153, 0.3);
      cursor: pointer;
    }
    

    环境变量

    • .env.development
    • .env.production
    # import.meta.env.NODE_ENV
    NODE_ENV=development
    
    VITE_APP_BASE_URL=/api
    
    # import.meta.env.NODE_ENV
    NODE_ENV=production
    
    VITE_APP_BASE_URL=/
    

    vite.config.ts

    • 基础代理配置
    • === 待完善 ===
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import { resolve } from 'path'
    
    const pathResolve = (pathStr: string): string => {
      return resolve(__dirname, '.', pathStr)
    }
    
    export default defineConfig({
      alias: {
        '@': pathResolve('./src'),
      },
    
      server: {
        open: false,
        https: false,
        proxy: {
          '/api': {
            target: 'http://',
            changeOrigin: true,
            ws: false,
            secure: false,
            ignorePath: true,
          },
        },
      },
    
      plugins: [vue()],
    })
    

    起源地下载网 » vue3+ts+vite 项目配置

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元