Vue3中怎麼使用TypeScript
May 13, 2023 pm 11:46 PM如何宣告欄位名為枚舉的型別?
根據(jù)設(shè)計(jì),type 欄位應(yīng)該是一個(gè)枚舉值,不應(yīng)該由呼叫方隨意設(shè)定。
下面是 Type 的枚舉聲明,共有 6 個(gè)欄位。
enum?Type?{????primary?=?"primary",????success?=?"success",????warning?=?"warning",????warn?=?"warn",?//?warning?alias????danger?=?"danger",????info?=?"info",??}
TypeScript 中聲明類型的關(guān)鍵字有兩個(gè),interface 和 type,在聲明 key 不確定類型的欄位時(shí)稍有不同。
使用 type 進(jìn)行宣告:
type?ColorConfig?=?{????[key?in?Type]:?Colors;??};
使用 interface 卻只能像下面這樣:
interface?ColorConfig?{????[key:?string]:?Colors;??}
因?yàn)?interface 的索引只能是基礎(chǔ)類型,類型別名也不可以。而 type 的索引可以是複合型別。
Vue 3 如何取得元素實(shí)例?
在 vue3 中,元件的邏輯可以放在 setup 函數(shù)裡面,但是 setup 中不再有 this,所以 vue2 中的 this.$refs 的用法在 vue3 中無(wú)法使用。
新的用法是:
為元素新增 ref 屬性。
在 setup 中宣告與元素 ref 同名的變數(shù)。
在 setup 的 return 物件中將 ref 變數(shù)作為同名屬性傳回。
在 onMounted 生命週期中存取 ref 變量,既是元素實(shí)例。
第一步:
<div></div>
第二步:
const?point?=?ref<htmldivelement>(null);</htmldivelement>
注意類型要填入 HTMLDivElement,這樣才能享受類型推論。
第三步:
return?{?point?};
這一步必不可少,如果傳回物件中不包含這個(gè)同名屬性,onMounted 中存取的 ref 物件會(huì)是 null。
第四步:
onMounted(()?=>?{????if?(point?.value)?{??????//?logic????}??});
如何操作偽類?
JavaScript 無(wú)法取得到偽類元素,但是可以換個(gè)想法。偽類樣式引用 css 變量,再透過(guò) js 控制 css 變數(shù)來(lái)完成間接操作偽類的效果。
例如這是一個(gè)偽類別:
.point-flicker:after?{????background-color:?var(--afterBg);??}
它依賴了 afterBg 變數(shù)。
如果需要修改它的內(nèi)容,只需要使用 js 操作 afterBg 的內(nèi)容。
point.value.style.setProperty("--bg",?colorConfig[props.type].bg);
API 的變更
Vue3 中元件如何修改自身的 props?
有一種不是很常見的情況,需要元件修改父元件傳遞給自己的 Props。
例如抽屜組件、擬態(tài)框組件等。
在 vue2 中常見的用法是 sync 和 v-model。
vue3 中只建議使用 v-model:xxx="" 的方式。
例如父元件傳遞:
<ws-log></ws-log>
子元件:
<template>??????<div>??????...?????</div>??</template>??<script> // ... props: { visible: { type: Boolean, }, }, </script>
Vue3 中 watch 用法的變化
watch 變得更簡(jiǎn)單。
import?{?watch?}?from?"vue";??watch(source,?(currentValue,?oldValue)?=>?{??????//?logic??});
當(dāng) source 變更時(shí)自動(dòng)執(zhí)行 watch 第二個(gè)參數(shù)所傳入的函數(shù)。
Vue3 中 computed 用法的變化
computed 也變得更簡(jiǎn)單。
import?{?computed?}?from?"vue"??const?v?=?computed(()?=>?{??????return?x??});
computed 傳回的變數(shù)是一個(gè)響應(yīng)式物件。
Vue3 中元件循環(huán)本身的技巧
這是一種開發(fā)元件的技巧。
假設(shè)你有一個(gè)不確定深度的樹狀結(jié)構(gòu)資料。
{????"label":?"root",????"children":?[??????{????????"label":?"a",????????"children":?[??????????{????????????"label":?"a1",????????????"children":?[]??????????},??????????{????????????"label":?"a2",????????????"children":?[]??????????}????????]??????}????]??}
它的類型定義如下:
export?interface?Menu?{????id:?string;????label:?string;????children:?Menu?|?null;??}
你需要實(shí)作一個(gè)樹狀元件來(lái)渲染它們。這時(shí)就需要用到這種技巧。
<template>??????<div>{{?menu.label?}}</div>??????<menu></menu>??</template>??<script> import { defineComponent } from "vue"; export default defineComponent({ name: "Menu", props: { menu: { type: Object, }, }, }); </script>
元件的 name 可以在自身中直接使用,而不需要在 component 中宣告。
一些坑
Vuex:慎用 Map
在 Vuex 中,我設(shè)計(jì)了一個(gè)資料結(jié)構(gòu)來(lái)儲(chǔ)存模組(商業(yè)概念)不同的狀態(tài)。
type?Code?=?number;??export?type?ModuleState?=?Map<code>;</code>
但我發(fā)現(xiàn)一個(gè)問(wèn)題,當(dāng)我修改 Map 中某一個(gè) value 中的屬性時(shí),不會(huì)觸發(fā) Vuex 的監(jiān)聽。
所以我只好將資料結(jié)構(gòu)修改為物件的形式。
export?type?ModuleState?=?{?[key?in?Code]:?StateProperty?};
ts 中索引不可以使用類型別名,但是可以寫成下面這樣:
type?Code?=?number;??export?type?ModuleState?=?{?[key?in?Code]:?StateProperty?};
除此之外,Map 還存在另一個(gè)問(wèn)題。
當(dāng)一個(gè) Map 類型的 Proxy 物件被傳遞為參數(shù)時(shí),是無(wú)法使用 get、set、clear 等 Map 方法的,但是 TypeScript 會(huì)提示這些方法可用。如果使用了這些方法,會(huì)得到一個(gè) Uncaught TypeError。
如果使用 Object 就不會(huì)產(chǎn)生這個(gè)問(wèn)題。
WebSocket 發(fā)生異常無(wú)法被 try catch 監(jiān)聽
ws 的異常只能在 onerror 和 onclose 兩個(gè)事件中進(jìn)行處理,try catch 是無(wú)法捕獲的。
有些時(shí)候,onerror 和 onclose 會(huì)連續(xù)執(zhí)行,例如觸發(fā) onerror,導(dǎo)致連線關(guān)閉,就會(huì)緊接著觸發(fā) onclose。
Vue Devtools
vue devtools 目前無(wú)法支援 Vue3,但 vue devtools 幾乎是開發(fā)中必不可少的工具,目前可以使用 vue devtools beta 版本,但存在一些 Bug。
用法非常簡(jiǎn)單,安裝後重新啟動(dòng)瀏覽器就可以。不需要設(shè)定 vue.config.devtools = true,在 vue3 中 vue.config 實(shí)例不存在 devtools 屬性。
ESbuild 安裝依賴
在使用 vite 啟動(dòng)服務(wù)的同時(shí)安裝依賴,非常容易碰到一個(gè)錯(cuò)誤。
Error:?EBUSY:?resource?busy?or?locked,?open?'E:\gxt\property-relay-fed\node_modules\esbuild\esbuild.exe'
這個(gè)問(wèn)題的原因是 vite 依賴的編譯工具 esbuild.exe 被佔(zhàn)用所導(dǎo)致的,解決方法很簡(jiǎn)單,就是停掉 vite,安裝完依賴後再重新啟動(dòng) vite。
Vite 在 Chrome 中偵錯(cuò)的問(wèn)題
系統(tǒng)中有一些行動(dòng)頁(yè)面,需要嵌入在 App 中使用。
常見的調(diào)試 WebView 的方法有兩種,一種簡(jiǎn)單的方式是使用騰訊開源的 vcosnole,另一種麻煩一些的調(diào)試方式是使用 Chrome 的 DevTools。
但是 vconsole 并沒(méi)有想象中那么好用。
所以我選擇使用 Chrome 調(diào)試,chrome://inspect/#devices
但是在調(diào)試過(guò)程中我發(fā)現(xiàn) Chrome 調(diào)試工具里面竟然運(yùn)行的是 TS 源碼,TS 的語(yǔ)法直接被認(rèn)為語(yǔ)法錯(cuò)誤。(我是使用 Vite 啟動(dòng)的開發(fā)服務(wù)。)
解決方案很簡(jiǎn)單,但挺 Low。先使用 vite build 把 TS 代碼編譯成 JS,再使用 vite preview 啟動(dòng)服務(wù)。
WebSocket
websocket 和 Vue3 沒(méi)什么關(guān)系,但是在這里簡(jiǎn)單提一下。
設(shè)備管理系統(tǒng)的核心概念是設(shè)備,設(shè)備會(huì)有很多屬性,在硬件上也被稱作數(shù)據(jù)點(diǎn)。這些屬性會(huì)經(jīng)歷非常長(zhǎng)的鏈路傳輸?shù)接脩艚缑嫔稀Uw流程大概是:硬件通過(guò) tcp 協(xié)議上傳到接入網(wǎng)關(guān),接入網(wǎng)關(guān)處理后再通過(guò) mqtt 協(xié)議上傳到物聯(lián)網(wǎng)平臺(tái),物聯(lián)網(wǎng)平臺(tái)再經(jīng)過(guò)規(guī)則引擎處理,通過(guò) webhook restful 的形式發(fā)送到業(yè)務(wù)系統(tǒng),業(yè)務(wù)系統(tǒng)再通過(guò) websocket 推送到前端。
雖然數(shù)據(jù)通過(guò)層層編解碼、不同的協(xié)議繞了非常遠(yuǎn)的距離呈現(xiàn)到用戶面前,但是前端只需要關(guān)心 websocket 就足夠了。
WebSocket 重連
在做重連時(shí),需要注意 onerror 和 onclose 連續(xù)執(zhí)行的問(wèn)題,通常是使用類似防抖的方法來(lái)解決。
我的做法是增加一個(gè)變量來(lái)控制重連次數(shù)。
let connecting = false; // 斷開連接后,先觸發(fā) onerror,再觸發(fā) onclose,主要用于防止重復(fù)觸發(fā)
conn();???function?conn()?{?????connecting?=?false;?????if?(ctx.state.stateWS.instance?&&?ctx.state.stateWS.instance.close)?{???????ctx.state.stateWS.instance.close();?????}?????const?url?=?ctx.state.stateWS.url?+?"?Authorization="?+?getAuthtication();?????ctx.state.stateWS.instance?=?new?WebSocket(url);?????ctx.state.stateWS.instance.onopen?=?()?=>?{???????ctx.commit(ActionType.SUCCESS);?????};?????ctx.state.stateWS.instance.onclose?=?()?=>?{???????if?(connecting)?return;???????ctx.commit(ActionType.CLOSE);???????setTimeout(()?=>?{?????????conn();???????},?10?*?1000);???????connecting?=?true;?????};????ctx.state.stateWS.instance.onerror?=?()?=>?{???????if?(connecting)?return;???????ctx.commit(ActionType.ERROR);???????setTimeout(()?=>?{?????????conn();???????},?10?*?1000);???????connecting?=?true;?????};?????ctx.state.stateWS.instance.onmessage?=?function?(???????this:?WebSocket,???????ev:?MessageEvent?????)?{???????//?logic???????}?catch?(e)?{?????????console.log("e:",?e);???????}?????};???}
WebSocket 連接活動(dòng)日志
系統(tǒng)是設(shè)計(jì)成 7*24 小時(shí)不間斷運(yùn)行。所以 websocket 很容易受到一些網(wǎng)絡(luò)因素或者其它因素的影響發(fā)生斷開,重連是一項(xiàng)非常重要的功能,同時(shí)還應(yīng)該具備重連日志功能。
在用戶的不同環(huán)境中,排查 WebSocket 的連接狀態(tài)很麻煩,添加一個(gè)連接日志功能是比較不錯(cuò)的方案,這樣可以很好的看到不同時(shí)間的連接情況。
image.png
需要注意,這些日志是存儲(chǔ)在用戶的瀏覽器內(nèi)存中的,需要設(shè)置上限,到達(dá)上限要自動(dòng)清除早期日志。
WebSocket 鑒權(quán)
websocket 的鑒權(quán)是很多人容易忽視的一個(gè)點(diǎn)。
我在系統(tǒng)設(shè)計(jì)中,restful API 的鑒權(quán)是通過(guò)在 request header 上附帶 Authorization 字段,設(shè)置生成的 JWT 來(lái)實(shí)現(xiàn)的。
websocket 無(wú)法設(shè)置 header,但是可以設(shè)置 query,實(shí)現(xiàn)思路類似 restful 的認(rèn)證設(shè)計(jì)。
關(guān)于 ws 鑒權(quán)的過(guò)期、續(xù)期、權(quán)限等問(wèn)題,和 restful 保持一致即可。
script setup:更加清爽的 API
script setup 至今仍是一個(gè)實(shí)驗(yàn)性特性,但它確實(shí)非常清爽。
單文件組件的 setup 常規(guī)用法像下面這樣:
<script> import { defineComponent } from 'vue' export default defineComponent({ setup () { return {} } }) </script>
使用 script setup 后,代碼變成了下面這樣:
<script> </script>
在 sciprt 標(biāo)簽中的頂層變量、函數(shù)都會(huì) return 出去。
在這種模式下,減少了大量代碼,可以提高開發(fā)效率、降低心智負(fù)擔(dān)。
但這時(shí)也存在幾個(gè)問(wèn)題,比如在 script setup 中怎么使用生命周期和 watch/computed 函數(shù)?怎么使用組件?怎么獲取 props 和 context?
使用組件
直接導(dǎo)入組件后,vue 會(huì)自動(dòng)識(shí)別,無(wú)需使用 component 掛載。
<script> import C from "component" </script>
使用生命周期和監(jiān)聽計(jì)算函數(shù)
和標(biāo)準(zhǔn)寫法基本無(wú)差異。
<script> import { watch, computed, onMounted } from "vue" </script>
使用 props 和 context
由于 setup 被提升到 script 標(biāo)簽上了,自然也就沒(méi)辦法接收 props 和 context 這兩個(gè)參數(shù)。
所以 vue 提供了 defineProps、defineEmit、useContext 函數(shù)。
defineProps
defineProps 的用法和 OptionsAPI 中的 props 用法幾乎一致。
<script> import { defineProps } from "vue"; interface Props { moduleID: string; } const props = defineProps<Props>(["moduleID"]); console.log(props.moduleID); </script>
defineEmit
defineEmit 的用法和 OptionsAPI 中的 emit 用法也幾乎一致。
<script> import { defineEmit } from "vue"; const emit = defineEmit(["select"]); console.log(emit("select")); </script>
emit 的第一個(gè)參數(shù)是事件名稱,后面支持傳遞不定個(gè)數(shù)的參數(shù)。
useContext
useContext 是一個(gè) hook 函數(shù),返回 context 對(duì)象。
const?ctx?=?useContext()
原理
原理相當(dāng)簡(jiǎn)單。增加了一層編譯過(guò)程,將 script setup 編譯成標(biāo)準(zhǔn)模式的代碼。
但是實(shí)現(xiàn)上有非常多的細(xì)節(jié),所以導(dǎo)致至今仍未推出正式版。
Vue3 Composition 所帶來(lái)的模塊化開發(fā)方式
這套技術(shù)棧帶給我最深的感受還是開發(fā)方式上的變化。
在 Vue2 的開發(fā)中,Options API 在面對(duì)業(yè)務(wù)邏輯復(fù)雜的頁(yè)面時(shí)非常吃力。當(dāng)邏輯長(zhǎng)達(dá)千行時(shí),追蹤一個(gè)變量的變化是一件非常頭痛的事情。
但是有了 Composition API 后,這將不再是問(wèn)題,它帶來(lái)了一種全新的開發(fā)方式,雖然有種 React 的感覺,但這相比之前已經(jīng)非常棒了!
這項(xiàng)目中所有的頁(yè)面,我都使用 hooks 的方式開發(fā)。
在設(shè)備模塊中,我的 js 代碼是這樣的。
<script> import { defineComponent, toRefs } from "vue"; import { useDeviceCreate } from "./create"; import { useDeviceQuery } from "./query"; import { useDeviceDelete } from "./delete"; import { useUnbind } from "./unbind"; import { useBind } from "./bind"; import { useDeviceEdit } from "./edit"; import { useState } from "./state"; import { useAssign } from "./assign"; export default defineComponent({ setup() { const queryObj = useDeviceQuery(); const { query, devices } = queryObj; const reload = query; return { ...toRefs(useDeviceCreate(reload)), ...toRefs(queryObj), ...toRefs(useDeviceDelete(reload)), ...toRefs(useUnbind(reload)), ...toRefs(useBind(reload)), ...toRefs(useDeviceEdit(reload)), ...toRefs(useState(devices)), ...toRefs(useAssign()), }; }, }); </script>
每個(gè)模塊各司其職,各自有自己的內(nèi)部數(shù)據(jù),各個(gè)模塊如果需要共享數(shù)據(jù),可以通過(guò) Vuex,或者在頂層組件的 setup 中傳遞,比如上面的 reload 函數(shù)。
我的目錄結(jié)構(gòu)是這樣的。
以上是Vue3中怎麼使用TypeScript的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁(yè)開發(fā)工具

SublimeText3 Mac版
神級(jí)程式碼編輯軟體(SublimeText3)

想要實(shí)現(xiàn)頁(yè)面的局部刷新,我們只需要實(shí)現(xiàn)局部元件(dom)的重新渲染。在Vue中,想要實(shí)現(xiàn)這效果最簡(jiǎn)單的方式方法就是使用v-if指令。在Vue2中我們除了使用v-if指令讓局部dom的重新渲染,也可以新建一個(gè)空白元件,需要刷新局部頁(yè)面時(shí)跳轉(zhuǎn)至這個(gè)空白元件頁(yè)面,然後在空白元件內(nèi)的beforeRouteEnter守衛(wèi)中又跳轉(zhuǎn)回原來(lái)的頁(yè)面。如下圖所示,如何在Vue3.X中實(shí)現(xiàn)點(diǎn)擊刷新按鈕實(shí)現(xiàn)紅框範(fàn)圍內(nèi)的dom重新加載,並展示對(duì)應(yīng)的加載狀態(tài)。由於Vue3.X中scriptsetup語(yǔ)法中組件內(nèi)守衛(wèi)只有o

最終效果安裝VueCropper組件yarnaddvue-cropper@next上面的安裝值針對(duì)Vue3的,如果時(shí)Vue2或想使用其他的方式引用,請(qǐng)?jiān)L問(wèn)它的npm官方地址:官方教程。在元件中引用使用時(shí)也很簡(jiǎn)單,只需要引入對(duì)應(yīng)的元件和它的樣式文件,我這裡沒(méi)有在全域引用,只在我的元件檔案中引入import{userInfoByRequest}from'../js/api' import{VueCropper}from'vue-cropper&

vue3+ts+axios+pinia實(shí)作無(wú)感刷新1.先在專案中下載aiXos和pinianpmipinia--savenpminstallaxios--save2.封裝axios請(qǐng)求-----下載js-cookienpmiJS-cookie-s//引入aixosimporttype{AxiosRequestConfigig ,AxiosResponse}from"axios";importaxiosfrom'axios';import{ElMess

如何使用MySQL在TypeScript中實(shí)作資料型別轉(zhuǎn)換功能引言:在開發(fā)Web應(yīng)用程式時(shí),資料型別轉(zhuǎn)換是一個(gè)非常常見的需求。在處理資料庫(kù)中儲(chǔ)存的資料時(shí),特別是使用MySQL作為後端資料庫(kù)時(shí),我們經(jīng)常需要將查詢結(jié)果中的資料按照我們所需的類型進(jìn)行轉(zhuǎn)換。本文將介紹如何在TypeScript中利用MySQL實(shí)作資料類型轉(zhuǎn)換的功能,並提供程式碼範(fàn)例。一、準(zhǔn)備工作:在開

使用Vue建構(gòu)自訂元素WebComponents是一組web原生API的統(tǒng)稱,允許開發(fā)者建立可重複使用的自訂元素(customelements)。自訂元素的主要好處是,它們可以在使用任何框架,甚至在不使用框架的場(chǎng)景下使用。當(dāng)你面向的最終用戶可能使用了不同的前端技術(shù)棧,或者當(dāng)你希望將最終的應(yīng)用與它使用的組件實(shí)現(xiàn)細(xì)節(jié)解耦時(shí),它們會(huì)是理想的選擇。 Vue和WebComponents是互補(bǔ)的技術(shù),Vue為使用和創(chuàng)建自訂元素提供了出色的支援。你可以將自訂元素整合到現(xiàn)有的Vue應(yīng)用中,或使用Vue來(lái)構(gòu)

如何使用Redis和TypeScript開發(fā)高效能運(yùn)算功能概述:Redis是一個(gè)開源的記憶體資料結(jié)構(gòu)儲(chǔ)存系統(tǒng),具有高效能和可擴(kuò)展性的特性。 TypeScript是JavaScript的超集,提供了型別系統(tǒng)和更好的開發(fā)工具支援。結(jié)合Redis和TypeScript,我們可以開發(fā)出高效的運(yùn)算功能來(lái)處理大數(shù)據(jù)集,並充分利用Redis的記憶體儲(chǔ)存和運(yùn)算能力。本文將介紹如何

函數(shù)定義createApp函數(shù)定義在檔案packages/runtime-dom/src/index.ts中exportconstcreateApp=((...args)=>{constapp=ensureRenderer().createApp(...args)if(__DEV__){injectNativeTagCheck (app)injectCompilerOptionsCheck(app)}const{mount}=appapp.mount=(containerOrSelector

vue3的生命週期:1、beforeCreate;2、created;3、beforeMount;4、mounted;5、beforeUpdate;6、updated;7、beforeDestroy;8、destroyed;9、activated;10、deactivated;11、errorCaptured;12 、getDerivedStateFromProps 等等
