4. vue-router、vuex
npm install vue-router@4 vuex
4.1 vuex
在根目录下创建 store/index.ts
import { InjectionKey } from 'vue' import { createStore, Store } from 'vuex' export interface State { count: number } export const key: InjectionKey<Store<State>> = Symbol() export const store = createStore<State>({ state() { return { count: 0 } }, mutations: { increment(state) { state.count++ } } })
main.ts 修改
import { createApp } from 'vue' import { store, key } from './store' import App from './App' import './index.css' const app = createApp(App) app.use(store, key) app.mount('#app')
components/HelloWord.vue 修改
<template> <h1>{{ msg }}</h1> <button @click="inCrement"> count is: </button> <p>{{ count }}</p> </template> <script> import { defineComponent, computed } from 'vue' import { useStore } from 'vuex' import { key } from '../store' export default defineComponent({ name: 'HelloWorld', props: { msg: { type: String, default: '' } }, setup() { const store = useStore(key) const count = computed(() => store.state.count) return { count, inCrement: () => store.commit('increment') } } }) </script>
4.2 vue-router
在 src 目录下建立 router/index.ts,内容如下:
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; import HelloWorld from "../components/HelloWorld.vue"; const routes: Array<RouteRecordRaw> = [ { path: "/", name: "HelloWorld", component: HelloWorld, }, { path: "/about", name: "About", // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "About" */ "../components/About.vue") } ]; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes, }); export default router;
再新建一个 components/About.vue 文件,内容如下:
<template> <img alt="Vue logo" src="../assets/logo.png" /> <h1>{{ msg }}</h1> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ name: 'About', data() { return { msg: 'Hello Vue 3.0 + Vite!' } }, setup() {} }) </script>
再修改 main.ts
import { createApp } from 'vue' import { store, key } from './store' import router from "./router"; import App from './App' import './index.css' const app = createApp(App) app.use(store, key) app.use(router) app.mount('#app')
和 http://localhost:3000/about 即可
5. 加入 Element Plus
5.1 安装 element-plus
全局安装
npm install element-plus --save
5.2 引入 Element Plus
你可以引入整个 Element Plus,或是根据需要仅引入部分组件。我们先介绍如何引入完整的 Element。
完整引入
在 main.js 中写入以下内容:
import { createApp } from 'vue' import ElementPlus from 'element-plus'; import router from "./router"; import 'element-plus/lib/theme-chalk/index.css'; import App from './App.vue'; import './index.css' const app = createApp(App) app.use(ElementPlus) app.use(router) app.mount('#app')
以上代码便完成了 Element Plus 的引入。需要注意的是,样式文件需要单独引入。
按需引入
借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。
首先,安装 babel-plugin-component:
npm install babel-plugin-component -D
然后,将 .babelrc 修改为:
{ "plugins": [ [ "component", { "libraryName": "element-plus", "styleLibraryName": "theme-chalk" } ] ] }
接下来,如果你只希望引入部分组件,比如 Button 和 Select,那么需要在 main.js 中写入以下内容:
import { createApp } from 'vue' import { store, key } from './store'; import router from "./router"; import { ElButton, ElSelect } from 'element-plus'; import App from './App.vue'; import './index.css' const app = createApp(App) app.component(ElButton.name, ElButton); app.component(ElSelect.name, ElSelect); /* or * app.use(ElButton) * app.use(ElSelect) */ app.use(store, key) app.use(router) app.mount('#app') app.mount('#app')
更详细的安装方法请看 快速上手。
5.3 全局配置
在引入 Element Plus 时,可以传入一个全局配置对象。
该对象目前支持 size
与 zIndex
字段。size
用于改变组件的默认尺寸,zIndex
设置弹框的初始 z-index(默认值:2000)。按照引入 Element Plus 的方式,具体操作如下:
完整引入 Element:
import { createApp } from 'vue' import ElementPlus from 'element-plus'; import App from './App.vue'; const app = createApp(App) app.use(ElementPlus, { size: 'small', zIndex: 3000 });
按需引入 Element:
import { createApp } from 'vue' import { ElButton } from 'element-plus'; import App from './App.vue'; const app = createApp(App) app.config.globalProperties.$ELEMENT = option app.use(ElButton);
按照以上设置,项目中所有拥有 size
属性的组件的默认尺寸均为 'small',弹框的初始 z-index 为 3000。
5.4 配置 vite.config.ts
其中 proxy 和 alias 是和 vue-cli 区别比较大的地方。
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import styleImport from 'vite-plugin-style-import' import path from 'path' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), styleImport({ libs: [ { libraryName: 'element-plus', esModule: true, ensureStyleFile: true, resolveStyle: (name) => { return `element-plus/lib/theme-chalk/${name}.css`; }, resolveComponent: (name) => { return `element-plus/lib/${name}`; }, } ] }) ], /** * 在生产中服务时的基本公共路径。 * @default '/' */ base: './', /** * 与“根”相关的目录,构建输出将放在其中。如果目录存在,它将在构建之前被删除。 * @default 'dist' */ // outDir: 'dist', server: { // hostname: '0.0.0.0', host: "localhost", port: 3001, // // 是否自动在浏览器打开 // open: true, // // 是否开启 https // https: false, // // 服务端渲染 // ssr: false, proxy: { '/api': { target: 'http://localhost:3333/', changeOrigin: true, ws: true, rewrite: (pathStr) => pathStr.replace('/api', '') }, }, }, resolve: { // 导入文件夹别名 alias: { '@': path.resolve(__dirname, './src'), views: path.resolve(__dirname, './src/views'), components: path.resolve(__dirname, './src/components'), utils: path.resolve(__dirname, './src/utils'), less: path.resolve(__dirname, "./src/less"), assets: path.resolve(__dirname, "./src/assets"), com: path.resolve(__dirname, "./src/components"), store: path.resolve(__dirname, "./src/store"), mixins: path.resolve(__dirname, "./src/mixins") }, } })
踩到坑
在 npm run dev
打包时不报错,但是在 npm run build
时却报错了,build 的时候会把 node_modules
里面的文件也编译,所以挺多 element-plus 的类型文件报错了。
把 tsconfig.json
里面的 include
和 exclude
修改一下就不会了,配置如下
{ "compilerOptions": { "target": "esnext", "module": "esnext", "moduleResolution": "node", "strict": true, "jsx": "preserve", "sourceMap": true, // 忽略 this 的类型检查, Raise error on this expressions with an implied any type. "noImplicitThis": false, "resolveJsonModule": true, "esModuleInterop": true, "lib": ["esnext", "dom"], "types": ["vite/client"] }, "include": ["/src/**/*.ts", "/src/**/*.d.ts", "/src/**/*.tsx", "/src/**/*.vue"], // ts 排除的文件 "exclude": ["node_modules"] }
Vue3 + vite2 打包出来的文件和原来 vue2 版的差别也挺大的,由原来 2.5M 直接变成了 1.8M ,amazing!