vite vue项目搭建

这篇博客详细介绍了如何使用Vite搭建Vue3项目,包括创建项目、安装和配置Sass、自动导入插件、设置路由、安装Pinia状态管理、封装axios以及配置@别名。还涉及到Element Plus组件库的引入和Mock数据的设置。
摘要由CSDN通过智能技术生成

1. 创建 vite 项目

npm create vite@latest

ele

 2. 安装sass/less ( 一般我使用sass )

cnpm add -D sass

cnpm add -D less

3. 自动导入 两个插件 使用之后,不用导入vue中hook reactive ref  

cnpm install -D unplugin-vue-components unplugin-auto-import

在 vite.config.ts 中配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 自动导入vue中hook reactive ref等
import AutoImport from "unplugin-auto-import/vite"
//自动导入ui-组件 比如说ant-design-vue  element-plus等
import Components from 'unplugin-vue-components/vite';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      //安装两行后你会发现在组件中不用再导入ref,reactive等
      imports: ['vue', 'vue-router'],
      //存放的位置
      dts: "src/auto-import.d.ts",
    }),
    Components({
      // 引入组件的,包括自定义组件
      // 存放的位置
      dts: "src/components.d.ts",
    }),
  ],

})

记得在 main.ts 中引入 框架样式

import 'element-plus/dist/index.css'

这一步做完最好重新运行项目

4. 安装 router

cnpm install vue-router@4

 在src下创建一个 routes 文件夹,再创建一个 index.ts 文件   

import { createRouter, createWebHistory } from "vue-router";

let routes= [
    {
        path: "/",
        redirect: "/home"
    },
    {
        path: '/home',
        name: 'home',
        //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
        component: () => import('../views/home.vue')
    }
]
// 路由
const router = createRouter({
    history: createWebHistory(),
    routes
})
// 导出
export default router 

然后再到 main.ts 文件引入

import { createApp } from 'vue'
import './style.css'
import router from "./routes/index"; 
import App from './App.vue'

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

在 src 下新建 views 文件夹,整理页面( 清理多余的 components 文件,整理 app.vue 文件 )

app.vue 页面记得配置路由占位符

<template>
  <div>
    <router-view />
  </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
</style>

基本模板如下

<template>
  <div>

  </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
</style>

5. 安装pinia 因为是vue3+ts,安装pinia更好点,vuex拥抱ts没有pinia好

cnpm install pinia

在 main.ts 引入

import { createPinia } from 'pinia' 
const pinia = createPinia()
createApp(App).use(pinia)

在src下创建一个 store 文件夹,再创建一个 home.ts 文件

其它名也可以,因为pinia它有一个根文件,会把 defineStore 第一个参数当id值,相当于vuex中的 module 自动引入,也会在Vue.js devtools 插件中以第一个参数名展示(下面展示)
注意:defineStore第一个参数很重要,而且是唯一值。它的命名在devtools 插件能方便找到这个文件的数据,方便调试。

home.ts 文件

import { defineStore } from 'pinia'
// useMain  可以是 useUser、useCart 之类的名字 
// defineStore('main',{..}) 在devtools 就使用 main 这个名
export const useMain = defineStore('main', {
    // 相当于data
    state: () => {
        return {
          // 所有这些属性都将自动推断其类型,如果推断失败可以试下 as xxx
          counter: 0,
          name: 'Eduardo',
        }
    },
    // 相当于计算属性
    getters: {
        doubleCount: (state) => {
            return state.counter * 2
        },
    },
    // 相当于vuex的 mutation + action,可以同时写同步和异步的代码
    actions: {
        increment() {
          this.counter++
        },
        randomizeCounter() {
            setTimeout(() => {
                this.counter = Math.round(100 * Math.random())
            }, 0);
        },
    },
})

新建 testPinia.vue 文件 测试 pinia 是否生效。

<template>
    <div>
        <div>counter:{{ counter }}</div>
        <div>doubleCount:{{ doubleCount }}</div>
        <el-button @click="main.randomizeCounter()">counter(round)</el-button>
        <el-button type="primary" @click="main.increment()">counter++</el-button>

        <div>{{ name }}</div>
        <el-button @click="amend()">修改</el-button>
    </div>
</template>
<script setup lang='ts'>

//引入想要的pinia文件 {} 里面就是对应导出的名字
import { useMain } from '../store/home'
import { storeToRefs } from 'pinia';

const main = useMain()
// 解构main里面的state和getters的数据,
// 使用storeToRefs解构才有响应式,响应式可以直接修改数据,不过这我只用来渲染
let { counter, name, doubleCount } = storeToRefs(main)

//(常用方法三种)
//常用方法一: 使用数据
console.log(counter);
//使用方法(方法目前不能解构)
main.increment()


// 常用方法二:修改数据
counter.value = 9999

//常用方法三:
//进阶使用$patch,多个修改
const amend = () => {
    main.$patch((state: any) => {
        state.counter += 10;
        state.name = '张三'
    })
}
</script>

6. 安装和封装 axios 

为什么要封装axios?

axios.get().then()   这样的书写,会有缺陷,在以下缺点
请求头能不能统一处理
    解决: 创建一个 request/request.js 文件夹,
        在里面可以使用axios.create创建实例对象
        也可以在里面设置  请求 与 响应 拦截器

不便于接口的统一管理  
    解决:在 request 文件夹加多一个api文件来管理所有接口,
        (会先导入rerequest.js的实例)
        并使用函数,不然每次发请求时都会跑一次api文件

容易出现回调地狱
    LogoutAPI () 最终的结果是返回proise对象
    解决:acync + await
    await 后面一般放promise对象
注意:但封装axios后还是可以用 .then() 

开始安装

cnpm install axios

封装 request 先在 src 下创建一个 request 文件夹,并添加一个  getBaseUrl.ts  文件

const getBaseUrl = () => {

    // 当项目要部署的时候把这里的 baseURL 更换就行了

    let BASE_URL = "";

    // 本地
    // BASE_URL = "/api";

    // 云
    // BASE_URL = "";

    // mock
    BASE_URL = "/api";

    return BASE_URL;

};

export default getBaseUrl;

添加一个  request.ts  文件

import axios from 'axios'

import getBaseUrl from './getBaseUrl'
// 创建axios实例
const request = axios.create({
    baseURL: getBaseUrl(),// 所有的请求地址前缀部分(没有后端请求不用写)
    timeout: 80000, // 请求超时时间(毫秒)
    // 这一步千万注释掉 会影响后端的 cors 跨域
    // withCredentials: true,// 异步请求携带cookie
    // headers: {
    // 设置后端需要的传参类型
    // 'Content-Type': 'application/json',
    // 'token': x-auth-token',//一开始就要token
    // 'X-Requested-With': 'XMLHttpRequest',
    // },
})
 
// request拦截器
request.interceptors.request.use(
    config => {
        // 如果你要去localStor获取token,(如果你有)
        // let token = localStorage.getItem("x-auth-token");
        // if (token) {
            //添加请求头
            //config.headers["Authorization"]="Bearer "+ token
        // }
        return config
    },
    error => {
        // 对请求错误做些什么
        Promise.reject(error)
    }
)
 
// response 拦截器
request.interceptors.response.use(
    response => {
        // 对响应数据做点什么
        return response.data
    },
    error => {  
        // 对响应错误做点什么
        //响应错误
		let message = "";
		if (error.response && error.response.status) {
			const status = error.response.status;
			switch (status) {
				case 400:
					message = "请求错误";
					break;
				case 401:
					message = "请求错误";
					break;
				case 404:
					message = "请求地址出错";
					break;
				case 408:
					message = "请求超时";
					break;
				case 500:
					message = "服务器内部错误!";
					if(error.response.data && error.response.data == '该账号已存在,请重新输入!'){
						message = "该账号已存在,请重新输入!";
					}
					break;
				case 501:
					message = "服务未实现!";
					break;
				case 502:
					message = "网关错误!";
					break;
				case 503:
					message = "服务不可用!";
					break;
				case 504:
					message = "网关超时!";
					break;
				case 505:
					message = "HTTP版本不受支持";
					break;
				default:
					message = "请求失败";
			}
			return Promise.reject(error);
		}
	  	return Promise.reject(error);
    }
)
export default request

新建 api 文件夹,新建 mock.ts 文件夹 里面是基本的接口调用例子,和 mock 接口

import request from "../request";

export const getTestApi = (data: any) => {
    return request.get("/getMenu", {
        params: data, timeout: 1000,
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
    })
};
export const postTestApi = (data: any) => {
    return request.post("/getMenu", {
        data: data, timeout: 1000,
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
    })
};
export const deleteTestApi = (data: any) => {
    return request.delete("/getMenu", {
        data: data, timeout: 1000,
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
    })
};
export const putTestApi = (data: any) => {
    return request.put("/getMenu", {
        data: data, timeout: 1000,
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
    })
};

export const getMockFirstApi = () => {
    return request.get("/first")
};

export const getMockMenuApi = (data: any) => {
    return request.get("/menu", {
        params: data,
    })
};

在 vite.config.ts 文件 配置 proxy 代理

proxy 是 前端 开发阶段 使用的 跨域处理,部署的时候都是 后端使用 cors 或者 nginx 反向代理

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 自动导入vue中hook reactive ref等
import AutoImport from "unplugin-auto-import/vite"
//自动导入ui-组件 比如说ant-design-vue  element-plus等
import Components from 'unplugin-vue-components/vite';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
      // ...
  ],
  server: {
    host: '0.0.0.0', // 指定服务器应该监听哪个 IP 地址
    open: false, //自动打开 
    port: 8888,
    proxy: {
        '/api': { // 匹配请求路径,
            
            // 本地
            // target: 'http://127.0.0.1:3000', // 代理的目标地址

            // mock
            target: 'http://127.0.0.1:3300', // 代理的目标地址
            
             // 开发模式,默认的127.0.0.1,开启后代理服务会把origin修改为目标地址
            changeOrigin: true,
            // secure: true, // 是否https接口
            // ws: true, // 是否代理websockets

            // 路径重写,**** 如果你的后端有统一前缀(如:/api),就不开启;没有就开启
            //简单来说,就是是否改路径 加某些东西
            rewrite: (path) => path.replace(/^\/api/, '') 
        }
    }
  }
})

7. 配置@别名

cnpm install @types/node

安装这个包 让 nodeJS 支持 ts
让 vscode 认识@符号, 在 tsconfig.json 文件

{
  "compilerOptions": {
    // ...
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

让 vite 识别@符号,在 vite.config.ts 文件

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 配置@别名
import { resolve } from "path"; 

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // ↓解析配置
  resolve: {
    // ↓路径别名
    alias: {
      "@": resolve(__dirname, "./src")
    }
  }
})

将 request.ts 文件 中 进行测试 @ 功能

// import getBaseUrl from './getBaseUrl'
import getBaseUrl from '@/request/getBaseUrl'

9. 安装element-puls组件库

cnpm install element-plus --save

vite.config.ts

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  // ...
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

重新运行 打开 testPinia 页面 看到 

10. 进行 mock 数据

在 src 同级目录下 创建 mock 文件夹  开始 mock 假数据,在 mock 文件夹下
cnpm install --save express
创建 index.js , data 文件夹

index.js

const express = require("express")
const app = express()

const url = require("url")

app.get("/first", (req, res)=>{
    res.send(' first 接口调用成功')
})

const menu = require("./data/menu.json")

app.get("/menu", (req, res)=>{
    const user = url.parse(req.url, true).query.user
    res.send(menu)
})

app.listen(3300, ()=>{
    console.log("服务器运行在 3300")
})

在 data 文件夹 下,新建 menu.json

{
    "code": 200,
    "msg": "操作成功",
    "data": {
      "menu": [
        {
          "id": 666,
          "title": "123123",
          "path": "",
          "component": null,
          "children": [
            {
              "id": 888,
              "title": "数字字典",
              "path": "/mockPackage/test",
              "component": "mockPackage/test",
              "children": []
            }
          ]
        }
      ],
      "authoritys": [
        "ROLE_admin",
        "ROLE_normal"
      ]
    }
  }
  

新建 testMockApi.vue 页面,进行 mock 接口 测试

<template>
    <div>
        testMockApi
        <br>
        <br>
        <br>
        第一个接口: {{ state.firstMsg }}
        <br>
        <br>
        <br>
        第二个接口:
        {{ state.menuData.menu }}
        <br>
        <br>
        <br>
        {{ state.menuData.authoritys }}
    </div>
</template>
  
<script setup lang="ts">
import { getMockFirstApi, getMockMenuApi } from "@/request/api/mock"

interface stateType {
    firstMsg: any,
    menuData: object
}

const state: stateType = reactive({
    firstMsg: "",
    menuData: {}
})

const getData = async () => {
    state.firstMsg = await getMockFirstApi()
    const { data } = await getMockMenuApi("")
    state.menuData = data
}

getData()

</script>
  
<style scoped></style>
  

修改 style.css 样式

body {
  margin: 0;
  padding: 0;
}

#app {
  height: 100vh;
  width: 100vw;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值