<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Vue3.2 setup語法糖 [ 單檔案元件的語法糖<script setup>
]
如果你對Vue3語法糖有一定了解,配和我另外一篇一起食用更好哦!Vue3必學技巧-自定義Hooks-讓寫Vue3更暢快
閱讀本來,預設你已經對Vue3.0的composition API有一定了解,但困擾於setup函數內需要繁瑣return相關的變數和函數,那setup的語法糖<script setup>
你將收穫滿滿。語法糖<script setup>
的引入讓你寫Vue3更爽,讓Vue3更豐滿。本文是在官方檔案基礎上寫的,如果有時間,建議上官方檔案上看,本文寫得更為語意化和通俗,希望你能喜歡。
<script setup>
是在單檔案元件 (SFC) 中使用組合式 API 的編譯時語法糖
解決Vue3.0中setup需要繁瑣將宣告的變數、函數以及 import 引入的內容通過return向外暴露,才能在<template/>
使用的問題
<script setup>
中無需return 宣告的變數、函數以及import引入的內容,即可在<template/>
使用
<script setup>
語法糖
<script setup> //import引入的內容 import { getToday } from './utils' // 變數 const msg = 'Hello!' // 函數 function log() { console.log(msg) } </script> //在template中直接使用宣告的變數、函數以及import引入的內容 <template> <div @click="log">{{ msg }}</div> <p>{{getToday()}}</p> </template>
標準元件<script>
需要寫setup函數並繁瑣retrun
<script> //import引入的內容 import { getToday } from './utils' export default{ setup(){ // 變數 const msg = 'Hello!' // 函數 function log() { console.log(msg) } //想在tempate裡面使用需要在setup內return暴露出來 return{ msg, log, getToday } } } </script> <template> <div @click="log">{{ msg }}</div> <p>{{getToday()}}</p> </template>
小結:<script setup>
語法糖裡面的程式碼會被編譯成元件 setup()
函數的內容,不需要通過return暴露 宣告的變數、函數以及import引入的內容,即可在<template/>
使用,並且不需要寫export default{}
<script setup>
語法糖裡面的程式碼會被編譯成元件 setup()
函數的內容。這意味著與普通的 <script>
只在元件被首次引入的時候執行一次不同,<script setup>
中的程式碼會在每次元件範例被建立的時候執行
<script> console.log('script');//多次範例元件,只觸發一次 export default { setup() { console.log('setupFn');//每次範例化元件都觸發和script-setup標籤一樣 } } </script>
(script-setup標籤最終都會編譯成setup()
函數的內容,每次範例化元件,就是範例化一次setup函數。script標籤裡面的setup函數也是一樣每次範例化元件,就是範例化一次setup函數,但是script標籤setup是需要寫在export default{}內的,外的只是首次引入的時候執行一次)
不需要在引入元件後,通過 components:{}
註冊元件,可直接使用
<script setup> import MyComponent from './MyComponent.vue' //components:{MyComponent} 不需要註冊直接使用 </script> <template> <MyComponent /> </template>
在<script setup>
中必須使用 defineProps
和 defineEmits
API 來替代 props 和 emits
defineProps
和 defineEmits
具備完整的型別推斷並且在 <script setup>
中是直接可用的(瀏覽了一下掘金,發現大部分文章demo還是通過import引入這2個api,這點官方檔案寫得很清楚)
接收父元件傳遞的資料(父元件向子元件傳參)
父元件:
<template> <div>父元件</div> <Child :title="msg" /> </template> <script setup> import {ref} from 'vue' import Child from './child.vue' const msg = ref('父的值') //自動返回,在template直接解套使用 </script>
子元件:
<template/>
中可以直接使用父元件傳遞的props (可省略props.)
<script-setup>
需要通過props.xx獲取父元件傳遞過來的props
<template> <div>子元件</div> <div>父元件傳遞的值:{{title}}</div> </template> <script setup> //import {defineProps} from 'vue' 不需要引入 //語法糖必須使用defineProps替代props const props = defineProps({ title: { type: String } }); //script-setup 需要通過props.xx獲取父元件傳遞過來的props console.log(props.title) //父的值 </script>
子元件向父元件傳遞資料(子元件向外暴露資料)
子元件程式碼:
<template> <div>子元件</div> <button @click="toEmits">子元件向外暴露資料</button> </template> <script setup> import {ref} from 'vue' const name = ref('我是子元件') //1、暴露內部資料 const emits = defineEmits(['childFn']); const toEmits = () => { //2、觸發父元件中暴露的childFn方法並攜帶資料 emits('childFn',name) } </script>
父元件程式碼:
<template> <div>父元件</div> <Child @childFn='childFn' /> <p>接收子元件傳遞的資料{{childData}} </p> </template> <script setup> import {ref} from 'vue' import Child from './child.vue' const childData = ref(null) const childFn=(e)=>{ consloe.log('子元件觸發了父元件childFn,並傳遞了引數e') childData=e.value } </script>
使用 <script setup>
的元件,父元件是無法通過ref 或者 $parent
獲取到子元件的ref等響應資料,需要通過defineExpose 主動暴露
子元件程式碼:
<script setup> import { ref } from 'vue' const a = 1 const b = ref(2) //主動暴露元件屬性 defineExpose({ a, b }) </script>
父元件程式碼:
<template> <div>父元件</div> <Child ref='childRef' /> <button @click='getChildData'>通過ref獲取子元件的屬性 </button> </template> <script setup> import {ref} from 'vue' import Child from './child.vue' const childRef= ref() //註冊響應資料 const getChildData =()=>{ //子元件接收暴露出來得值 console.log(childRef.value.a) //1 console.log(childRef.value.b) //2 響應式資料 } </script>
useSlots
和 useAttrs
(少用,由於大部分人是SFC模式開發,在<template/>
通過<slot/>
標籤就可以渲染插槽)
如果需要在script-setup
中使用 slots
和 attrs
需要用useSlots
和 useAttrs
替代
需要引入:import { useSlots ,useAttrs } form 'vue'
在<template/>
中通過 $slots
和 $attrs
來存取更方便(attrs用來獲取父元件中非props的傳遞到子元件的引數/方法,attrs 用來獲取父元件中非props的傳遞到子元件的引數/方法,attrs用來獲取父元件中非props的傳遞到子元件的引數/方法,slots可以獲取父元件中插槽傳遞的虛擬dom物件,在SFC模式應該用處不大,在JSX /TSX使用比較多)
父元件:
<template> <Child msg="非porps傳值子元件用attrs接收" > <!-- 匿名插槽 --> <span >預設插槽</span> <!-- 具名插槽 --> <template #title> <h1>具名插槽</h1> </template> <!-- 作用域插槽 --> <template #footer="{ scope }"> <footer>作用域插槽——姓名:{{ scope.name }},年齡{{ scope.age }}</footer> </template> </Child> </template> <script setup> // 引入子元件 import Child from './child.vue' </script>
子元件:
<template> <!-- 匿名插槽 --> <slot /> <!-- 具名插槽 --> <slot name="title" /> <!-- 作用域插槽 --> <slot name="footer" :scope="state" /> <!-- $attrs 用來獲取父元件中非props的傳遞到子元件的引數 --> <p>{{ attrs.msg == $attrs.msg }}</p> <!--true 沒想到有啥作用... --> <p>{{ slots == $slots }}</p> </template> <script setup> import { useSlots, useAttrs, reactive, toRef } from 'vue' const state = reactive({ name: '張三', age: '18' }) const slots = useSlots() console.log(slots.default()); //獲取到預設插槽的虛擬dom物件 console.log(slots.title()); //獲取到具名title插槽的虛擬dom物件 // console.log(slots.footer()); //報錯 不知道為啥有插槽作用域的無法獲取 //useAttrs() 用來獲取父元件傳遞的過來的屬性資料的(也就是非 props 的屬性值)。 const attrs = useAttrs() </script>
useSlots或許在JSX/TSX下更實用
想使用JSX語法在vite需要下載相關jsx的plugins才能識別jsx
useSlots 可以獲取父元件傳遞過來插槽的虛擬dom物件,可以用來渲染插槽內容
<script lang='jsx'> import { defineComponent, useSlots } from "vue"; export default defineComponent({ setup() { // 獲取插槽資料 const slots = useSlots(); // 渲染元件 return () => ( <div> {slots.default?slots.default():''} {slots.title?slots.title():''} </div> ); }, }); </script>
大部分人是SFC模式開發,在<template/>
通過<slot/>
標籤就可以渲染插槽,這種JSX 的寫法應該是很少人會使用的
setup
裡不能存取 this
,不能再直接存取 this.$router
或 this.$route
。(getCurrentInstance可以替代this但不推薦)
推薦:使用useRoute
函數和useRouter
函數替代this.$route
和 this.$router
<script setup> import { useRouter, useRoute } from 'vue-router' const route = useRoute() const router = useRouter() function pushWithQuery(query) { router.push({ name: 'search', query: { ...route.query, }, }) } <script/>
仍然可以使用路由範例元件的導航守衛
import router from './router' router.beforeEach((to,from,next)=>{ })
也可以使用組合式api的導航守衛onBeforeRouteLeave, onBeforeRouteUpdate
<script setup> import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router' // 與 beforeRouteLeave 相同,無法存取 `this` onBeforeRouteLeave((to, from) => { const answer = window.confirm( 'Do you really want to leave? you have unsaved changes!' ) // 取消導航並停留在同一頁面上 if (!answer) return false }) const userData = ref() // 與 beforeRouteUpdate 相同,無法存取 `this` onBeforeRouteUpdate(async (to, from) => { //僅當 id 更改時才獲取使用者,例如僅 query 或 hash 值已更改 if (to.params.id !== from.params.id) { userData.value = await fetchUser(to.params.id) } }) <script/>
組合式 API 守衛也可以用在任何由 `<router-view>` 渲染的元件中,它們不必像元件內守衛那樣直接用在路由元件上。
小結:setup的語法糖作為Vue3的補充,讓Vue3更加豐滿,讓我們寫Vue3更爽。如果覺得寫得還不錯不吝嗇給點給贊再走吧!
如果你看完後覺得意猶未盡,似乎沒get到Vue3究竟好在哪?請了解下Vue3的自定義Hooks!
Vue3配合自定義Hooks或許才是Vue3的完全體!因為有部分人看完這篇後,還覺得Vue3函數和變數寫在一起不優雅!不妨看下這篇!
以上就是Vue3程式設計流暢技巧使用setup語法糖拒絕寫return的詳細內容,更多關於Vue3程式設計setup語法糖的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45