vue3+ts實(shí)際開(kāi)發(fā)中該如何優(yōu)雅書(shū)寫(xiě)vue3語(yǔ)法
vue3語(yǔ)法的發(fā)展
- Vue3 在早期版本( 3.0.0-beta.21 之前)中對(duì) composition api 的支持,只能在組件選項(xiàng) setup 函數(shù)中使用。
- 在 3.0.0-beta.21 版本中增加了 <script setup> 的實(shí)驗(yàn)特性。如果你使用了,會(huì)提示你 <script setup> 還處在實(shí)驗(yàn)特性階段。
- 在 3.2.0 版本中移除<script setup> 的實(shí)驗(yàn)狀態(tài),從此,宣告 <script setup> 正式轉(zhuǎn)正使用,成為框架穩(wěn)定的特性之一。
所以我們現(xiàn)在直接就開(kāi)始使用3.2.0之后的寫(xiě)法
優(yōu)勢(shì)
與組件選項(xiàng) setup 函數(shù)對(duì)比, <script setup>
的優(yōu)點(diǎn):
- 更少、更簡(jiǎn)潔的代碼,不需要使用 return {} 暴露變量和方法了,使用組件時(shí)不需要主動(dòng)注冊(cè)了;
- 更好的 Typescript 支持,使用純 Typescript 聲明 props 和拋出事件,不會(huì)再像 option api 里那么蹩腳了;
- 更好的運(yùn)行時(shí)性能;
- 當(dāng)然, <script setup> 也是有自己的缺點(diǎn)的,比如需要學(xué)習(xí)額外的 API。
Composition Api類型約束
<script setup lang="ts"> import { ref, reactive, computed } from 'vue' type User = { name: string age: number } // ref const msg1 = ref('') // 會(huì)默認(rèn)約束成 string 類型,因?yàn)閠s類型推導(dǎo) const msg2 = ref<string>('') // 可以通過(guò)范型約束類型 const user1 = ref<User>({ name: 'tang', age: 18 }) // 范型約束 const user2 = ref({} as User) // 類型斷言 // reactive const obj = reactive({}) const user3 = reactive<User>({ name: 'tang', age: 18 }) const user4 = reactive({} as User) // computed const msg3 = computed(() => msg1.value) const user5 = computed<User>(() => { return { name: 'tang', age: 18 } }) </script>
編譯器宏
編譯器宏(compiler macros) 有:defineProps、defineEmits、withDefaults、defineExpose 等。
編譯器宏只能在 <script setup>
塊中使用,不需要被導(dǎo)入,并且會(huì)在處理 <script setup>
塊時(shí)被一同編譯掉。
編譯器宏必須在 <script setup>
的頂層使用,不可以在 <script setup>
的局部變量中引用
defineProps
在 <script setup>
塊中是沒(méi)有組件配置項(xiàng)的,也就是說(shuō)是沒(méi)有 props 選項(xiàng),需要使用 defineProps 來(lái)聲明 props 相關(guān)信息。defineProps 接收的對(duì)象和組件選項(xiàng) props 的值一樣。
我這邊引用了pug 如果需要安裝一下就可以直接使用 <template lang="pug">
好處可以減少代碼量 層次也清楚
npm install pug
// componentA.vue 組件 <template lang="pug"> div div {{`我的名字是${name},今年${age}`}} div(v-for="item in list",:key="item.name") {{`我的名字是${item.name},今年${item.age}`}} </template> <script setup lang="ts"> interface item { name: string, age: string } const props = defineProps<{ name: string, age: string, list?: item[] // ?非必傳參數(shù) }>() </script>
// home.vue 頁(yè)面 <template lang="pug"> .mainBg componentA(:name="name",:age="age", :list="list") </template> <script lang="ts" setup> import { ref } from 'vue'; import componentA from '@/components/componentA.vue'; let name = ref('') const age = ref('') const list = ref( [ { name: '張三', age: '20' }, { name: '李四', age: 18 }, { name: '王五', age: 25 }, ] ) <style lang="scss"> .mainBg { padding: 10px; } </style>
這時(shí)候是可以看到TS寫(xiě)法里面 name和age是沒(méi)有定義默認(rèn)值
頁(yè)面效果
Vue3 為我們提供了 withDefaults 這個(gè)編譯器宏,給 props 提供默認(rèn)值
// componentA.vue 組件 <template lang="pug"> div div {{`我的名字是${name},今年${age}`}} div(v-for="item in list",:key="item.name") {{`我的名字是${item.name},今年${item.age}`}} </template> <script setup lang="ts"> interface item { name: string, age: string } interface Props { name: string, age: string, list?: item[] } const props = withDefaults(defineProps<Props>(),{ name: "小cc", age: "18", list: ()=> [] }) </script>
這邊給它定義默認(rèn)值之后保存 看頁(yè)面發(fā)現(xiàn)還是沒(méi)有把默認(rèn)值展示出來(lái)
這是因?yàn)槲覀冊(cè)趆ome頁(yè)面給name和age用ref賦值的時(shí)候給了 ‘ ’ 所以他把空當(dāng)成了默認(rèn)值就沒(méi)有展示withDefaults里面給的默認(rèn)值 這時(shí)候我們把name和age寫(xiě)成
let name = ref() const age = ref()
還有一種情況 當(dāng)不給props定義默認(rèn)值的時(shí)候 傳參也是為空時(shí)
defineEmits
一樣的,在 <script setup>
塊中也是沒(méi)有組件配置項(xiàng) emits 的,需要使用 defineEmits 編譯器宏聲明 emits 相關(guān)信息。
// componentA.vue 組件 <template lang="pug"> div div {{`我的名字是${name},今年${age}`}} //- div(v-for="item in list",:key="item.name") {{`我的名字是${item.name},今年${item.age}`}} el-button(type="primary",@click="setName") 向父組件發(fā)送 name el-button(type="primary",@click="setAge") 向父組件發(fā)送 age </template> <script setup lang="ts"> interface item { name: string, age: string } interface Props { name: string, age: string, list?: item[] } const props = withDefaults(defineProps<Props>(),{ name: "小cc", age: "18", list: ()=> [] }) const emits = defineEmits<{ (e: 'changeName', value: string) : void, (e: 'changeAge', value: string) : void, }>() const setName = () => { emits('changeName', '小橙子') } const setAge = () => { emits("changeAge", "28") } </script>
// home.vue <template lang="pug"> .mainBg componentA(:name="name",:age="age", :list="list", @changeName="changeName",@changeAge="changeAge") </template> <script lang="ts" setup> import { ref } from 'vue'; import componentA from '@/components/componentA.vue'; let name = ref('') const age = ref('') const list = ref( [ { name: '張三', age: '20' }, { name: '李四', age: 18 }, { name: '王五', age: 25 }, ] ) const changeName = (val: string) => { name.value = val } const changeAge = (val: string) => { age.value = val } <style lang="scss"> .mainBg { padding: 10px; } </style>
點(diǎn)擊后
defineExpose
在 Vue3 中,默認(rèn)不會(huì)暴露任何在 <script setup>
中聲明的綁定,即不能通過(guò)模板 ref 獲取到組件實(shí)例聲明的綁定。
Vue3 提供了 defineExpose 編譯器宏,可以顯式地暴露需要暴露的組件中聲明的變量和方法。
這個(gè)情況的場(chǎng)景父組件需要直接調(diào)用子組件內(nèi)部的方法或者修改子組件里的值時(shí),需要將方法或值通過(guò)defineExpose暴露才能操作
// componentB.vue <template lang="pug"> div h1 組件B h1 {{msg}} </template> <script setup lang="ts"> import {ref} from 'vue' const msg = ref('今天天氣不怎么好') const changeMsg = (v: string) => { msg.value = v } // 對(duì)外暴露的屬性 需要用ref 調(diào)用子組件方法是需要把方法暴露出去 defineExpose({ msg, changeMsg, }) </script>
<template lang="pug"> .mainBg el-button(type="primary",@click="handleChangeMsg") 組件B componentB(ref="root") </template> <script lang="ts" setup> import { ref } from 'vue'; import componentB from '@/components/componentB.vue'; const root = ref<any>(null) const handleChangeMsg = () => { root.value.changeMsg("果然 下雨了") } </script> <style lang="scss"> .mainBg { padding: 10px; } </style>
如果把defineExpose注釋掉
由于沒(méi)有把這個(gè)方法暴露出來(lái) 導(dǎo)致找不到這個(gè)方法 changeMsg is not a function
總結(jié)
到此這篇關(guān)于vue3+ts實(shí)際開(kāi)發(fā)中該如何優(yōu)雅書(shū)寫(xiě)vue3語(yǔ)法的文章就介紹到這了,更多相關(guān)vue3+ts 書(shū)寫(xiě)vue3語(yǔ)法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue 使用高德地圖添加點(diǎn)標(biāo)記 + 點(diǎn)擊地圖獲取坐標(biāo) + 帶搜索(即地
這篇文章主要介紹了Vue 使用高德地圖添加點(diǎn)標(biāo)記 + 點(diǎn)擊地圖獲取坐標(biāo) + 帶搜索(即地理編碼 + 逆地理編碼) 附完整示例,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-01-01Vite3結(jié)合Svelte3使用@import導(dǎo)入scss樣式
這篇文章主要為大家介紹了Vite3結(jié)合Svelte3使用@import導(dǎo)入scss樣式實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06vue @input和@click的區(qū)別及說(shuō)明
這篇文章主要介紹了vue @input和@click的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue2.0在沒(méi)有dev-server.js下的本地?cái)?shù)據(jù)配置方法
這篇文章主要介紹了vue2.0在沒(méi)有dev-server.js下的本地?cái)?shù)據(jù)配置方法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-02-02Vue3滑動(dòng)到最右驗(yàn)證功能實(shí)現(xiàn)
在登錄頁(yè)面需要啟動(dòng)向右滑塊驗(yàn)證功能,遇到這樣的需求怎么實(shí)現(xiàn)呢,下面小編通過(guò)示例代碼給大家分享Vue3滑動(dòng)到最右驗(yàn)證功能實(shí)現(xiàn),感興趣的朋友一起看看吧2024-06-06VUE 實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板的兩種方法
這篇文章主要介紹了VUE 實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能,本文通過(guò)兩種方法,給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-04-04Vue Render函數(shù)原理及代碼實(shí)例解析
這篇文章主要介紹了Vue Render函數(shù)原理及代碼實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07