vue3.2 + vite + ts + vue-router4 + pinia + elementPlus + echarts5 项目初始化 (三)

307 阅读2分钟

接上: juejin.cn/post/717433…

五.路由

执行下列命令安装依赖

pnpm i vue-router@4

src 新新建目录 router ,并新建 index.ts 文件, 内容如下:

import { RouteRecordRaw, createRouter, createWebHashHistory } from 'vue-router'

const modules = import.meta.glob('../views/**/**.vue')

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'Login',
    component: modules['../views/login/index.vue']
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router


// 原来的 import 路由懒加载在开发环境可行,在生产环境不可行,故改为上面
// import.meta.glob 形式

修改入口文件main.ts

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import router from './router'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}
app.use(router).use(ElementPlus).mount('#app')

注意: 在App.vue 中添加路由出口

至此,路由的基本配置已经完成,更多配置信息,详见官网:router.vuejs.org/zh/guide/

六.统一封装请求 (axios)

执行下列命令安装依赖

pnpm i axios
pnpm i qs -D
pnpm i @types/qs -D

src 下新建目录 utils,并新建文件 http.ts,内容如下:

import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
import qs from 'qs'

/**
 * 业务自定义状态码
 * 1000 请求成功
 * 5000 重定向
 * 5002 重定向+提示(token获取失败)
 * 5003 cookie中缺失appKey
 * 5004 用户被拉入黑名单
 * 4003 未授权
 */

// axios声明合并,在axios的配置项AxiosRequestConfig接口定义中自定义新值
declare module 'axios' {
  export interface AxiosRequestConfig {
    /**
     * @description 设置为false,表示请求错误是用户自定义处理(true)还是全局处理(false)
     */
    customError?: boolean
  }
}

// 创建axios实例,此时的content-type已指定为json,如需使用form-data,请自行修改
const http = axios.create({
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  // 表示跨域请求时是否需要使用凭证
  withCredentials: true,

  validateStatus(status) {
    return status === 200 // 自定义状态码范围
  },
  paramsSerializer(params) {
    // 序列化请求参数,避免get请求参数出现[],&,空格等识别错误的问题
    return qs.stringify(params, { arrayFormat: 'brackets' })
  },
  transformRequest: [
    data => {
      // 转化为正常的json
      data = JSON.stringify(data)
      return data
    }
  ]
})
// 请求拦截
http.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // do something

    return config
  },
  (error: any) => {
    Promise.reject(error)
  }
)

// 响应拦截
http.interceptors.response.use(
  async (response: AxiosResponse) => {
    return Promise.reject(response)
  },
  (error: any) => {
    // do something
    return Promise.reject(error)
  }
)

export default http

在请求拦截和响应拦截根据自己的需求加以修,之后在发请求时,可以直接运用以上封装的工具函数.

七.状态管理pinia

安装

pnpm i pinia@next
pnpm i pinia-plugin-persist 持久化插件

src 下新增 store 文件夹, 接着在 store 中新增 index.ts 文件,内容如下:

import type { App } from 'vue'

import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'

const store = createPinia()
store.use(piniaPluginPersist) //使用插件持久化

export function setupStore(app: App<Element>) {
  app.use(store)
}

export default store

并在入口文件下 main.ts 中增加

import store from './store'
app.use(store)

pinia 基本已经配置完毕,如何使用可以参考官网: pinia.web3doc.top/introductio…

八.vue3中使用echarts图表

安装

pnpm i echarts

使用方式如下所示:

<!--  线 + 柱混合图 -->
<template>
  <div id="poy-charts" style="height: 200px; width: 300px" />
</template>

<script setup lang="ts">
import { nextTick, onMounted } from 'vue'
// 引入 echarts
import { init, EChartsOption } from 'echarts'
import * as echarts from 'echarts'

// const { mounted, chart, beforeDestroy, activated, deactivated } = resize()

// 初始化图表
function initChart() {
  const barChart = init(document.getElementById('poy-charts') as HTMLDivElement)

  barChart.setOption({
    title: {
      show: true,
      text: '业绩总览',
      x: 'center',
      padding: 15,
      textStyle: {
        fontSize: 18,
        fontStyle: 'normal',
        fontWeight: 'bold',
        color: '#337ecc'
      }
    },
    grid: {
      left: '2%',
      right: '2%',
      bottom: '10%',
      containLabel: true
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross',
        crossStyle: {
          color: '#999'
        }
      }
    },
    legend: {
      x: 'center',
      y: 'bottom',
      data: ['收入', '毛利润', '收入增长率', '利润增长率']
    },
    xAxis: [
      {
        type: 'category',
        data: ['浙江', '北京', '上海', '广东', '深圳'],
        axisPointer: {
          type: 'shadow'
        }
      }
    ],
    yAxis: [
      {
        type: 'value',
        min: 0,
        max: 10000,
        interval: 2000,
        axisLabel: {
          formatter: '{value} '
        }
      },
      {
        type: 'value',
        min: 0,
        max: 100,
        interval: 20,
        axisLabel: {
          formatter: '{value}%'
        }
      }
    ],
    series: [
      {
        name: '收入',
        type: 'bar',
        data: [7000, 7100, 7200, 7300, 7400],
        barWidth: 20,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: '#83bff6' },
            { offset: 0.5, color: '#188df0' },
            { offset: 1, color: '#188df0' }
          ])
        }
      },
      {
        name: '毛利润',
        type: 'bar',
        data: [8000, 8200, 8400, 8600, 8800],
        barWidth: 20,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: '#25d73c' },
            { offset: 0.5, color: '#1bc23d' },
            { offset: 1, color: '#179e61' }
          ])
        }
      },
      {
        name: '收入增长率',
        type: 'line',
        yAxisIndex: 1,
        data: [60, 65, 70, 75, 80],
        itemStyle: {
          color: '#67C23A'
        }
      },
      {
        name: '利润增长率',
        type: 'line',
        yAxisIndex: 1,
        data: [70, 75, 80, 85, 90],
        itemStyle: {
          color: '#409EFF'
        }
      }
    ]
  } as EChartsOption)
}

// 页面挂载时初始化图表
onMounted(() => {
  nextTick(() => {
    initChart()
  })
})
</script>