手把手教你用vite2搭建Vue3.0项目

1,633 阅读3分钟

开始

vite2新型前端构建工具,能够显著提升前端开发体验,话不多说,我们先来体验一下

搭建vite项目

Vite 需要 Node.js 版本 >= 12.0.0。

# NPM
npm init @vitejs/app

# YARN 
yarn create @vitejs/app

vite-create.png 然后按照操作,选择你想要的模板执行就行。

我们可以通过附加的命令行选项直接指定项目名称和你想要使用的模板,可以直接生成项目

# npm 6.x
npm init @vitejs/app my-vue-app --template vue

# npm 7+, 需要额外的双横线:
npm init @vitejs/app my-vue-app -- --template vue

# yarn
yarn create @vitejs/app my-vue-app --template vue

配置项目

首先看下项目结构:

# my-vue-app

├── index.html
├── package.json
├── public
│   └── favicon.ico
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   └── HelloWorld.vue
│   └── main.js
├── tree.md
└── vite.config.js

打开项目,我们看到结构还是cli4结构类似的,就是简单了好多了。

vite2现在还没有开箱即用的模板,供我们使用,不过文档还是比较全面的。vite中文文档

下面我们配置下:

1. vue-router

 # vue-router4.0正式版已经发布,我们使用4.0版本
 # 如果你想下载最新版本 yarn add vue-router@4. 会让你选择4.0所有版本,你选择想要的版本即可

 # NPM
 npm install vue-router@4.0.4

 # YARN
 yarn add vue-router@4.0.4
1. 在src创建router文件夹,新建index.js文件
 import { createRouter, createWebHashHistory } from 'vue-router'
 import Home from '../views/Home.vue'

 const routes = [
   {
     path: '/',
     name: 'Home',
     component: Home
   },
   {
     path: '/about',
     name: 'About',
     component: () => import('@/views/About.vue') // @/views设置的别名
   }
 ]

 const router = createRouter({
   history: createWebHashHistory(import.meta.env.BASE_URL),
   routes
 })

 export default router

2. 在main.js引入router
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'

createApp(App).use(router).mount('#app')
3. 修改App.vue文件
<template>
  <router-view />
</template>

<script setup>
</script>

<style></style>         
4. src/views添加Home.vue
<template>
  <router-link to="/">
    Home
  </router-link>
  <router-link to="/about">
    About
  </router-link>
</template>

<script>
export default {

}
</script>
5. src/views添加About.vue
//  About.vue
<template>
  <div>About</div>
</template>

<script>
export default {

}
</script>

<style></style>

在链接中输入http://localhost:8000/#/about 内容显示about,那么恭喜你已经配置成功了。

6. 模块化

如果你想把项目模块化,可以按照下面的结构和方式配置(vuex类似),如果不是,请跳过此步骤

 ├── index.html
 ├── package.json
 ├── public
 │   └── favicon.ico
 ├── src
 │   ├── App.vue
 │   ├── assets
 │   │   └── logo.png
 │   ├── components
 │   │   └── HelloWorld.vue
 │   ├── main.js
 │   ├── router
 │   │   └── index.js
 │   └── views
 │       ├── Home.vue
 │       ├── about
 │       │   ├── index.vue
 │       │   └── router
 │       │       └── index.js
 │       └── indo
 │           ├── index.vue
 │           └── router
 │               └── index.js
 ├── tree.md
 ├── vite.config.js
 └── yarn.lock
 // about/router/index.js
 export default [
   {
     path: '/about',
     name: 'About',
     component: () => import('../index.vue'),
   },
 ];

每一个模块都包含一个router文件夹,我们可以通过动态引入的方式引入模块中的路由,了解详情 不用一个一个去引入,在src/router中设置

// src/router/index.js 
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routesModules = import.meta.globEager('../views/**/*.js')
const modules = []
Object.keys(routesModules).forEach(key => {
  modules.push(...routesModules[key].default)
})
console.log('modules: ', modules);

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  ...modules
]

const router = createRouter({
  history: createWebHashHistory(import.meta.env.BASE_URL),
  routes
})

export default router

在链接中输入http://localhost:8000/#/info 内容显示Info,那么恭喜你已经配置成功了。

2. 安装scss

# NPM
npm install sass -D 

# YARN 
yarn add sass -D 

一般我们都是设置公用的scss文件,统一设置公用的样式,方便统一修改统一的样式

1. 我们可以在src新建styles文件夹,新建common.scss文件
$themeColor: #f4364c;
2. 在vite.config.js中设置公用的引入common.scss就可以直接在vue文件中使用公用的样式了
import { defineConfig } from 'vite'
const {resolve} = require('path')
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    port: 8000 // 配置启用的端口号
  },
  resolve:{
    // 设置别名
    alias:{
      '@/views': resolve(__dirname, 'src/views/'),
      '@/styles': resolve(__dirname, 'src/styles/')
    }
  },
  css: {
    preprocessorOptions: {
      // 引入公用的样式
      scss: {
        additionalData: `@import "@/styles/common.scss";`
      }
    }
  }
})

测试:

# About.vue
<template>
 <div class="about">About</div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
.about {
  color: themeColor;
 }
</style>

3. vuex

 # vuex正式版已经发布,我们使用4.0版本,
 # 如果你想下载最新版本 yarn add vuex@4. 会让你选择4.0所有版本,你选择想要的版本即可

 # NPM
 npm install vuex@4.0.0

 # YARN
 yarn add vuex@4.0.0
1. src下添加store文件夹,新建index.js
 import {createStore} from 'vuex'
      
 const store = createStore({
   state: {
     count: 0
   },
   mutations: {
     increment (state) {
       state.count++
     }
   },
   getters: { },
   actions: { }
 })

 export default store
2. 在main.js引入vuex
 import { createApp } from 'vue'
 import router from './router'
 import store from './store'
 import App from './App.vue'

 createApp(App).use(router).use(store).mount('#app')
3. 持久化,需要下载vuex-persistedstate
 # NPM
 npm installvuex-persistedstate@4.0.0

 # YARN
 yarn add vuex-persistedstate@4.0.0
4. store/index.js 中配置
  import { createStore } from 'vuex'
  import createPersistedState from 'vuex-persistedstate'

  const store = createStore({
    ...

    plugins: [
      createPersistedState({
        storage: window.sessionStorage // 修改存储的状态
      })
    ] // 状态持久化
  })

  export default store
5. 如果想模块化,可以参考 详情

4. Eslint

让我们的代码有更好的代码规范和统一的代码格式,方面多人开发,和阅读代码。

1. 首先安装eslint以及其他的依赖
 # NPM
 npm install eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-vue -D
 
 # YARN 
 yarn add eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-vue -D
2. 根目录添加 .eslintrc.js
module.exports = {
  extends: ['plugin:vue/vue3-essential', 'airbnb-base'],
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
  },
  plugins: ['vue'],
  rules: {
    // 自己写一些想配置的规则
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境禁用consele
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境禁用debugger
    'linebreak-style': 'off', // 忽略检测换行风格
    'vue/max-attributes-per-line': 'off', // 关闭强制 html 标签换行
    'no-param-reassign': ['error', { props: false }], // 允许修改参数中的属性值
    'prefer-destructuring': ['error', { object: true, array: false }], // 允许数组通过下标取值
    'max-len': 'off', // 对象选项
    'no-use-before-define': 'off', // 允许定义之前使用
    'func-names': 'off', // 允许使用匿名函数
    'no-shadow': ['error', { allow: ['state'] }], // 允许对其进行阴影处理
    'import/prefer-default-export': 'off', // 模块只输出一个变量时,是否需要添加default
    'no-plusplus': 'off', // 一元运算符
  },
  overrides: [
    {
      files: ['*.vue'],
      rules: {
        // 这里写覆盖vue文件的规则
      },
    },
  ],
};

3. 配置vscode

根目录添加 .vscode文件夹,文件夹下添加settings.json

// settings.json
{
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
        "source.fixAll": true,
        "source.fixAll.eslint": true
    },
    "[json]": {
        "editor.defaultFormatter": "vscode.json-language-features"
    },
}
4. 测试eslint

随便打开一个文件。我们用main.js为例,

如果出现eslint报错的情况,恭喜eslint已经生效了。

按下快捷键 Ctrl + Shift + P, 输入 ESLint: Manage Library Execution 选择并回车

会出现下图显示:

选中弹框的 Allow Everywhere 选项, 右下角的图标变为 √√ESLint

点击保存就会自动格式化我们的代码以及规范我们的代码。

了解更多 ESLint中文网 airbnb(爱彼迎)代码规范 airbnb代码规范 Vue代码规范

5. 安装Element Plus

# NPM
npm install element-plus --save

# YARN
yarn add element-plus --save

main.js中引入element-ui

import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import router from './router';
import App from './App.vue';
import 'element-plus/lib/theme-chalk/index.css';

createApp(App).use(router).use(ElementPlus).mount('#app');

6. axios

1. 下载axios
# NPM
npm install axios --save

# YARN
yarn add axios --save
2. 封装axios请求
/**
 * @file axios请求封装
 */
import axios from 'axios';
import { ElMessage } from 'element-plus';
// import { store } from '../store';

// 请求失败错误信息提示
function checkCode(message) {
  // 弹出错误信息
  ElMessage.closeAll();
  ElMessage({ message, type: 'error', customClass: 'deep-message' });
  // ElMessage.error(message)
}

// 响应时间
axios.defaults.timeout = 10000;
// `withCredentails`选项表明了是否是跨域请求
axios.defaults.withCredentials = true;
// 设置默认请求头
axios.defaults.headers = {
  'X-Requested-With': 'XMLHttpRequest',
  'Content-Type': 'application/json; charset=UTF-8',
};

const pending = []; // 声明一个数组用于存储每个ajax请求的取消函数和ajax标识
const cancelToken = axios.CancelToken;
const removePending = (config) => {
  const resUrl = `${config.url}&${config.method}`;
  // eslint-disable-next-line no-restricted-syntax
  for (const p in pending) {
    if (pending[p].url === resUrl) { // 当当前请求在数组中存在时执行函数体
      pending[p].fn(); // 执行取消操作
      pending.splice(p, 1); // 把这条记录从数组中移除
    }
  }
};

// 添加请求拦截器
axios.interceptors.request.use(
  (config) => {
    // 获取token
    // if (store.state.common.token) {
    //   // 判断是否存在token,如果存在的话,则每个http header都加上token
    //   config.headers.Authorization = store.state.common.token;
    // }
    removePending(config); // 在一个ajax发送前执行一下取消操作
    // eslint-disable-next-line new-cap
    config.cancelToken = new cancelToken((cf) => {
      // 这里的ajax标识我是用请求地址&请求方式拼接的字符串,当然你可以选择其他的一些方式
      pending.push({ url: `${config.url}&${config.method}`, fn: cf });
    });
    return config;
  },
  (error) =>
    // endLoading()
    // eslint-disable-next-line implicit-arrow-linebreak
    Promise.reject(error),

);

// 添加返回拦截器
axios.interceptors.response.use(
  (response) => {
    // endLoading()
    removePending(response.config); // 在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
    const { data, data: { code } } = response || {};
    const listCode = [0, 1001, 1000, 1100];
    if (typeof response !== 'undefined') {
      if (listCode.includes(code)) return data;
      if (response.data.msg) return response.data;
      checkCode(response.data.message);
    }
    return '';
  },
  (error) => {
    if (error && error.response) {
      switch (error.response.status) {
        case 400:
          error.message = '请求错误';
          break;
        case 401:
          error.message = '登录过期,请重新登录';
          // 跳到登录界面
          localStorage.clear();
          sessionStorage.clear();
          break;
        case 403:
          error.message = '拒绝访问';
          break;
        case 404:
          error.message = '请求失败';
          break;
        case 408:
          error.message = '请求超时';
          break;
        case 500:
          error.message = '服务器内部错误';
          break;
        case 501:
          error.message = '服务未实现';
          break;
        case 502:
          error.message = '无法连接服务器';
          break;
        case 503:
          error.message = '服务不可用';
          break;
        case 504:
          error.message = '连接服务器超时';
          break;
        case 505:
          error.message = 'HTTP版本不受支持';
          break;
        default:
      }
    } else {
      // error.message = '无法连接服务器'
    }
    // 对返回的错误处理
    return Promise.reject(error);
  },
);

export default {
  async get(url, params) {
    try {
      const res = await axios.get(url, { params });
      return typeof res.data !== 'undefined' && res.data;
    } catch (err) {
      return checkCode(err.message);
    }
  },
  async post(url, params) {
    try {
      const res = await axios({
        method: 'post',
        url,
        data: params,
      });
      return typeof res.data !== 'undefined' && res.data;
    } catch (err) {
      return checkCode(err.message);
    }
  },
  async put(url, params) {
    try {
      const res = await axios({
        method: 'put',
        url,
        data: params,
      });
      return typeof res.data !== 'undefined' && res.data;
    } catch (err) {
      return checkCode(err.message);
    }
  },
  async delete(url, params) {
    try {
      const res = await axios.delete(url, { params });
      return typeof res.data !== 'undefined' && res.data;
    } catch (err) {
      return checkCode(err.message);
    }
  },
  async all(url, params) {
    try {
      const res = await axios.all(url, { params });
      return typeof res.data !== 'undefined' && res.data;
    } catch (err) {
      return checkCode(err.message);
    }
  },
};

3. 本地调试设置跨域

使用proxy代理设置跨域,查看详情

// vite.config.js
export default {
  resolve: {
    proxy: {
      '/api': {
        target: 'https://xxx.com/api',
        changeOrigin: true,
      },
    },
  },
}
4. 使用
// about/api/index.js
import $api from '@/utils/request';

export default {
  getData(params) {
    return $api.get('/api/basis/Data',params);
  },
};
// about/index.vue
<template>
  <div>about</div>
</template>

<script>
import aboutApi from './api';

export default {
  setup() {
    const test = async () => {
      const result = await aboutApi.getData();
      console.log('result: ', result);
    };
    test();
  },
};
</script>

<style></style>

如果不想这么麻烦,安装k-cli,直接使用模板就行。

其他功能正在开发,敬请期待!!!