使用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构建项目步骤

  1. 安装node,cmd输入:node -v验证是否安装成功;一般node安装后会自动安装npm,cmd输入:npm -v验证是否安装成功
  2. 选择一个文件夹作为项目文件夹,搜索框输入cmd,输入:npm init @vitejs/app
  3. 输入项目名称或者按enter使用默认名称:vite-project
  4. 选择框架vue
  5. 进入项目:cd vite-project
  6. 执行:npm install
  7. 运行项目:npm run dev
  8. 如果出现报错,管理vue模板校验:VSCode -> 设置 -> 取消勾选Vetur>Validation:template

单文件组件

<template>  
</template>

<script>
export default

</script>

<style>
</style>

vite项目的单文件组件使用逻辑

  1. 自定义的单文件组件如helloworld.vue通过export导出
  2. 在app.vue中通过import导入自定义的单文件组件
  3. 在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构建生产级项目架构的主要内容,如果未能解决你的问题,请参考以下文章

使用Vite快速构建前端React项目

Vite+Vue3+Vant快速构建项目

vue3.0入门:vite构建vue项目

vue3.0入门:vite构建vue项目

构建一个 Vite + Vue3 项目 开发Cesium

vue3.x项目用vite构建之后提示“vite use `--host` to expose”问题