Vue3.x全家桶+vite+TS-構建Vue3基本框架
一、搭建基礎專案
1、vite建立專案
使用 vite 搭建專案
npm init @vitejs/app
or
yarn create @vitejs/app
根據步驟選擇:
- 專案名稱
- 框架(vue,react…)
- js或ts
3、執行專案
cd 專案目錄 npm install npm run dev
2、環境變數設定介紹
vite serve 時是development開發模式, vite build時是production生產模式。
分別建立配置檔案: .env.development 、.env.production
注意: 命名規範 VITE_為字首的變數才會暴露給經過vite
處理的程式碼
.env.development
# .env.development
VITE_APP_TITLE = MY PROJECT
.env.production
# .env.production NODE_ENV = development #base api VITE_APP_BASE_API = 'http://vitetest.com'
讀取環境變數
讀取環境變數使用import.meta.env.xxx,可在 main.js中測試
// base api
console.log(import.meta.env.VITE_APP_BASE_API);
// title
console.log(import.meta.env.VITE_APP_TITLE);
vite配置多環境打包
- 安裝cross-env
- cross-env 通過js在平臺設定不同的環境變數的工具
npm install --save-dev cross-env
- 配置環境
在專案打包的時候,我們通常需要根據環境變數來區分不同的環境,以請求不同的後臺介面
那麼我們在專案的根目錄下建立如下的環境配置檔案,以production為例,在專案根目錄下建立.env.production,並新增環境變數VITE_PROJECT_ENV = 'production',需要注意的是,環境變數必須以VITE開頭
# .env.production
NODE_ENV = development
#base api
VITE_APP_BASE_API = 'http://vitetest.com'
#環境變數
VITE_PROJECT_ENV = 'production'
- 配置打包
修改package.json (根據自己的實際情況增減)
"scripts": {
"serve": "cross-env vite --mode development",
"product": "cross-env vite --mode production",
"build": "cross-env vite build --mode development",
"build:product": "cross-env vite build --mode production"
}
二、配置Router
1、安裝路由
這裡要注意我們安裝的要是4以上的所有采用@next進行安裝
npm i vue-router@next -S
2、配置路由
在 src 下新建 router 資料夾,並在資料夾內建立 index.ts
vue-router 引數
- 建立router例項:createRouter
- router的模式分為:
- createWebHistory -- history模式
- createWebHashHistory -- hash模式 - routes的約束型別是:RouteRecordRaw
import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '../views/Home.vue';
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
});
export default router
擴充套件路由額外屬性
在實際專案開發中,常常會遇到這麼一個場景,某一個路由是不需要渲染到側邊欄導航上的,此時我們可以給該路由新增一個hidden屬性來實現。
在ts的強型別約束下,新增額外屬性就會報錯,那麼我們就需要擴充套件RouteRecordRaw
型別。
// 聯合型別
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
type RouteConfig = RouteRecordRaw & {hidden?: boolean}; //hidden 是可選屬性
import Home from '../views/Home.vue';
const routes: Array< RouteRecordRaw > = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
3、引入
我們在main.ts檔案中引入Vue-Router,如下所示。
import router from './router';
createApp(App).use(router).mount("#app");
最後和vue2一樣在App.vue中寫入掛在渲染的元件
<router-view/>
三、配置Vuex
Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也整合到 Vue 的官方除錯工具 devtools extension (opens new window),提供了諸如零配置的 time-travel 除錯、狀態快照匯入匯出等高階除錯功能。
1、安裝vuex
使用Vuex之前,需要先安裝Vuex外掛,如下所示。
npm install vuex@next --save
2、配置vuex
安裝完成之後,需要先初始化Vuex。首先,建立一個store/index.ts檔案,新增如下程式碼
import { createStore } from 'vuex'
export default createStore({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
封裝一下
不同模組執行不同的業務邏輯。
以使用者模組為例
- 新建user.ts
import REQUEST_DATA from "@/api/requestHandler";
const state = {
userInfo:[]
};
const mutations = {
setStateItem(state:any, data:any) {
state[data.key] = data.value;
}
};
const actions = {
async getUserData({ commit }:any, data?:any):Promise<any> {
try {
const res = await REQUEST_DATA('userInfoUri', data);
if (res.data.code == 200) {
commit("setStateItem", {
key: "reasonList",
value: res.data.data
});
data.cb && data.cb(res.data.data.satisfaction_status)
} else {
//給出錯誤提示toast
return false;
}
} catch (e) {
return false;
}
},
};
export default {
state,
actions,
mutations,
namespaced: true
};
- index.ts中呼叫
import { createStore } from 'vuex'
import user from './modules/user'
const store = createStore({
modules: {
user,
},
})
export default store
3、引入
我們在main.ts檔案中引入Vuex,如下所示。
import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
import store from './store'
createApp(App).use(store).use(router).mount("#app");
4、頁面呼叫
- import { useStore } from 'vuex';
- const store = useStore();
- store中的方法:
方法|介紹
:--|:--
store.state.xxx|訪問 state
store.getters.xxx |訪問 getter
store.xxx |訪問 Store 的函式
store.commit("xxx", payload?) |呼叫 (優化約束,以強化提示)
store.commits.xxx(payload?) |呼叫 commit
store.dispatch("xxx", payload?) |呼叫 (優化約束,以強化提示)
store.dispatchs.xxx(payload?) |呼叫 dispatch
store.subscribe(fn) | 優化約束,以強化提示
store.subscribeAction(fn) | 優化約束,以強化提示
store.mapState({...}) | 對映 state
store.mapStateOfKeys(...) |對映 state
store.mapGetters({...}) |對映 getters
store.mapGettersOfKeys(...) | 對映 getters
store.mapActions({...}) | 對映 actions
store.mapActionsOfKeys(...) | 對映 actions
store.mapMutations({...}) | 對映 mutations
store.mapMutationsOfKeys(...) | 對映 mutations
<template>
<h1>Home Page</h1>
<h2>{{count}}</h2>
<button @click="handleClick">click</button>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { useStore } from 'vuex';
export default defineComponent({
setup () {
const store = useStore();
const count = computed(() => store.state.home.count);
const handleClick = () => {
store.commit('user/add');
};
return {
handleClick,
count
};
}
})
</script>
四、alias起別名
- vite.config.ts
在過去使用vue-cli的時候,我們總是使用@去引入某些檔案,由於Vite沒有提供類似的配置,所以我們需要手動的對其進行相關配置,才能繼續使用@符號去快捷的引入檔案。首先,我們需要修改vite.config.ts的配置。
核心程式碼
resolve: {
alias: [
{
find: '@',
replacement: '/src',
},
{ find: 'views', replacement: '/src/views' },
{ find: 'components', replacement: '/src/components' },
]
}
完成程式碼
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve:{
alias:[
{
find:'@',
replacement:'/src'
},
{
find:'views',
replacement:'/src/views'
},
{
find:'components',
replacement:'/src/components'
},
]
}
})
- tsconfig.json
然後,我們在修改tsconfig.json檔案
核心程式碼
"types": ["vite/client", "jest"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
完成程式碼
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": [
"esnext",
"dom"
],
"types": ["vite/client", "jest"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue"
]
}
五、基礎語法
1、定義data
- script標籤上:lang="ts"
- 定義一個型別type或者介面:interface來約束data
- 定義響應式資料:可以使用ref或者toRefs來
- 使用ref在setup讀取的時候需要獲取xxx.value,但在template中不需要
- 使用reactive時,可以用toRefs解構匯出,在template就可以直接使用了
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from "vue";
type Todo = {
id: number;
name: string;
completed: boolean;
};
export default defineComponent({
setup() {
const data = reactive({
todoList: [] as Todo[],
});
const count = ref(0);
console.log(count.value);
return {
...toRefs(data),
};
},
});
</script>
2、定義props
props需要使用PropType泛型來約束
<script lang="ts">
import { defineComponent, PropType } from "vue";
interface UserInfo {
id: number;
name: string;
age: number;
}
export default defineComponent({
props: {
userInfo: {
type: Object as PropType<UserInfo>, // 泛型型別
required: true,
},
},
});
</script>
3、定義methods
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from "vue";
type Todo = {
id: number;
name: string;
completed: boolean;
};
export default defineComponent({
setup() {
const data = reactive({
todoList: [] as Todo[],
});
// 約束輸入和輸出型別
const newTodo = (name: string): Todo => {
return {
id: 1,
name,
completed: false,
};
};
const addTodo = (todo: Todo): void => {
data.todoList.push(todo);
};
return {
...toRefs(data),
newTodo,
addTodo,
};
},
});
</script>