Vue3項(xiàng)目中引用TS語法的實(shí)例講解
基礎(chǔ)語法
定義data
//script標(biāo)簽上 **lang="ts"** <script lang="ts"> import { defineComponent, reactive, ref, toRefs } from 'vue'; //定義一個(gè)類型type或者接口interface來約束data type Todo = { ? id: number, ? name: string, ? completed: boolean } export default defineComponent({ ?? ?//使用reactive時(shí),可以用toRefs解構(gòu)導(dǎo)出,在template就可以直接使用了 ?? ?const data = reactive({ ?? ? ?todoList: [] as Todo[] ?? ?}) ?? ?//可以使用ref或者toRefs來定義響應(yīng)式數(shù)據(jù) ?? ?const count = ref(0); ?? ?//使用ref在setup讀取的時(shí)候需要獲取xxx.value,但在template中不需要 ?? ?console.log(count.value) ?? ?return { ?? ? ?...toRefs(data) ?? ?} }) </script>
定義props
import { defineComponent, PropType} from 'vue'; interface UserInfo = { ? id: number, ? name: string, ? age: number } export default defineComponent({ //props需要使用PropType泛型來約束。 ? props: { ? ? userInfo: { ? ? ? type: Object as PropType<UserInfo>, // 泛型類型 ? ? ? required: true ? ? } ? }, })
定義methods
import { defineComponent, reactive, ref, toRefs } from 'vue'; type Todo = { ? id: number, ? name: string, ? completed: boolean } export default defineComponent({ ? const data = reactive({ ? ? todoList: [] as Todo[] ? }) ? // 約束輸入和輸出類型 ? const newTodo = (name: string):Todo ?=> { ? ? return { ? ? ? id: this.items.length + 1, ? ? ? name, ? ? ? completed: false ? ? }; ? } ? const addTodo = (todo: Todo): void => { ? ? data.todoList.push(todo) ? } ? return { ? ? ...toRefs(data), ? ? newTodo, ? ? addTodo ? } })
vue-router
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; import Home from '../views/Home.vue'; //routes的約束類型是RouteRecordRaw const routes: Array< RouteRecordRaw > = [ ? { ? ? path: '/', ? ? name: 'Home', ? ? component: Home, ? }, ? { ? ? path: '/about', ? ? name: 'About', ? ? component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') ? } ]; //createRouter創(chuàng)建router實(shí)例 const router = createRouter({ //router的模式分為 ?? ?//createWebHistory -- history模式 ?? ?//createWebHashHistory -- hash模式 ? history: createWebHistory(process.env.BASE_URL), ? routes }); export default router;
擴(kuò)展路由額外屬性
// 聯(lián)合類型 //在實(shí)際項(xiàng)目開發(fā)中,常常會(huì)遇到這么一個(gè)場(chǎng)景 //某一個(gè)路由是不需要渲染到側(cè)邊欄導(dǎo)航上的 //此時(shí)我們可以給該路由添加一個(gè)hidden屬性來實(shí)現(xiàn)。 //在ts的強(qiáng)類型約束下,添加額外屬性就會(huì)報(bào)錯(cuò),那么我們就需要擴(kuò)展RouteRecordRaw類型。 type RouteConfig = RouteRecordRaw & {hidden?: boolean}; //hidden 是可選屬性 const routes: Array<RouteConfig> = [ ? { ? ? path: '/', ? ? name: 'Home', ? ? component: Home, ? ? hidden: true, ? ? meta: { ? ? ? permission: true, ? ? ? icon: '' ? ? } ? } ];
在setup中使用
//需要導(dǎo)入useRouter創(chuàng)建一個(gè)router實(shí)例。 import { useRouter } from 'vue-router'; import { defineComponent } from 'vue'; export default defineComponent({ ? setup () { ? ? const router = useRouter(); ? ? goRoute(path) { ? ? ? ?router.push({path}) ? ? } ? } })
vuex#####
使用this.$store
import { createStore } from 'vuex'; export type State = { ? count: number } export default createStore({ ? state: { ? ? count: 0 ? } });
- 需要?jiǎng)?chuàng)建一個(gè)聲明文件vuex.d.ts
import {ComponentCustomProperties} from 'vue'; import {Store} from 'vuex'; import {State} from './store' declare module '@vue/runtime-core' { ? ? interface ComponentCustomProperties { ? ? ? ? $store: Store<State> ? ? } }
在setup中使用
- 定義InjecktionKey
import { InjectionKey } from 'vue'; import { createStore, Store } from 'vuex'; export type State = { ? count: number } // 創(chuàng)建一個(gè)injectionKey export const key: InjectionKey<Store<State>> = Symbol('key');
- 在安裝插件時(shí)傳入key
// main.ts import store, { key } from './store'; app.use(store, key);
- 在使用useStore時(shí)傳入
import { useStore } from 'vuex'; import { key } from '@/store'; export default defineComponent({ ? setup () { ? ? const store = useStore(key); ? ? const count = computed(() => store.state.count); ? ? return { ? ? ? count ? ? } ? } })
模塊
- 新增一個(gè)todo模塊。導(dǎo)入的模塊,需要是一個(gè)vuex中的interface Module的對(duì)象,接收兩個(gè)泛型約束
- 第一個(gè)是該模塊類型
import { Module } from 'vuex'; import { State } from '../index.ts'; type Todo = { ? id: number, ? name: string, ? completed: boolean } const initialState = { ? todos: [] as Todo[] }; export type TodoState = typeof initialState; export default { ? namespaced: true, ? state: initialState, ? mutations: { ? ? addTodo (state, payload: Todo) { ? ? ? state.todos.push(payload); ? ? } ? } } as Module<TodoState, State>; //Module<S, R> S 該模塊類型 R根模塊類型
- 第二個(gè)是根模塊類型
// index.ts export type State = { ? count: number, ? todo?: TodoState // 這里必須是可選,不然state會(huì)報(bào)錯(cuò) } export default createStore({ ? state: { ? ? count: 0 ? } ? modules: { ? ? todo ? } });
- 使用:
setup () { ? console.log(store.state.todo?.todos); }
elementPlus
yarn add element-plus
完整引入
import { createApp } from 'vue' import ElementPlus from 'element-plus';import 'element-plus/lib/theme-chalk/index.css';import App from './App.vue'; import 'dayjs/locale/zh-cn' import locale from 'element-plus/lib/locale/lang/zh-cn' const app = createApp(App) app.use(ElementPlus, { size: 'small', zIndex: 3000, locale }) app.mount('#app')
按需加載
- 需要安裝babel-plugin-component插件:
- 安裝依賴包
yarn add babel-plugin-component -D
- 加入配置
// babel.config.js plugins: [ ? ? [ ? ? ? 'component', ? ? ? { ? ? ? ? libraryName: 'element-plus', ? ? ? ? styleLibraryName: 'theme-chalk' ? ? ? } ? ? ] ]
- 創(chuàng)建 element 組件文件
import 'element-plus/lib/theme-chalk/index.css'; import 'dayjs/locale/zh-cn'; import locale from 'element-plus/lib/locale'; import lang from 'element-plus/lib/locale/lang/zh-cn'; import { ? ElAside, ? ElButton, ? ElButtonGroup, } from 'element-plus'; const components: any[] = [ ? ElAside, ? ElButton, ? ElButtonGroup, ]; const plugins:any[] = [ ? ElLoading, ? ElMessage, ? ElMessageBox, ? ElNotification ]; const element = (app: any):any => { ? // 國(guó)際化 ? locale.use(lang); ? // 全局配置 ? app.config.globalProperties.$ELEMENT = { size: 'small' }; ?? ? components.forEach(component => { ? ? app.component(component.name, component); ? }); ? plugins.forEach(plugin => { ? ? app.use(plugin); ? }); }; export default element;
- 引用于項(xiàng)目
// main.ts import element from './plugin/elemment' const app = createApp(App); element(app);
axios
- axios的安裝使用和vue2上沒有什么大的區(qū)別,如果需要做一些擴(kuò)展屬性,還是需要聲明一個(gè)新的類型。
type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : boolean}
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'; import { ElMessage } from 'element-plus'; const instance = axios.create({ ? baseURL: process.env.VUE_APP_API_BASE_URL || '', ? timeout: 120 * 1000, ? withCredentials: true }); // 錯(cuò)誤處理 const err = (error) => { ? if (error.message.includes('timeout')) { ? ? ElMessage({ ? ? ? message: '請(qǐng)求超時(shí),請(qǐng)刷新網(wǎng)頁(yè)重試', ? ? ? type: 'error' ? ? }); ? } ? if (error.response) { ? ? const data = error.response.data; ? ? if (error.response.status === 403) { ? ? ? ElMessage({ ? ? ? ? message: 'Forbidden', ? ? ? ? type: 'error' ? ? ? }); ? ? } ? ? if (error.response.status === 401) { ? ? ? ElMessage({ ? ? ? ? message: 'Unauthorized', ? ? ? ? type: 'error' ? ? ? }); ? ? } ? } ? return Promise.reject(error); }; type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : boolean} // 請(qǐng)求攔截 instance.interceptors.request.use((config: Config) => { ? config.headers['Access-Token'] = localStorage.getItem('token') || ''; ? return config; }, err); // 響應(yīng)攔截 instance.interceptors.response.use((response: AxiosResponse) => { ? const config: Config = response.config; ? const code = Number(response.data.status); ? if (code === 200) { ? ? if (config && config.successNotice) { ? ? ? ElMessage({ ? ? ? ? message: response.data.msg, ? ? ? ? type: 'success' ? ? ? }); ? ? } ? ? return response.data; ? } else { ? ? let errCode = [402, 403]; ? ? if (errCode.includes(response.data.code)) { ? ? ? ElMessage({ ? ? ? ? message: response.data.msg, ? ? ? ? type: 'warning' ? ? ? }); ? ? } ? } }, err); export default instance;
setup script
- 官方提供了一個(gè)實(shí)驗(yàn)性的寫法,直接在script里面寫setup的內(nèi)容,即:setup script。
- 之前我們寫組件是這樣的:
<template> ? <div> ? ? {{count}} ? ? <ImgReview></ImgReview > ? </div> </template>
<script lang="ts"> import { ref, defineComponent } from "vue"; import ImgReview from "./components/ImgReview.vue"; export default defineComponent({ ? components: { ? ? ImgReview, ? }, ? setup() { ? ? const count = ref(0); ? ? return { count }; ? } }); </script>
- 啟用setup script后:在script上加上setup
<template> ? <div> ? ? {{count}} ? ? <ImgReview></ImgReview> ? </div> </template>
<script lang="ts" setup> ?? ?import { ref } from "vue"; ?? ?import ImgReview from "./components/ImgReview.vue"; ?? ?const count = ref(0); </script>
- 是不是看起來簡(jiǎn)潔了很多,組件直接導(dǎo)入就行了,不用注冊(cè)組件,數(shù)據(jù)定義了就可以用。其實(shí)我們可以簡(jiǎn)單的理解為script包括的內(nèi)容就是setup中的,并做了return。
導(dǎo)出方法
const handleClick = (type: string) => { ? console.log(type); }
定義props
- 使用props需要用到defineProps來定義,具體用法跟之前的props寫法類似:
- 基礎(chǔ)用法
import { defineProps } from "vue"; const props = defineProps(['userInfo', 'gameId']);
- 構(gòu)造函數(shù)進(jìn)行檢查 給props定義類型:
const props = defineProps({ ? gameId: Number, ? userInfo: { ? ? ? type: Object, ? ? ? required: true ? } });
- 使用類型注解進(jìn)行檢查
defineProps<{ ? name: string ? phoneNumber: number ? userInfo: object ? tags: string[] }>()
- 可以先定義好類型:
interface UserInfo { ? id: number, ? name: string, ? age: number } defineProps<{ ? name: string ? userInfo: UserInfo }>()
defineEmit
import { defineEmit } from 'vue'; // expects emits options const emit = defineEmit(['kk', 'up']); const handleClick = () => { ??emit('kk', '點(diǎn)了我'); };
<Comp @kk="handleClick"/> <script lang="ts" setup> const handleClick = (data) => { ? console.log(data) } </script>
獲取上下文
- 在標(biāo)準(zhǔn)組件寫法里,setup 函數(shù)默認(rèn)支持兩個(gè)入?yún)ⅲ?nbsp;
- 在setup script 中使用useContext獲取上下文:
import { useContext } from 'vue' const { slots, attrs } = useContext();
- 獲取到的slots,attrs跟setup里面的是一樣的。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于Vue 消除Token過期時(shí)刷新頁(yè)面的重復(fù)提示問題
很多朋友在token過期時(shí)刷新頁(yè)面,頁(yè)面長(zhǎng)時(shí)間未操作,再刷新頁(yè)面時(shí),第一次彈出“token失效,請(qǐng)重新登錄!”提示,針對(duì)這個(gè)問題該怎么處理呢,下面小編給大家?guī)碓蚍治黾敖鉀Q方法,一起看看吧2021-07-07Vue3進(jìn)階主題Composition API使用詳解
這篇文章主要為大家介紹了Vue3進(jìn)階主題Composition API使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04VUE3.2項(xiàng)目使用Echarts5.4詳細(xì)步驟總結(jié)
Vue3.2是一款非常流行的JavaScript框架,它讓在前端領(lǐng)域開發(fā)變得更加的便捷,下面這篇文章主要給大家介紹了關(guān)于VUE3.2項(xiàng)目使用Echarts5.4的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06vue使用監(jiān)聽實(shí)現(xiàn)全選反選功能
最近做的項(xiàng)目用到了全選全不選功能,于是我就自己動(dòng)手寫了一個(gè),基于vue使用監(jiān)聽實(shí)現(xiàn)全選反選功能,具體實(shí)例代碼大家參考下本文2018-07-07