這篇文章主要介紹“Vue3中如何使用TypeScript”,在日常操作中,相信很多人在Vue3中如何使用TypeScript問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Vue3中如何使用TypeScript”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
創(chuàng)新互聯是一家專注于成都做網站、網站制作、成都外貿網站建設與策劃設計,永仁網站建設哪家好?創(chuàng)新互聯做網站,專注于網站建設十多年,網設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:永仁等地區(qū)。永仁做網站價格咨詢:028-86922220
根據設計,type 字段應該是一個枚舉值,不應該由調用方隨意設置。
下面是 Type 的枚舉聲明,共有 6 個字段。
enum Type { primary = "primary", success = "success", warning = "warning", warn = "warn", // warning alias danger = "danger", info = "info", }
TypeScript 中聲明類型的關鍵字有兩個,interface 和 type,在聲明 key 不確定類型的字段時稍有不同。
使用 type 進行聲明:
type ColorConfig = { [key in Type]: Colors; };
使用 interface 卻只能像下面這樣:
interface ColorConfig { [key: string]: Colors; }
因為 interface 的索引只能是基礎類型,類型別名也不可以。而 type 的索引可以是復合類型。
在 vue3 中,組件的邏輯可以放在 setup 函數里面,但是 setup 中不再有 this,所以 vue2 中的 this.$refs 的用法在 vue3 中無法使用。
新的用法是:
給元素添加 ref 屬性。
在 setup 中聲明與元素 ref 同名的變量。
在 setup 的 return 對象中將 ref 變量作為同名屬性返回。
在 onMounted 生命周期中訪問 ref 變量,既是元素實例。
第一步:
<div class="point point-flicker" ref="point"></div>
第二步:
const point = ref<HTMLDivElement | null>(null);
注意類型要填寫 HTMLDivElement,這樣才能享受類型推斷。
第三步:
return { point };
這一步必不可少,如果返回對象中不包含這個同名屬性,onMounted 中訪問的 ref 對象會是 null。
第四步:
onMounted(() => { if (point?.value) { // logic } });
JavaScript 無法獲取到偽類元素,但是可以換一種思路。偽類樣式引用 css 變量,再通過 js 控制 css 變量來完成間接操作偽類的效果。
比如這是一個偽類:
.point-flicker:after { background-color: var(--afterBg); }
它依賴了 afterBg 變量。
如果需要修改它的內容,只需要使用 js 操作 afterBg 的內容即可。
point.value.style.setProperty("--bg", colorConfig[props.type].bg);
有一種不是很常見的情況,需要組件修改父組件傳遞給自己的 Props。
比如抽屜組件、擬態(tài)框組件等。
在 vue2 中常見的用法是 sync 和 v-model。
vue3 中只推薦使用 v-model:xxx="" 的方式。
比如父組件傳遞:
<ws-log v-model="wsLogVisible" />
子組件:
<template> <div v-model:visible="visible"> ... </div> </template> <script> // ... props: { visible: { type: Boolean, }, }, </script>
watch 變得更加簡單。
import { watch } from "vue"; watch(source, (currentValue, oldValue) => { // logic });
當 source 變化時自動執(zhí)行 watch 第二個參數所傳入的函數。
computed 也變得更加簡單。
import { computed } from "vue" const v = computed(() => { return x });
computed 返回的變量是一個響應式對象。
這是一種開發(fā)組件的技巧。
假設你有一個不確定深度的樹狀結構數據。
{ "label": "root", "children": [ { "label": "a", "children": [ { "label": "a1", "children": [] }, { "label": "a2", "children": [] } ] } ] }
它的類型定義如下:
export interface Menu { id: string; label: string; children: Menu | null; }
你需要實現一種樹狀組件來渲染它們。這時就需要用到這種技巧。
<template> <div>{{ menu.label }}</div> <Menu @select="select" v-for="item in menu.children" :key="item.id" :menu="item" /> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ name: "Menu", props: { menu: { type: Object, }, }, }); </script>
組件的 name 可以在自身中直接使用,而不需要在 component 中聲明。
在 Vuex 中,我設計了一個數據結構用于存儲模塊(業(yè)務概念)不同的狀態(tài)。
type Code = number; export type ModuleState = Map<Code, StateProperty>;
但是我發(fā)現一個問題,當我修改 Map 中某一個 value 中的屬性時,不會觸發(fā) Vuex 的監(jiān)聽。
所以我只好將數據結構修改為對象的形式。
export type ModuleState = { [key in Code]: StateProperty };
ts 中索引不可以使用類型別名,但是可以寫成下面這樣:
type Code = number; export type ModuleState = { [key in Code]: StateProperty };
除此之外,Map 還存在另外一個問題。
當一個 Map 類型的 Proxy 對象作為參數被傳遞時,是無法使用 get、set、clear 等 Map 方法的,但是 TypeScript 會提示這些方法可用。如果使用了這些方法,會得到一個 Uncaught TypeError。
如果使用 Object 則不會產生這個問題。
ws 的異常只能在 onerror 和 onclose 兩個事件中進行處理,try catch 是無法捕獲的。
有些時候,onerror 和 onclose 會連續(xù)執(zhí)行,比如觸發(fā) onerror,導致連接關閉,就會緊接著觸發(fā) onclose。
vue devtools 目前無法支持 Vue3,但是 vue devtools 幾乎是開發(fā)中必不可少的工具,目前可以使用 vue devtools beta 版本,但存在一些 Bug。
用法非常簡單,安裝后重啟瀏覽器就可以。不需要設置 vue.config.devtools = true,在 vue3 中 vue.config 實例不存在 devtools 屬性。
在使用 vite 啟動服務的同時安裝依賴,非常容易碰到一個錯誤。
Error: EBUSY: resource busy or locked, open 'E:\gxt\property-relay-fed\node_modules\esbuild\esbuild.exe'
這個問題的原因是 vite 依賴的編譯工具 esbuild.exe 被占用所導致的,解決方法很簡單,就是停掉 vite,安裝完依賴后再重新啟動 vite。
系統中有一些移動頁面,需要嵌入在 App 中使用。
常見的調試 WebView 的方法有兩種,一種簡單的方式是使用騰訊開源的 vcosnole,另一種麻煩一些的調試方式是使用 Chrome 的 DevTools。
但是 vconsole 并沒有想象中那么好用。
所以我選擇使用 Chrome 調試,chrome://inspect/#devices
但是在調試過程中我發(fā)現 Chrome 調試工具里面竟然運行的是 TS 源碼,TS 的語法直接被認為語法錯誤。(我是使用 Vite 啟動的開發(fā)服務。)
解決方案很簡單,但挺 Low。先使用 vite build 把 TS 代碼編譯成 JS,再使用 vite preview 啟動服務。
websocket 和 Vue3 沒什么關系,但是在這里簡單提一下。
設備管理系統的核心概念是設備,設備會有很多屬性,在硬件上也被稱作數據點。這些屬性會經歷非常長的鏈路傳輸到用戶界面上。整體流程大概是:硬件通過 tcp 協議上傳到接入網關,接入網關處理后再通過 mqtt 協議上傳到物聯網平臺,物聯網平臺再經過規(guī)則引擎處理,通過 webhook restful 的形式發(fā)送到業(yè)務系統,業(yè)務系統再通過 websocket 推送到前端。
雖然數據通過層層編解碼、不同的協議繞了非常遠的距離呈現到用戶面前,但是前端只需要關心 websocket 就足夠了。
在做重連時,需要注意 onerror 和 onclose 連續(xù)執(zhí)行的問題,通常是使用類似防抖的方法來解決。
我的做法是增加一個變量來控制重連次數。
let connecting = false; // 斷開連接后,先觸發(fā) onerror,再觸發(fā) onclose,主要用于防止重復觸發(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); } }; }
系統是設計成 7*24 小時不間斷運行。所以 websocket 很容易受到一些網絡因素或者其它因素的影響發(fā)生斷開,重連是一項非常重要的功能,同時還應該具備重連日志功能。
在用戶的不同環(huán)境中,排查 WebSocket 的連接狀態(tài)很麻煩,添加一個連接日志功能是比較不錯的方案,這樣可以很好的看到不同時間的連接情況。
image.png
需要注意,這些日志是存儲在用戶的瀏覽器內存中的,需要設置上限,到達上限要自動清除早期日志。
websocket 的鑒權是很多人容易忽視的一個點。
我在系統設計中,restful API 的鑒權是通過在 request header 上附帶 Authorization 字段,設置生成的 JWT 來實現的。
websocket 無法設置 header,但是可以設置 query,實現思路類似 restful 的認證設計。
關于 ws 鑒權的過期、續(xù)期、權限等問題,和 restful 保持一致即可。
script setup 至今仍是一個實驗性特性,但它確實非常清爽。
單文件組件的 setup 常規(guī)用法像下面這樣:
<script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ setup () { return {} } }) </script>
使用 script setup 后,代碼變成了下面這樣:
<script setup lang="ts"> </script>
在 sciprt 標簽中的頂層變量、函數都會 return 出去。
在這種模式下,減少了大量代碼,可以提高開發(fā)效率、降低心智負擔。
但這時也存在幾個問題,比如在 script setup 中怎么使用生命周期和 watch/computed 函數?怎么使用組件?怎么獲取 props 和 context?
直接導入組件后,vue 會自動識別,無需使用 component 掛載。
<script setup lang="ts"> import C from "component" </script>
和標準寫法基本無差異。
<script setup lang="ts"> import { watch, computed, onMounted } from "vue" </script>
由于 setup 被提升到 script 標簽上了,自然也就沒辦法接收 props 和 context 這兩個參數。
所以 vue 提供了 defineProps、defineEmit、useContext 函數。
defineProps
defineProps 的用法和 OptionsAPI 中的 props 用法幾乎一致。
<script setup lang="ts"> import { defineProps } from "vue"; interface Props { moduleID: string; } const props = defineProps<Props>(["moduleID"]); console.log(props.moduleID); </script>
defineEmit
defineEmit 的用法和 OptionsAPI 中的 emit 用法也幾乎一致。
<script setup lang="ts"> import { defineEmit } from "vue"; const emit = defineEmit(["select"]); console.log(emit("select")); </script>
emit 的第一個參數是事件名稱,后面支持傳遞不定個數的參數。
useContext
useContext 是一個 hook 函數,返回 context 對象。
const ctx = useContext()
原理相當簡單。增加了一層編譯過程,將 script setup 編譯成標準模式的代碼。
但是實現上有非常多的細節(jié),所以導致至今仍未推出正式版。
這套技術棧帶給我最深的感受還是開發(fā)方式上的變化。
在 Vue2 的開發(fā)中,Options API 在面對業(yè)務邏輯復雜的頁面時非常吃力。當邏輯長達千行時,追蹤一個變量的變化是一件非常頭痛的事情。
但是有了 Composition API 后,這將不再是問題,它帶來了一種全新的開發(fā)方式,雖然有種 React 的感覺,但這相比之前已經非常棒了!
這項目中所有的頁面,我都使用 hooks 的方式開發(fā)。
在設備模塊中,我的 js 代碼是這樣的。
<script lang="ts"> 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>
每個模塊各司其職,各自有自己的內部數據,各個模塊如果需要共享數據,可以通過 Vuex,或者在頂層組件的 setup 中傳遞,比如上面的 reload 函數。
我的目錄結構是這樣的。
到此,關于“Vue3中如何使用TypeScript”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯網站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
當前文章:Vue3中如何使用TypeScript
鏈接URL:http://bm7419.com/article22/iihecc.html
成都網站建設公司_創(chuàng)新互聯,為您提供網站內鏈、靜態(tài)網站、網站設計公司、定制網站、自適應網站、云服務器
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯