使用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
    }
  });
};

猜你喜欢

转载自blog.csdn.net/sinat_36728518/article/details/122960056
今日推荐