简介
本项目采用 vue3 + webpack 的方式来开发,已经引入了常用功能,不需要再去配置路由、请求、pinia 等,上手直接开发页面即可,真正做到开箱即用
你可以直接拉取我的仓库来直接使用,也可以按照本文教程自己操作
仓库地址:https://gitee.com/szxio/vue3-template。
如果对你有用的话,点赞、收藏、关注。❥(^_-)
技术栈
- vue3
- webpack
- pinia
- vue-router4
- element-plus
- axios
- i18n
- sass
启动项目
安装
运行
打包
Pinia使用
安装
首先安装依赖,本项目已经安装好,下面只是教程
配置
新建 src/store/index.js
,内容如下
1 2 3
| import {createPinia} from 'pinia'
export default createPinia()
|
在 main.js
中引入
1 2 3 4 5 6 7 8
| import { createApp } from 'vue' import App from './App.vue'
const app = createApp(App) import pinia from '@/store/index.js'
app.use(pinia) app.mount('#app')
|
使用
新建 src/store/userInfo.js
,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import { defineStore } from 'pinia'
export const userInfo = defineStore('userInfo', { state: () => ({ userInfo: { name: 'lisi', age: 18, }, }), actions: { async setUserInfo(data) { this.userInfo = data }, }, })
|
在页面中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <template> <div> {{ store.userInfo.name }} <button @click="getClick">修改store</button> </div> </template>
import { userInfo } from '@/store/userInfo' const store = userInfo()
const getClick = () => { store.setUserInfo({ name: 'wangwu', }) }
|
国际化配置
安装
配置
新建 src/i18n/index.js
,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import { createI18n } from 'vue-i18n' import homeEn from './home/en.js' import homeZh from './home/zh.js'
const messages = { en: { home: { ...homeEn }, }, zh: { home: { ...homeZh }, }, }
const language = (navigator.language || 'zh').toLocaleLowerCase()
const i18n = createI18n({ legacy: false, locale: localStorage.getItem('i18n') || language.split('-')[0] || 'zh', fallbackLocale: 'zh', messages, })
export default i18n
|
上面引入的中英文文件分别如下
src/i18n/home/en.js
1 2 3 4 5
| export default { login: 'Log in', userName: 'Username', password: 'Password', }
|
src/i18n/home/zh.js
1 2 3 4 5
| export default { login: '登录', userName: '用户名', password: '密码', }
|
在 main.js
文件中引入
1 2 3 4 5 6 7 8
| import { createApp } from 'vue' import App from './App.vue'
const app = createApp(App) import i18n from '@/i18n/index.js'
app.use(i18n) app.mount('#app')
|
使用
$t
不用在js中单独引入,在全局已经引入过了,所以这里在页面中可以直接使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| <template> <div> {{ $t('home.userName') }} <el-button type="primary" @click="switchLanguage">切换语言</el-button> </div> </template>
<script setup> const switchLanguage = () => { localStorage.setItem('i18n', 'en') window.location.reload() } </script>
|
Sass安装
安装
这里不能安装高版本,否则会有兼容问题导致项目启动不起来
1
| npm install sass sass-loader@8.0.2 node-sass@4.14.1
|
配置
新建 src/assets/style/index.scss
1 2 3 4 5 6 7 8
| :root { --primary-color: #1c82e3; }
body { margin: 0; min-height: 100vh; }
|
在 main.js
中引入
1 2 3 4 5 6
| import { createApp } from 'vue' import App from './App.vue' import '@/assets/style/index.scss'
const app = createApp(App) app.mount('#app')
|
使用
1 2 3 4 5
| <style scoped lang="scss"> h1{ color: var(--primary-color) } </style>
|
VueRouter4使用
安装
1
| npm install vue-router@4
|
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import { createRouter, createWebHashHistory } from 'vue-router' import Layout from '@/layout/index.vue'
const routes = [ { path: '/', component: Layout, redirect: '/home', title: '首页', children: [ { path: 'home', title: '首页', component: import('../view/home/index.vue'), }, { path: 'about', title: '关于我', component: import('../view/about/index.vue'), }, ], }, ]
const router = createRouter({ history: createWebHashHistory(), routes, })
export default router
|
新建 src/layout/index.vue
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| <template> <div> <div class="d-flex flex-justify-center gap-10 bg-yellow-light flex-items-center navtop" style="height: 50px" > <div :class="{ active: route.path === '/home' || route.path === '/', }" @click="goPage1" > 首页 </div> <div :class="{ active: route.path === '/about', }" @click="goPage2" > 我的 </div> </div>
<router-view v-slot="{ Component }"> <transition name="fade" mode="out-in"> <component :is="Component" /> </transition> </router-view> </div> </template>
<script setup> import { useRoute, useRouter } from 'vue-router' import { ref, watchEffect } from 'vue'
const route = ref(useRoute()) const router = ref(useRouter())
const goPage1 = () => { router.value.push({ path: '/home', }) }
const goPage2 = () => { router.value.push({ path: '/about', }) }
// 监听路由 watchEffect(() => { console.log(route.value.path, '5555') }) </script>
<style scoped lang="scss"> .fade-enter-active, .fade-leave-active { transition: opacity 0.2s; }
.fade-enter, .fade-leave-to { opacity: 0; }
.navtop { div { display: flex; align-items: center; background-color: #1ab394; color: white; height: 100%; line-height: 100%; padding: 0 20px; } }
.active { background-color: #1c82e3 !important; } </style>
|
在 main.js
中引入
1 2 3 4 5 6 7 8
| import { createApp } from 'vue' import App from './App.vue'
const app = createApp(App) import router from '@/router/index.js'
app.use(router) app.mount('#app')
|
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import { useRoute, useRouter } from 'vue-router'
const router = ref(useRouter()) const route = ref(useRoute())
const getRouteInfo = () => { console.log(route.value.path) console.log(route.value.query) console.log(route.value.meta) }
const goAbout = () => { router.value.push({ path: '/about', query: { id: '1', }, }) }
|
ElementPlus使用
安装
1
| npm install element-plus @element-plus/icons-vue
|
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { createApp } from 'vue' import App from './App.vue' import '@/assets/style/index.scss'
const app = createApp(App) import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import * as ElementPlusIconsVue from '@element-plus/icons-vue' import lang from 'element-plus/lib/locale/lang/zh-cn'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) } app.use(ElementPlus, { locale: lang, }) app.mount('#app')
|
使用
1 2 3 4 5 6
| <el-button type="primary" @click="showMsg">成功消息</el-button>
import {ElMessage} from "element-plus"; const showMsg = () => { ElMessage.success("success") }
|
Axios使用
安装
配置
新建 src/utils/request.js
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import axios from 'axios' import {ElMessage} from 'element-plus'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, })
service.interceptors.request.use( (config) => { return config }, (error) => { return Promise.reject(error) } )
service.interceptors.response.use( (res) => { const code = res.data.code || 200 const msg = res.data.msg if (code !== 200 && code !== 20000 && code !== 1) { ElMessage.error(msg) return Promise.reject('error') } else { return res.data } }, (error) => { console.log('err' + error) let {message} = error if (message === 'Network Error') { message = '后端接口连接异常' } else if (message.includes('Request failed with status code')) { message = '系统接口' + message.substr(message.length - 3) + '异常' } ElMessage({ message: message, type: 'error', duration: 5 * 1000, }) return Promise.reject(error) } )
export default service
|
设置代理,修改 vue.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const port = process.env.port || 10078
module.exports = { devServer: { host: '0.0.0.0', port: port, open: true, proxy: { [process.env.VUE_APP_BASE_API]: { target: `http://xxx.xxx.xxx`, changeOrigin: true, pathRewrite: { ['^' + process.env.VUE_APP_BASE_API]: '', }, }, }, disableHostCheck: true, }, }
|
使用
1 2 3 4 5 6 7 8
| import request from '@/utils/request'
export function testRequestFun() { return request({ url: `/homePage/getProcessNode`, method: 'get', }) }
|
配置@访问别名
修改 vue.config.js
1 2 3 4 5 6 7 8 9 10 11
| const path = require('path')
module.exports = { configureWebpack: { resolve: { alias: { '@': path.resolve(__dirname, 'src/'), }, }, }, }
|