## 一(yī)、創建 vue3 項目
[Vite](https://so.csdn.net¶≤Ω₹/so/search?q=Vite&spm=™☆1001.2101.3001.7020)是(shì)一(yī)種新型前端構建工"¥(gōng)具,能(néng)夠顯著提升前端開(kāi)發體(tǐ)驗。
1、 在需要(yào)創建項目的(de)目錄下(xià)打開(kāi←δ↑) cmd,并輸入以下(xià)命令:
npm create vite@latest
2、 之後根據自(zì)己所需按照(zhào)提示操作(zuò)即可(kě<Ω→),這(zhè)裡(lǐ)是(shì)使用(yπòng) ts 創建 vue3 項目。
3、 随後使用(yòng) vs cod≥""¶e 打開(kāi)項目執行(xíng)對(duì)應命令即可(kě) ±σ♦完成項目的(de)創建。
## 二、修改配置文(wén)件(jià←€n)
這(zhè)裡(lǐ)我們需要(yào)注意到(dào) `÷"§vite.config.ts` 這(zhè)個(gè)配置文(wén)件(j≤α<φiàn),之後我們的(de)配置都(dōu)♠ ™σ會(huì)寫在這(zhè)裡(lǐ)。
```
import { defineConfig } from 'vit₽σπ★e'
import vue from '&Ω;@vitejs/plugin-vue&λ↔#39;
import { resolve } from 'path'π§€;
export default defineCoαεnfig({
// 基本路(lù)徑
base: './',
plugins: [
vue()
],
resolve: {
// src 别名配置
alias:€£ {
"@": ↕•resolve(__dirname, 'src'),
},
// 使用(yòng)路(lù)徑别名時(shíα)想要(yào)省略的(de)後綴名,可(kě)以自(z∞♠ì)己增減
extensions: ['.js& ©#39;, '.json', '.ts& Ω#39;]
},
server: {
// 端口号
port: 80≈↑"±80,
// 監聽(tīng)所有(yǒ₽&παu)地(dì)址
host: '0.0. ¥0.0',
// 服務啓♥®σ動時(shí)是(shì)否自(zì)動δΩ打開(kāi)浏覽器(qì)
open: true,
// 允許跨域
cors: true,
// 自(zì)定義代理ε∞ (lǐ)規則
proxy: {},
},
build: {
// 設置最終構建的(de)₽ ₽₩浏覽器(qì)兼容目标
target: 'es201↔✘5',
// 構建後是(shì)否生¶←(shēng)成 source map 文(wén)件(jiàn)σ↕
sourcemap: false,
// chunk 大( ≠£→dà)小(xiǎo)警告的(de)限制(zhì)(以 kbs 為(wèi)單∑♥α→位)
chunkSizeWa←←φ≤rningLimit: 2000,
// 啓用(yòng)/禁∞α✘•用(yòng) gzip 壓縮大(dà)小(xiǎo)報(bà≥♦∞♥o)告
reportCompresse×♣dSize: false,
},
})
```
在 ts 中,可(kě)能(néng)會(huì)提☆£示找不(bù)到(dào) path,可(kě)執行(xíng)以下(x✔☆ià)命令安裝:pnpm install ♦•@types/node --save-de✘₽∞v
**别名配置**:
在 `tsconfig.json` 中加€∏入配置
```
{
"compilerOptions&quo ↑t;: {
"target": &≤>→→quot;ES2020",
"β<useDefineForClassFields"∞λ'★;: true,
"€✔←module": "ESNext",≈≈
"lib": [×↓↕
"E ≥S2020",
&quo ∞"t;DOM",
"DOM.Iterab✔♠₩le"
],
"skip€☆LibCheck": true,
/* Bun®αdler mode */
"moduleResolut€&ion": "bundler",
"allowIm≥₩♠portingTsExtensions"επ;: true,
"resolveJsonMod✘↑ule": true,
"isolatedModules&quo↑÷ <t;: true,
"noEmit": true,≠§↕≈
"jsx": " ↓✔preserve",
/* Linting */
"strict": tru'♦e,
"noUnusedLoc♦®als": true,
"noUn&β♠usedParameters": true,
"noFallthroughCase∏'≥σsInSwitch": true,
/* 别名配置 */
"baseUrl":₽'" ".",
"pa®₽ths": {
"@/÷¶*": [
&quo★ ≠t;src/*"
],
},
},
"include&±✔>quot;: [
"src/*↓α*/*.ts",
"s£¥βrc/**/*.tsx",
"src/**/*.v₹←™☆ue"
],
"references&qu¥ δ♣ot;: [
{
&quα₩'ot;path": ""★;./tsconfig.node.json"
}
],
}
```
之後即可(kě)通(tōng)過@來(lái)代指src目錄了δ∞♠✘(le)。
## 三、安裝 router
1、 在項目目錄的(de)控制(zhì)台中輸入命令>₹'"安裝 router:pnpm install vue-router@4
2、 為(wèi)了(le)方便測試,先在 src 目錄下(xi±☆↓€à)創建 views 目錄,并在 views 目錄下(xià→€↕)創建 index.vue 和(hé) about.≠↔₩vue 文(wén)件(jiàn)
index.vue
```
<template>
<div>
<h1>這(zγ™•'hè)是(shì)主頁!</h1>
<button @click="t♥Ω★αo">前往</button>
</div>
</template>
<script setup>
import { router } from &÷'@/router';
function to() {
router.push(&§↓>∏#39;/about')
}
</script>
```
about.vue
```
<template>
<div>
<h1>這≤β(zhè)是(shì)關于頁!</h1>
<button @click=&quoδ<★t;to">前往</button>
</div>
</template>
<script setup>∞®
import { router } from '@/router™™ ®';
function to() {
router.push('/ ♥39;)
}
</script>
```
3、 随後在 src 目錄下(xià)創建目錄 router,并在 β♠router 目錄下(xià)創建 index.ts 文(wé♣←σn)件(jiàn)。
```
import { createRouter, cr≠ ®eateWebHistory, Route↔€<•RecordRaw } from "♥∞ λvue-router";
const routes: Array&l∏✔≈←t;RouteRecordRaw> = [
{
path: "/",
component: () =&₩✔∑≤gt; import("@/vieβε§δws/index.vue")
},
{
path: &qε↕γuot;/about",
component: () > α=> import("@/views/ab↓♦∏∞out.vue")
},
];
export const router = createRout←£er({
history: createWebHistory(),
routes,
});
```
4、 在 `main.ts` 中引入
```
import { createApp } fr♣φΩ£om 'vue'
import './style.cs£↕s'
import App from '©β ;./App.vue'
import { router } from './route<✘r/index'
createApp(App)
.use(router)
.mount('#app')
```
5、 最後修改 `App.vue` 文(wén)件(jiàn)
```
<script setup>
import { RouterView } from 'vue-roε≈♠>uter'
</script>
<template>
<RouterVie→w></RouterView>
</template>
<style scoped>
</style>
```
## 四、引入 element plus
1、 引入依賴
pnpm install element-plus
2、全局引入
在 `main.ts` 中引入
```
import ElementPlus from 'elem÷&§ent-plus'
import 'element-plus/dist/index.css¶☆¶'
createApp(App)
.use(ElementPlus)
.mount('#app')♥β
```
## 五、添加環境變量
1、 在與 src 同級目錄下(xià)✔ ↔分(fēn)别創建`.env.development"®•` 和(hé)`.env.production` 文(wén)件(j©•iàn)
.env.development
```
VITE_USER_NODE_ENV=dev
VITE_PARAM=dev
VITE_BASE_URL="http://localhost>≈∑:8081/v1/api"
```
.env.production
```
VITE_USER_NODE_ENV=prod
VITE_PARAM=prod
VITE_BASE_URL='https://api.example ≈.com/v1/api'
```
需要(yào)注意的(de)是(shì),`VITE_` 前綴是(shì)必↑₽須要(yào)有(yǒu)的(de),否則會δ±(huì)獲取不(bù)到(dào)
2、使用(yòng)
```
import.meta.env.變量
// 例如(rú)
import.meta.env.VITE_♣εΩBASE_URL
```
## 六、引入 axios
1、引入 axios
pnpm install axios
2、封裝統一(yī)請(qǐng)求
在 src 目錄下(xià)新建 utils 目錄,然後在 utils 目錄下±∏λ(xià)創建 `request.ts`
```
import axios, { InternalAxiosRequ♦♣estConfig, AxiosRespons±÷✘δe } from "axios&q>×≠uot;
import { ElMessage } from 'e♦£lement-plus'
// 創建 axios 實例
const request = axiosε✘÷×.create({
baseURL: import.meta.env.VI↑ TE_BASE_URL,
timeout: 10000>™ ,
headers: { "Con •tent-Type": "applicaα≠tion/json;charset=utf-₹ππ≠8" },
});
// 請(qǐng)求攔截器(qì)
request.interceptors.requ♥☆est.use(
(config: InternalAxiosRe±∞₩questConfig) => {
const token = ♦α<window.sessionStorage.getItem('toke✔↓n')
if (token) {
config.headers.Aut★λφhorization = `Bearer ${token★α}`
}
return config
},
(error: any) => {♠→↔
return λβ¥Promise.reject(error)
}
);
// 響應攔截器(qì)
request.interceptors.res★→×ponse.use(
(response: AxiosResponsλ↓e) => {
const data = res♥≥≤ponse.data;
if (data.code === ≈≠ ♥200) {
return response.da•α∞ta;
}
ElMessage.error(dat•≈£a.msg || "系統出錯(c↑¥uò)");
return Promise.reje<©™πct(new Error(data.msg || "Errorσ¥"));
},
(error: any) ♥≥=> {
if (error.responseφσα₹.data) {
ElMes€≠sage.error(error.responα♦€se.data.msg || "系統出錯(cuò)₽♣©✔");
}
return Promise.r"∑≈eject(error.message);
}
);
// 導出 axios 實例
export default request;
```
4、編寫 api 請(qǐng)求
在 src 下(xià)創建 api 目錄,定義一(yī)個(gè) page©δ' 對(duì)象,用(yòng)于接收分(fēn)頁返回來<¥(lái)的(de)數(shù)據
page.ts
```
export interface Page<T>∞∑↑; {
records: Array<T$♣€>,
total: number,
}
```
在 api 下(xià)創建 test 目錄,并創建&€ test.ts 和(hé) types.ts 文(wén)件(jiànλ♣Ω)
test.ts
```
import request from ₹₽π"@/utils/request"
import { AxiosPromis♥αe } from "axios";
import { HotArticleQuery, σ<HotArticleVo } from ♦≤"39;./types'
import { Page } from "../pag↑§e";
// 入參是(shì)HotArticleQuery,返回體(tǐβ♣)是(shì)Page<HotArtiσ∏★cleVo>
export function getArticleApi(queryPara♣♦'ms?: HotArticleQuery) : Axio&φsPromise<Page<HotArticleVσ₩€o>> {
return request({
url: '/article/liλ↓st',
method: 'post',
data: queryParams
})
}
```
types.ts
```
// 請(qǐng)求參數(shù)
export interface HotArticleQuery {
pageSize: number;
pageIndex: number>&©;
searchKey: string;
}
// 返回分(fēn)頁數(shù)據的(de)具體(tǐ)參'×數(shù)
export interface HotArticleVo {
id: number;
title: string;
}
```
調用(yòng)
```
<template>
<div>
<h1>≤ ;這(zhè)是(shì)主頁!</h1>
<el-button @c'πlick="to">前往€←ε</el-button>
<el-butt¶on @click="getArticleL≈πist">獲取</el-button&∏ ×$gt;
</div>
</template>
<script setup>±♣
import { getArticleApi } fromγ©γ≈ '@/api/test/test'Ω←•≥
import { HotArticleQuery, HotArti♥≤✘cleVo } from '@/↕♦¥api/test/types'
import { Page } from 'δ↑∞@/api/page'
import { router } from ¥¥π9;@/router';
import { reactive, ref } from ↑β'vue';
const query = reactive<HotArti₽↕cleQuery>({
pageIndex: 1,
pageSize: 10,
searchKey: '&♣ #39;
})
const articleData = ref<Paαλ¶ge<HotArticleVo>>();
function getArticleList(↕) {
getArticleApi(queryφ♥σ).then(res => {
articleDa ©ta.value = res.data
console.log(articlΩ₽€∏eData.value.records)
console.log↓$∏(articleData.value.total)
})
}
function to() {
router.push('/about'♥β≈)
}
</script>
```
## 七、狀态管理(lǐ) Pinia
1、安裝pnpm install pinia
2、在 main.ts 中引入
```
import { createPinia } '•£from "pinia";
const pinia = createPinia→♠₽∏();
createApp(App)
.use(pinia)
.mount('#app')
```
3、創建 store
在 src 目錄下(xià)創建 storσ®★e 目錄,然後創建一(yī)個(gè) us≥"er.ts 用(yòng)于存放(fàngλ ₹)用(yòng)戶相(xiàng)關數(shù)™ε據
```
import { defineStore ✔Ω} from 'pinia★π9;
// 第一(yī)個(gè)參數(shù)是↕↑(shì)應用(yòng)程序中 store 的(de)唯一(yī) i♥£d
export const useUsersSt<£ore = defineStore('u§• sers', {
// 配置項
state: () =>÷π§ {
// 這(zhè)裡(lǐ)假設有'→ ≥(yǒu)一(yī)些(xiē)參數(shù)
return {
uid: 1,
username: &± #39;admin',
exp: 100
}
}
})
```
4、使用(yòng) store
```
<el-button @click="get&™↕€Ωquot;>測試pinia< σ↔/el-button>
import { useUsersStore } φ≈φfrom '@/store/user↑♦δ&9;
function get() {
const store = useUsersStore(β×♠)
console.log(store)
// 或者
const { uid, username, ↔☆ exp} = useUsersStore()
console.log(uid)
console.log(usernam★Ω¥≥e)
console.log(exp)✔↑•
// 修改
store.exp = 200
// 重置
store.$reset()
console.log(sto↔♦λre)
}
```
5、getter
在 user.ts 中定義一(yī)個("$gè) getters
```
import { defineStore } from ↔♥ 'pinia'
// 第一(yī)個(gè)參數(shù)α ™∑是(shì)應用(yòng)程序中 store 的±$®(de)唯一(yī) id
export const useUsers Store = defineStore('users∞∞39;, {
// 配置項
state: () => {
return {
uid: 1,
user≥γ name: 'admin',
exp: 100
}
},
getters: {
// 無參
addExp: (state) ↓"≠∏=> {
return state.exp + ♣® 150
},
// 帶參
addExpCustom: £δ€(state) => {
return✔<σα (num: number) => £φ₹state.exp + num
}
}
})
```
使用(yòng)
```
console.log(store.ad©γ¶dExp)
console.log(store.addEx♥&£↑pCustom(180))
```
6、actions 屬性
actions 屬性類似于一(yī)個(gè>↔✘↑)方法,我們可(kě)以在裡(lǐ)面進行(xínφ®g)業(yè)務操作(zuò),例如(rú)發送請(qǐng)求等
```
export const useUsersSt'φ<ore = defineStore('users♥γ™Ω9;, {
// 配置項
state: () => {
return {
uid: φ 1,
username: 'ad®×min',
exp: 100
}
},
getters: {
addExp: (st×→αate) => {
return ≤←♣✔state.exp + 150
},
addExpCustom: (sta☆£te) => {
return (nσ★✔©um: number) => state.exp + ₽↑num
}
},
actions: {
showParam(param: stri≤₽™ng) {
console.log(&€≠#39;傳入的(de)參數(shù)為(wèi):' +≤δβ÷ param)
}
}
})
```
使用(yòng)
```
store.showParam('test')
```
微(wēi)信公衆号
業(yè)務咨詢:4✘<σ00-9969-069(24小(xiǎo)↕$時(shí)服務) 028-8605<→≠'2918
售後熱(rè)線:028-86052836
公司地(dì)址:成都(d¶✘♠→ōu)市(shì)武侯區(qū)天益街(jiē)38号理(lǐ€ε≈☆)想中心3棟1810