隨著Vue 3.2的釋出,一個新的組合工具提供給我們,叫做 expose
。(學習視訊分享:)
你是否曾經建立過一個需要向模板提供一些方法和屬性的元件,但又希望這些方法對元件是私有的,不能被父類別呼叫?
如果你在開發一個開源的元件或庫,你有可能想保持一些內部方法的私有性。在Vue 3.2之前,這並不容易實現,因為所有在選項API中宣告的方法或資料等都是公開的,所以模板可以存取它。
組合API也是如此。我們從setup
方法中返回的所有東西都可以被父類別直接存取。
讓我們看一個實際的例子。想象一下,我們有一個元件,它建立了一個計數器,每一秒都會更新這個計數器。
** MyCounter.vue**
<template> <p>Counter: {{ counter }}</p> <button @click="reset">Reset</button> <button @click="terminate">☠️</button> </template> <script> import { ref } from 'vue' export default { setup () { const counter = ref(0) const interval = setInterval(() => { counter.value++ }, 1000) const reset = () => { counter.value = 0 } const terminate = () => { clearInterval(interval) } return { counter, reset, terminate } } } </script>
從組合的角度來看,我希望父級元件能夠在需要時直接呼叫reset
方法--但我希望保持terminate
函數和 counter
的參照只對元件可用。
如果我們把這個元件範例化到一個父類別中,例如 App.vue,並給它附加一個 ref 參照,我們可以很容易地讓父類別呼叫 reset
方法,因為當我們從 setup
中返回它時,它已經和 terminate
一起被暴露了。
App.vue
<template> <MyCounter ref="counter" /> <button @click="reset">Reset from parent</button> <button @click="terminate">Terminate from parent</button> </template> <script> import MyCounter from '@/components/MyCounter.vue' export default { name: 'App', components: { MyCounter }, methods: { reset () { this.$refs.counter.reset() }, terminate () { this.$refs.counter.terminate() } } } </script>
如果現在執行這個,並單擊重置或終止按鈕,兩者都可以工作。
讓我們明確說明我們要向父類別暴露(expose
)的內容,以便只有 reset
函數可用。
** MyCounter.vue**
<script> import { ref } from 'vue' export default { setup (props, context) { const counter = ref(null) const interval = setInterval(() => { counter.value++ }, 1000) const reset = () => { counter.value = 0 } const terminate = () => { console.log(interval) clearInterval(interval) } context.expose({ reset }) return { counter, reset, terminate } } } </script>
這裡,我們在setup
函數中加入了 props
和 context
引數。我們需要有可用的上下文,因為這是 expose
函數的位置。我們也可以像這樣使用重構: { expose }
。
接下來,我們使用 context.expose
來宣告一個我們想要向範例化這個元件的父類別公開的元素物件;在這個例子中,我們只打算讓 reset
功能可用。
如果我們再次執行這個例子,並點選 "Terminate from parent" 按鈕,我們會得到一個錯誤。
Uncaught TypeError: this.$refs.counter.terminate is not a function
terminate
功能不再可用,我們的私有API現在也無法存取了。
上面我們在 composition API
使用 exponse
,但在options API中也可以使用這個方法。我們可以把它改寫成如下。
// MyCounter.vue export default { created () { ... }, data: () => ({ counter: null }), methods: { reset () { ... }, terminate () { ... } }, expose: ['reset'] }
注意,我們新增了一個新的選項API屬性expose
,允許我們傳入一個陣列,其中字串'reset'
是我們公開的函數的名稱。
建立一個強大臉靈活的元件的方法是利用渲染函數的力量。這對Vue 3來說並不新鮮,但是隨著composition API的建立,我們現在可以靈活地從setup
方法中直接返回組合API h
函數。
這就產生了一個問題,因為在我們的setup
函數中,整個return
語句只是包含元件正在建立的節點的 h
方法。
如果在這個時候我們選擇向父類別 expose 一些東西,我們就會遇到與我們之前看到的相反的問題。沒有任何東西被暴露,因為除了DOM元素,沒有任何東西被返回。
讓我們重寫 MyCounter.vue
元件來使用這個方法。
<script> // The template has been deleted import { ref, h } from 'vue' export default { setup (props, context) { const counter = ref(0) const interval = setInterval(() => { counter.value++ }, 1000) const reset = () => { counter.value = 0 } const terminate = () => { clearInterval(interval) } // context.expose({ reset }) return () => h('div', [ h('p', `Counter: ${counter.value}`), h('button', { onClick: reset }, 'Reset'), h('button', { onClick: terminate }, 'Terminate') ]) } } </script>
注意,我們在頂部從Vue匯入了 h
,因為我們需要用它來建立我們的DOM元素。
為了說明問題,暫時註釋了context.expose
方法。
現在的 return 語句複製了我們之前的 <template>
的DOM結構,如果我們執行這個例子,我們能夠正確點選元素上的重置和終止按鈕。
然而,如果我們現在點選 "Reset from parent"按鈕,我們會遇到一個錯誤。
Uncaught TypeError: this.$refs.counter.reset is not a function
reset
方法不再被暴露,因為它沒有被setup
函數返回。為了解決這個問題,我們需要取消對context.expose
的呼叫,使其再次可用。
新的 expose
方法是非常直觀的,而且很容易在我們的元件中實現。它清除了一些非常重要的組成問題,這些問題在過去甚至需要重寫一個完整的元件,所以即使它不是你日常使用的API,它也是值得收藏在我們資料夾中吃灰。
英文原文:https://www.vuemastery.com/blog/understanding-vue-3-expose/
【相關視訊教學推薦:、】
以上就是Vue3.2中的expose是啥?有什麼用?的詳細內容,更多請關注TW511.COM其它相關文章!