基于vite创建Vue项目

322 阅读6分钟

搭建第一个 Vite 项目

兼容性注意

Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。(参考自vite官网cn.vitejs.dev/guide/#scaf…

构建项目雏形 image.png image.png

查看 create-vite 以获取每个模板的更多细节:vanillavanilla-tsvuevue-tsreactreact-tspreactpreact-tslitlit-tssveltesvelte-ts

在项目被创建后,通过以下步骤安装依赖并启动开发服务器:

# 打开项目  
cd <your-project-name>  
  
# 安装依赖  
npm install  
  
# 启动项目  
npm run dev

项目成功启动的界面如下

image.png

Vite基础配置

Vite 配置文件 vite.config.js 位于项目根目录下,项目启动时会自动读取。

本项目针对公共基础路径、自定义路径别名、服务器选项、构建选项等做了如下基础配置:

import { defineConfig } from 'vite';  
import { resolve } from 'path';  
import vue from '@vitejs/plugin-vue';  
  
export default defineConfig({  
    base'./',  
    plugins: [  
      vue(),  
    ],  
    resolve: {  
      // 设置别名
      alias: {  
        '@'resolve(__dirname, './src') ,  
      },  
      // routes引入组件的时候可以省略后缀,没有extensions则不可以省略
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
    },  
    server: {  
      // 是否开启 https  
      httpsfalse,  
      // 端口号  
      port3000,  
      // 监听所有地址  
      host'0.0.0.0',  
      // 服务启动时是否自动打开浏览器  
      opentrue,  
      // 允许跨域  
      corstrue,  
      // 自定义代理规则  
      proxy: {},  
    },  
    build: {  
      // 设置最终构建的浏览器兼容目标  
      target'es2015',  
      // 构建后是否生成 source map 文件  
      sourcemapfalse,  
      //  chunk 大小警告的限制(以 kbs 为单位)  
      chunkSizeWarningLimit2000,  
      // 启用/禁用 gzip 压缩大小报告  
      reportCompressedSizefalse,  
    },  
});

更多配置参考cn.vitejs.dev/config/

注意

没有配置extensions,路由引入组件.vue 不可省略

image.png

否则会出现如下错误

image.png 规范目录结构

image.png 集成 Vue Router 路由工具

  1. 安装依赖
npm i vue-router@4
  1. 创建路由配置文件

在 src/router 目录下新建 index.js 文件与 modules 文件夹

image.png

关于路由表,建议根据功能的不同拆分到modules文件夹中,优点是:

  • 方便后期维护
  • 减少代码合并的冲突

modules文件夹新建base.js

export default [  
  {
    path: "/login",
    component: () => import("@/views/login"),
  }
];

index.js中的内容如下

import { createRouter, createWebHistory } from 'vue-router'

// history:createWebHistory() 是history模式 即路由是 域名/a 这里采用

// history:createWebHashHistory() 是hash模式 即路由是 域名/#/a

// import.meta.env.BASE_URL 是模块的基本URL 未配置则为 /

// routes 则为包含路由信息的数组构成

import baseRouters from './modules/base';  
  
const routes = [...baseRouters];  


const router = createRouter({

    history: createWebHistory(import.meta.env.BASE_URL),

    routes

})

  


export default router

根据路由配置的实际情况,需要在 src 下创建 views 目录,用来存储页面组件。

3.在main.js中导入

import { createApp } from 'vue'  
  
import App from './App.vue'  
import router from './router'  
  
const app = createApp(App)  
  
app.use(router)  
  
app.mount('#app')

4.渲染内容

RouterView 是 Vue Router 提供的一个组件,用于根据当前路由状态动态渲染匹配到的组件内容,从而实现单页面应用中不同页面的切换。

通常在App.vue中引入

<template>
  <router-view /><!-- 这里会根据路由匹配渲染不同的组件 -->
</template>

注意

在vue3中没有this,所以我们没办法像下面这样使用

// 路由器实例 用于在 Vue 组件中进行路由导航操作  
this.$router  
// 如跳转到不同的路由、在路由之间切换等  
this.$router.push()  
this.$router.replace()  
this.$router.go()  
  
  
// 当前路由信息对象 包含了当前页面的路由相关信息  
this.$route  
// 可使用以下获取路径、参数、查询参数、哈希等  
this.$route.path  
this.$route.params  
this.$route.query

但是,给我们提供了其他方法以供使用。在模版中我们依旧可以使用route、router

<!-- 选项式 -->  
<script>  
import { useRouter, useRoute } from 'vue-router'  
  
export default {  
  setup() {  
    // 路由器实例  
    const router = useRouter()  
    // 当前路由信息对象  
    const route = useRoute()  
  
    // 示例  
    router.push('/home')  
    const path = route.path  
      
  },  
}  
</script>  
  
<!-- 组合式 -->  
<script setup>  
import { useRouter, useRoute } from 'vue-router'  
  
// 路由器实例  
const router = useRouter()  
// 当前路由信息对象  
const route = useRoute()  
  
// 示例  
router.push('/home')  
const path = route.path  
</script>

集成 Pinia 全局状态管理工具

1.安装依赖

npm i pinia

2.创建仓库配置文件

在 src/store 目录下新建 index.js 文件与 modules 文件夹

image.png

modules文件夹下新建counter.js

import { defineStore } from 'pinia';  
  
export const useCounterStore = defineStore('counter', {  
  state() => ({  
    count1,  
  }),  
  actions: {  
    accumulate() {  
      this.count++;  
    },  
  },  
});

index.js

import { createPinia } from 'pinia';  
  
const store = createPinia();  
  
export default store;  
  
export * from './modules/counter';

开发中需要将不同功能所对应的状态,拆分到不同的 modules,好处如同路由模块一样。

3.在main.js中导入

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store';

const app = createApp(App)
app.use(router)
app.use(store)
app.mount('#app')

集成 Axios HTTP 工具

  1. 安装依赖
npm i axios
  1. 请求配置

在 utils 目录下创建 request.js 文件,配置好适合自己业务的请求拦截和响应拦截:

image.png

request.js

import axios from 'axios';  
  
// 创建请求实例  
const instance = axios.create({  
  baseURL'/api',  
  // 指定请求超时的毫秒数  
  timeout1000,  
  // 表示跨域请求时是否需要使用凭证  
  withCredentialsfalse,  
});  
  
// 前置拦截器(发起请求之前的拦截)  
instance.interceptors.request.use(  
  (config) => {  
    /**  
     * 在这里一般会携带前台的参数发送给后台,比如下面这段代码:  
     * const token = getToken()  
     * if (token) {  
     *  config.headers.token = token  
     * }  
     */  
    return config;  
  },  
  (error) => {  
    return Promise.reject(error);  
  },  
);  
  
// 后置拦截器(获取到响应时的拦截)  
instance.interceptors.response.use(  
  (response) => {  
    /**  
     * 根据你的项目实际情况来对 response 和 error 做处理  
     * 这里对 response 和 error 不做任何处理,直接返回  
     */  
    return response;  
  },  
  (error) => {  
    const { response } = error;  
    if (response && response.data) {  
      return Promise.reject(error);  
    }  
    const { message } = error;  
    console.error(message);  
    return Promise.reject(error);  
  },  
);  
  
// 导出常用函数  
  
/**  
 * @param {string} url  
 * @param {object} data  
 * @param {object} params  
 */  
export function post(url, data = {}, params = {}) {  
  return instance({  
    method'post',  
    url,  
    data,  
    params,  
  });  
}  
  
/**  
 * @param {string} url  
 * @param {object} params  
 */  
export function get(url, params = {}) {  
  return instance({  
    method'get',  
    url,  
    params,  
  });  
}  
  
/**  
 * @param {string} url  
 * @param {object} data  
 * @param {object} params  
 */  
export function put(url, data = {}, params = {}) {  
  return instance({  
    method'put',  
    url,  
    params,  
    data,  
  });  
}  
  
/**  
 * @param {string} url  
 * @param {object} params  
 */  
export function _delete(url, params = {}) {  
  return instance({  
    method'delete',  
    url,  
    params,  
  });  
}  
  
export default instance;

之后在 api 文件夹中以业务模型对接口进行拆分,举个例子,将所有跟用户相关接口封装在 user.js 中。

在 user.js 中比如有登录、注册、获取用户信息等方法,如果有业务逻辑变动,只需要修改相关方法即可。

  
  /**  
   * 登录  
   * @param {String} username 用户名  
   * @param {String} password 密码  
   * @returns  
   */  
  export function login(username, password) {  
    return post('/login', {  
      username,  
      password,  
    });  
  }

模拟演示

在需要使用接口的地方,引入对应的业务模型文件,参考如下:

import { login } from '@/api/user'

然后在methods: {}中使用该方法

集成 CSS 预处理器 Less

本项目使用 CSS 预处理器 Less,直接安装为开发依赖即可。

Vite 内部已帮我们集成了相关的 loader,不需要额外配置。

1.安装依赖

npm i less -D

2.使用 在 <style></style> 样式标签中引用 lang="less" 即可。

<style lang="less"></style>

全局样式

在 src/style 目录下创建 variables.less 全局样式文件:

image.png

在 vite.config.js 配置文件中新增CSS 预处理器相关配置即可实现 less 全局样式:

import { resolve } from 'path';  
  
export default defineConfig({  
    css: {  
      preprocessorOptions: {  
        less: {  
          modifyVars: {  
            hack: `true; @import (reference) "${resolve('src/style/variables.less')}";`,  
          },  
          math'strict',  
          javascriptEnabledtrue,  
        },  
      },  
    },  
});

样式穿透

在 Vue3 中,改变了以往样式穿透的语法,如果继续使用 ::v-deep/deep/>>> 等语法的话,会出现一个警告,下面是新的语法:

/* 深度选择器 */  
:deep(selector) {  
  /* ... */  
}  
  
/* 插槽选择器 */  
:slotted(selector) {  
  /* ... */  
}  
  
/* 全局选择器 */  
:global(selector) {  
  /* ... */  
}

至此,一个基于 JavaScript + Vite + Vue3 + Vue Router + Pinia + Axios + Less 的前端项目开发环境搭建完毕。

文章参考链接

代码格式化、规范化