使用vite+vue3构建生产级项目架构
Posted 任磊abc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用vite+vue3构建生产级项目架构相关的知识,希望对你有一定的参考价值。
之前一直使用的Vue2(long long ago),现在我们也通过之前的开发经验进行搭建。
•框架: Vue3
•路由管理: Vue-router
•状态管理:Vuex
•UI组件库:Element UI
•可视化数据展示:echarts
•国际化:vue-i18n
•数据请求: Axios
下面,我们就对项目架构依次搭建起来。
撸一个基础项目出来
初始化项目,安装Vue3
yarn create vite
安装依赖
yarn
// run
yarn dev
路由管理:Vue-router
yarn add vue-router
创建3个页面
// home page
<template>
<div>home page</div>
<button @click="toAbout">toAbout</button>
</template>
<script setup>
import router from '../routes';
const toAbout = () =>
router.push('./about');
;
</script>
// about page
<template>
<div>about page</div>
<button @click="toHome">toHome</button>
</template>
<script setup>
import router from '../routes';
const toHome = () =>
router.push('/');
;
</script>
// 404 page
<template>
<div>404</div>
</template>
初始化路由stroe/index.js
import createRouter, createWebHistory from 'vue-router';
import Home from '../pages/home.vue';
import About from '../pages/about.vue';
import NotFound from '../pages/not-found.vue';
const routes = [
path: '/',
component: Home,
meta: title: 'Home' ,
,
path: '/About',
component: About,
meta: title: 'About' ,
// example of 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('./views/About.vue')
,
path: '/:path(.*)', component: NotFound ,
];
const router = createRouter(
history: createWebHistory(),
routes,
);
// 路由全局前置守卫
router.beforeEach((to, from, next) =>
// console.log("路由全局前置守卫", to, from);
next();
);
// 路由全局后置守卫
router.afterEach((to, from, next) =>
console.log('路由全局后置守卫', to, from);
next();
);
export default router;
注册路由
/main.js
import createApp from 'vue';
// import './tailwind.css';
import App from './App.vue';
import router from './routes';
createApp(App).use(router).mount('#app');
src/App.vue
<template>
<router-view />
</template>
效果展示:
状态管理:Vuex
yarn add vuex
初始化vuex,src/store/index.js
import createStore from 'vuex';
const store = createStore(
state()
return
count: 0,
;
,
mutations:
increment(state)
state.count++;
,
,
);
export default store;
挂载:
import createApp from 'vue';
import App from './App.vue';
import router from './routes';
import store from './store';
createApp(App).use(router).use(store).mount('#app');
使用:
<template>
<div>home page</div>
<p> store.state.count </p>
<button @click="toAbout">toAbout</button>
<button @click="increment">+</button>
</template>
<script setup>
import router from '../routes';
import store from '../store';
const toAbout = () =>
router.push('./about');
;
const increment = () =>
store.commit('increment');
console.log(store.state.count);
;
</script>
效果:
UI组件库: 按需导入 Element UI
yarn add element-plus
yarn add unplugin-vue-components unplugin-auto-import --dev
在vite.config.js中导入element
import defineConfig from 'vite';
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import ElementPlusResolver from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/
export default defineConfig(
plugins: [
vue(),
AutoImport(
resolvers: [ElementPlusResolver()],
),
Components(
resolvers: [ElementPlusResolver()],
),
],
);
多语言设置: 导入vue-i18n
yarn add vue-i18n
文件路径: plugins/i18n.js
在src目录下建立lang文件夹,存放不同语言的文件
i18n.js文件配置
import createI18n from 'vue-i18n';
import zhCN from 'element-plus/es/locale/lang/zh-cn';
import zhTW from 'element-plus/es/locale/lang/en';
import zhBG from 'element-plus/es/locale/lang/zh-tw';
import en from '@/lang/en-us';
import zh from '@/lang/zh-cn';
import tw from '@/lang/zh-tw';
const mergeZH = Object.assign(, zhCN, zh);
const mergeEN = Object.assign(, zhBG, en);
const mergeTW = Object.assign(, zhTW, tw);
const lang = localStorage.getItem('lang');
const i18n = createI18n(
locale: lang || 'zh',
messages:
en: mergeEN,
zh: mergeZH,
tw: mergeTW
);
export default i18n;
在main.js当中引入
数据请求:axios
安装axios和 vue-axios
yarn add axios vue-axios
新建http.js文件路径,plugins/http.js
// Configuration of Axios
import axios from 'axios';
const baseUrl = process.env.VUE_APP_BASE_URL;
axios.defaults.baseURL = `http:192.168.1.1:8800/api/v2`;
// Error message processing
const errorHandle = (status, other) =>
console.log(status);
if (status !== 200)
console.log(other);
;
// Add request interceptor
axios.interceptors.request.use(
(config) =>
/* if (localStorage.elementToken)
config.headers.Authorization = localStorage.elementToken;
console.log(config); */
if (config.method == 'post')
config.data =
...config.data
;
else if (config.method == 'get')
config.params =
_t: Date.parse(new Date()) / 1000,
...config.params
;
config.headers['Cache-Control'] = 'no-cache';
config.headers['Content-Type'] = 'application/json';
config.headers.Accept = 'application/json';
config.retry = 4;
config.retryDelay = 1000;
config.timeout = 60000;
console.log(config);
return config;
,
(error) =>
// Response error handling
return Promise.reject(error);
);
// Add response interceptor
axios.interceptors.response.use(
(response) =>
// console.log(response.data.token);
// response.headers['Authorization'] = response.data.token;
return response.status === 200
? Promise.resolve(response.data)
: Promise.reject(response);
,
(error) =>
// Response error handling
const response = error;
if (response)
errorHandle(response.status, response.data.message);
return Promise.reject(response.data);
else
console.log('The link has been broken');
);
export default axios;
在main.js当中引入
import createApp from 'vue';
import App from './App.vue';
import router from './router';
import stroe from './stroe';
import i18n from './plugins/i18n';
import axios from './plugins/http';
import VueAxios from 'vue-axios';
const app = createApp(App)
.use(router)
.use(stroe)
.use(i18n)
.use(VueAxios, axios: axios )
.mount('#app');
// provide 'axios'
app.provide('$http', app.config.globalProperties.axios);
app.mount('#app');
最后附上vite.config.js配置文件
import defineConfig from 'vite';
import path from 'path';
import vue from '@vitejs/plugin-vue';
import eslintPlugin from 'vite-plugin-eslint';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import ElementPlusResolver from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/
export default ( mode ) =>
console.log(mode);
const __DEV__ = mode === 'development';
const alias =
'@': path.resolve(__dirname, './src'),
pages: path.resolve(__dirname, './src/pages'),
assets: path.resolve(__dirname, './src/assets'),
store: path.resolve(__dirname, './src/store'),
components: path.resolve(__dirname, './src/components')
;
if (__DEV__)
// 解决警告You are running the esm-bundler build of vue-i18n.
alias['vue-i18n'] = 'vue-i18n/dist/vue-i18n.cjs.js';
return defineConfig(
plugins: [
vue(),
eslintPlugin(),
AutoImport(
resolvers: [ElementPlusResolver()]
),
Components(
resolvers: [ElementPlusResolver()]
)
],
resolve:
alias
);
;
vue3.0入门:vite构建vue项目
使用vite构建项目步骤
- 安装node,cmd输入:node -v验证是否安装成功;一般node安装后会自动安装npm,cmd输入:npm -v验证是否安装成功
- 选择一个文件夹作为项目文件夹,搜索框输入cmd,输入:npm init @vitejs/app
- 输入项目名称或者按enter使用默认名称:vite-project
- 选择框架vue
- 进入项目:cd vite-project
- 执行:npm install
- 运行项目:npm run dev
- 如果出现报错,管理vue模板校验:VSCode -> 设置 -> 取消勾选Vetur>Validation:template
单文件组件
<template>
</template>
<script>
export default
</script>
<style>
</style>
vite项目的单文件组件使用逻辑
- 自定义的单文件组件如helloworld.vue通过export导出
- 在app.vue中通过import导入自定义的单文件组件
- 在main.js中通过mount方法挂载
viet项目在app.vue中同样可使用单文件组件的形式,这时如果同时要引入自定义的单文件组件,需使用如下方式:
<!-- 例如引入自定义单文件组件HelloWorld.vue-->
<script>
import HelloWorld from ./components/HelloWorld.vue
export default
components:
HelloWorld
,
data()
return
// ...根组件中数据
</script>
使用规范
- 根组件app.vue的template标签中使用引入的子组件HelloWorld.vue时如果报错,子组件中模板应使用单根组件形式
<template>
<div>
<!-- HelloWorld.vue文件中只有一个根节点的模板才不会报错-->
</div>
</template>
- 在父组件app.vue中使用引入的子组件时,可使用小写,必须用横杠连接;使用子组件必须有闭合标签
<template>
<HelloWorld/>
<hello-world/>
</template>
以上是关于使用vite+vue3构建生产级项目架构的主要内容,如果未能解决你的问题,请参考以下文章