vue3+ts實際開發(fā)中該如何優(yōu)雅書寫vue3語法
vue3語法的發(fā)展
- Vue3 在早期版本( 3.0.0-beta.21 之前)中對 composition api 的支持,只能在組件選項 setup 函數(shù)中使用。
- 在 3.0.0-beta.21 版本中增加了 <script setup> 的實驗特性。如果你使用了,會提示你 <script setup> 還處在實驗特性階段。
- 在 3.2.0 版本中移除<script setup> 的實驗狀態(tài),從此,宣告 <script setup> 正式轉正使用,成為框架穩(wěn)定的特性之一。
所以我們現(xiàn)在直接就開始使用3.2.0之后的寫法
優(yōu)勢
與組件選項 setup 函數(shù)對比, <script setup>
的優(yōu)點:
- 更少、更簡潔的代碼,不需要使用 return {} 暴露變量和方法了,使用組件時不需要主動注冊了;
- 更好的 Typescript 支持,使用純 Typescript 聲明 props 和拋出事件,不會再像 option api 里那么蹩腳了;
- 更好的運行時性能;
- 當然, <script setup> 也是有自己的缺點的,比如需要學習額外的 API。
Composition Api類型約束
<script setup lang="ts"> import { ref, reactive, computed } from 'vue' type User = { name: string age: number } // ref const msg1 = ref('') // 會默認約束成 string 類型,因為ts類型推導 const msg2 = ref<string>('') // 可以通過范型約束類型 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>
塊中使用,不需要被導入,并且會在處理 <script setup>
塊時被一同編譯掉。
編譯器宏必須在 <script setup>
的頂層使用,不可以在 <script setup>
的局部變量中引用
defineProps
在 <script setup>
塊中是沒有組件配置項的,也就是說是沒有 props 選項,需要使用 defineProps 來聲明 props 相關信息。defineProps 接收的對象和組件選項 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 頁面 <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>
這時候是可以看到TS寫法里面 name和age是沒有定義默認值
頁面效果
Vue3 為我們提供了 withDefaults 這個編譯器宏,給 props 提供默認值
// 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>
這邊給它定義默認值之后保存 看頁面發(fā)現(xiàn)還是沒有把默認值展示出來
這是因為我們在home頁面給name和age用ref賦值的時候給了 ‘ ’ 所以他把空當成了默認值就沒有展示withDefaults里面給的默認值 這時候我們把name和age寫成
let name = ref() const age = ref()
還有一種情況 當不給props定義默認值的時候 傳參也是為空時
defineEmits
一樣的,在 <script setup>
塊中也是沒有組件配置項 emits 的,需要使用 defineEmits 編譯器宏聲明 emits 相關信息。
// 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>
點擊后
defineExpose
在 Vue3 中,默認不會暴露任何在 <script setup>
中聲明的綁定,即不能通過模板 ref 獲取到組件實例聲明的綁定。
Vue3 提供了 defineExpose 編譯器宏,可以顯式地暴露需要暴露的組件中聲明的變量和方法。
這個情況的場景父組件需要直接調用子組件內部的方法或者修改子組件里的值時,需要將方法或值通過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 } // 對外暴露的屬性 需要用ref 調用子組件方法是需要把方法暴露出去 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注釋掉
由于沒有把這個方法暴露出來 導致找不到這個方法 changeMsg is not a function
總結
到此這篇關于vue3+ts實際開發(fā)中該如何優(yōu)雅書寫vue3語法的文章就介紹到這了,更多相關vue3+ts 書寫vue3語法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue 使用高德地圖添加點標記 + 點擊地圖獲取坐標 + 帶搜索(即地
這篇文章主要介紹了Vue 使用高德地圖添加點標記 + 點擊地圖獲取坐標 + 帶搜索(即地理編碼 + 逆地理編碼) 附完整示例,本文結合示例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧2024-01-01Vite3結合Svelte3使用@import導入scss樣式
這篇文章主要為大家介紹了Vite3結合Svelte3使用@import導入scss樣式實現(xiàn)實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06vue2.0在沒有dev-server.js下的本地數(shù)據(jù)配置方法
這篇文章主要介紹了vue2.0在沒有dev-server.js下的本地數(shù)據(jù)配置方法的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-02-02