Vue3 实战(二)

337 阅读2分钟

1. 依赖配置

1.1. Vue-Router

/src/config/route/index.ts

import { createRouter, createWebHistory } from 'vue-router';
​
const route = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'index',
      redirect: '/index',
      component: () => import('@/components/index.vue'),
      children: []
    }
  ]
});
​
export default route;
  • history: 可填写createWebHistory()和createWebHistory(),表象区别在于跳转时URL是否携带”#“,并且createWebHistory需要Nginx转发。
  • routes: 组件路由声明,如路径、名称、重定向、组件、子路由信息等等。

/src/App.vue

<template>
  <router-view />
</template>

1.2. Vuex

/src/plugins/store/index.ts

import Vuex from 'vuex';
​
export default new Vuex.Store({
  state: {
    "key":"value"
  },
  mutations: {
    change(state, value){
      state.key = value;
    }
  },
});
  • state: 声明参数。
  • mutations: 声明参数改变方法(只能通过该方法)

1.3. Axios

/src/plugins/axios/index.ts

import axios from 'axios';
​
const instance = axios.create({
  // 接口域名
  baseURL: import.meta.env.BASE_URL,
  // 超时时限
  timeout: 6000,
  // 请求头
  headers: {
    'Content-Type': 'application/json;charset=UTF-8;',
  },
});
​
// 请求拦截
instance.interceptors.request.use(
  (config) => config,
  (error) => Promise.reject(error)
);
​
// 响应拦截
instance.interceptors.response.use(
  (response: any) => {},
  (error) => Promise.reject(error)
);
​
export default instance;

1.4. Element-Plus

/src/config/ui/index.ts

import { App } from 'vue';
import {ElAlert,ElAffix,ElAside,ElAutocomplete,ElAvatar,ElBacktop,ElBadge,ElBreadcrumb,ElBreadcrumbItem,ElButton,ElButtonGroup,ElCalendar,ElCard,ElCarousel,ElCarouselItem,ElCascader,ElCascaderPanel,ElCheckbox,ElCheckboxButton,ElCheckboxGroup,ElCol,ElCollapse,ElCollapseItem,ElCollapseTransition,ElColorPicker,ElContainer,ElDatePicker,ElDescriptions,ElDescriptionsItem,ElDialog,ElDivider,ElDrawer,ElDropdown,ElDropdownItem,ElDropdownMenu,ElFooter,ElForm,ElFormItem,ElHeader,ElIcon,ElImage,ElInput,ElInputNumber,ElLink,ElMain,ElMenu,ElMenuItem,ElMenuItemGroup,ElOption,ElOptionGroup,ElPageHeader,ElPagination,ElPopconfirm,ElPopover,ElPopper,ElProgress,ElRadio,ElRadioButton,ElRadioGroup,ElRate,ElResult,ElRow,ElScrollbar,ElSelect,ElSelectV2,ElSlider,ElStep,ElSteps,ElSubMenu,ElSwitch,ElTabPane,ElTable,ElTableColumn,ElTabs,ElTag,ElTimePicker,ElTimeSelect,ElTimeline,ElTimelineItem,ElTooltip,ElTransfer,ElTree,ElUpload,ElInfiniteScroll,ElLoading,ElMessage,ElMessageBox,ElNotification} from 'element-plus';
import * as ElementPlusIcons from '@element-plus/icons-vue';

const components = [ElAlert,ElAffix,ElAside,ElAutocomplete,ElAvatar,ElBacktop,ElBadge,ElBreadcrumb,ElBreadcrumbItem,ElButton,ElButtonGroup,ElCalendar,ElCard,ElCarousel,ElCarouselItem,ElCascader,ElCascaderPanel,ElCheckbox,ElCheckboxButton,ElCheckboxGroup,ElCol,ElCollapse,ElCollapseItem,ElCollapseTransition,ElColorPicker,ElContainer,ElDatePicker,ElDescriptions,ElDescriptionsItem,ElDialog,ElDivider,ElDrawer,ElDropdown,ElDropdownItem,ElDropdownMenu,ElFooter,ElForm,ElFormItem,ElHeader,ElIcon,ElImage,ElInput,ElInputNumber,ElLink,ElMain,ElMenu,ElMenuItem,ElMenuItemGroup,ElOption,ElOptionGroup,ElPageHeader,ElPagination,ElPopconfirm,ElPopover,ElPopper,ElProgress,ElRadio,ElRadioButton,ElRadioGroup,ElRate,ElResult,ElRow,ElScrollbar,ElSelect,ElSelectV2,ElSlider,ElStep,ElSteps,ElSubMenu,ElSwitch,ElTabPane,ElTable,ElTableColumn,ElTabs,ElTag,ElTimePicker,ElTimeSelect,ElTimeline,ElTimelineItem,ElTooltip,ElTransfer,ElTree,ElUpload,ElInfiniteScroll,ElLoading,ElMessage,ElMessageBox,ElNotification];
​
const plugins = [ElInfiniteScroll,ElLoading,ElMessage,ElMessageBox,ElNotification];
​
export const ElementPlus = {
  install: (app: App<Element>): void => {
    // 组件
    components.forEach((component) => {
      app.component(component.name, component);
    });
    // 图标
    for (const [key, component] of Object.entries(ElementPlusIcons)) {
      app.component(key, component);
    }
    // 插件
    plugins.forEach((plugin) => {
      app.use(plugin);
    });
  },
};

1.5. Echarts

/src/plugins/echarts/echarts.vue

安装guid-typescript(创建唯一标识)

npm install guid-typescript

<template>
  <div :style="{ height: height }" :id="id"></div>
</template><script lang="ts" setup>
import { onMounted, watch } from "vue";
import * as Echarts from "echarts";
import { Guid } from "guid-typescript";
​
const { height, option } = defineProps({
  height: {
    type: String,
    required: false,
    default: () => '300px'
  },
  option: {
    type: Object,
    required: true,
    default: () => { }
  }
});
​
// Id
const id = Guid.create().toString();
​
onMounted(() => {
  const element = document.getElementById(id);
  if (!element) {
    throw new Error('Element is not defined');
  }
​
  const chart = Echarts.init(element);
  chart.setOption(option);
​
  // 窗口大小改变
  window.onresize = () => chart.resize();
});
</script>

2. 系统配置

2.1. vite.config.ts

安装vite-plugin-style-import加载ELement-Plus CSS

npm install vite-plugin-style-import

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import {
  createStyleImportPlugin,
  ElementPlusResolve,
} from 'vite-plugin-style-import';
​
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    createStyleImportPlugin({
      resolves: [ElementPlusResolve()], // vite2(新),配置更少
    }),
  ],
  server: {
    host: '0.0.0.0', //解决“vite use `--host` to expose”
    port: 80,
    open: true,
    proxy: {
      '/api': {
        target: '', // 目标地址
        changeOrigin: true,
        secure: false,
        rewrite: (path) => path.replace('/api/', '/'),
      },
    },
  },
  resolve: {
    alias: [
      {
        find: '@',
        replacement: resolve(__dirname, 'src'),
      },
    ],
  },
});

2.2. tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "baseUrl": "./",
    "paths": {
      "@": ["src"],
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
  • paths: 解决编译器警告不识别自定标签的路径问题。
  • 其他: 略。

2.3. main.ts

/src/main.ts

import { createApp } from 'vue';
import App from './App.vue';
import Route from './config/route';
import { ElementPlus } from './config/ui';
import lang from 'element-plus/lib/locale/lang/zh-cn';
import 'dayjs/locale/zh-cn';
import 'element-plus/theme-chalk/src/base.scss';
​
// 1.路由; 2.UI&语言;
createApp(App).use(Route).use(ElementPlus, { lang }).mount('#app');

3. 目录结构

├── public
│   └── favicon.ico
├── src
│   ├── assets
│   ├── components
│   │   └── Index.vue
│   ├── config
│   │   ├── route
│   │   │   └── index.ts
│   │   └── ui
│   │       └── index.ts
│   ├── plugins
│   │   ├── axios
│   │   │   └── index.ts
│   │   ├── echarts
│   │   │   └── echarts.vue
│   │   └── store
│   │       └── index.ts
│   ├── App.vue
│   ├── env.d.ts
│   └── main.ts
├── index.html
├── package-lock.json
├── package.json
├── README.md
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts