如何監聽Vue的插槽變化?以下這篇文章跟大家介紹一下監聽Vue插槽變化的方法,希望對大家有幫助!
最近,每當元件的內容(插槽、子元件等)改變時,我需要更新它的狀態。對於上下文,它是一個表單元件,用於追蹤其輸入的有效性狀態。
下面的程式碼片段是以Options
API格式編寫的,但除了指定的地方外可以在Vue2 和 Vue2中使用。 【相關推薦:vuejs影片教學】
先從控製表單狀態開始,根據狀態修改一個類,孩子內容使用<slot/>
填充:
<template> <form :class="{ '--invalid': isInvalid }"> <slot /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), }; </script>
為了更新isInvalid
屬性,我們需要新增一個觸發的事件,可以使用sumit
事件,但我更喜用input
事件。
表單事件7個: focus, blur, input, select, change, reset, submit 等,具體詳解看這篇文章:https://blog.csdn.net/qq_4379 ...
表單不會觸發input
事件,但我們可以使用"事件委託"。我們將監聽器附加到父元素(<form>
)上,當事件發生在它的子元素(<input>
、<select>
、<textarea>
等)上時就會被觸發。
任何時候在這個元件的<slot>
中觸發input
事件,表單將捕獲該事件。
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), methods: { validate() { // 验证逻辑 } } }; </script>
驗證邏輯可以是簡單或複雜的。本文為了示範,用簡單的方法,使用form.checkValidity()
API 來檢視表單是否基於HTML驗證屬性而有效。
為了存取<form>
元素。可以用refs
或$el
屬性。為了簡單起見,本文使用$el
。
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), methods: { validate() { this.isInvalid = !this.$el.checkValidity() } } }; </script>
這裡有一點問題。如果表單的內容改變了,會發生什麼事?如果一個<input>
在表單載入被加入到DOM中,會發生什麼事?
舉個例子,我們把這個表單元件稱為"MyForm"
,在App 中,內容如下:
// App.vue <template> <MyForm> <input v-model="showInput" id="toggle-name" name="toggle-name" type="checkbox" /> <label for="toggle-name">显示其它 input</label> <template v-if="showInput"> <label for="name">Name:</label> <input id="name" name="name" required /> </template> <button type="submit">提交</button> </MyForm> </template> <script> import Form from "./components/form.vue"; export default { name: "App", components: { MyForm: Form, }, data: () => ({ showInput: false, }), }; </script>
當App.vue
透過條件來隱藏顯示某些input
,我們的表單需要知道。在這種情況下,我們會想到在表單內容變更時追蹤其有效性,而不僅僅是在 input
事件或mounted
生命週期鉤子上。否則,可能會顯示不正確的資訊。
熟悉 Vue的生命週期鉤子小夥伴,這裡可能會想到使用 update
來追蹤變化。理論上,這聽起來不錯。在實踐中,它會創造一個無限的循環,然後瀏覽器掛了。
經過一番研究和測試,最佳解決方案是使用MutationObserver
API。它是瀏覽器內建的方法,提供了監視對DOM樹所做更改的能力,如果節點的增減、屬性的變動、文字內容的變動,這個 API 都可以得到通知。
它是原生的方法,所以不受限於框架。
使用時,先使用MutationObserver
建構函數,新建一個觀察器實例,同時指定這個實例的回調函數。在每次 DOM 變動後調用,這個回呼都會被調用。這個回呼函數接受兩個參數,第一個是變動數組,第二個是觀察器實例,將我們的form
元件改寫成如下:
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), mounted() { const observer = new MutationObserver(this.validate); observer.observe(this.$el, { childList: true, subtree: true, }); this.observer = observer; }, methods: { validate() { this.isInvalid = !this.$el.checkValidity(); }, }, beforeUnmount() { this.observer.disconnect(); }, }; </script> <style scoped> </style>
這裡還需要使用beforeUnmount
生命週期事件來斷開observer
的連接,這會清除它所分配的任何記憶體。
最後,我們將isInvalid
狀態傳遞給要存取的內容的插件槽,這也稱為作用域的槽,它非常有用。
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot v-bind="{ isInvalid }" /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), mounted() { const observer = new MutationObserver(this.validate); observer.observe(this.$el, { childList: true, subtree: true, }); this.observer = observer; }, methods: { validate() { this.isInvalid = !this.$el.checkValidity(); }, }, beforeUnmount() { this.observer.disconnect(); }, }; </script>
透過這樣的設置,可以在我們的表單元件中添加任意數量的 input
,並添加任何它需要的條件渲染邏輯。只要input
使用HTML驗證屬性,表單就會追蹤它是否處於有效狀態。
此外,由於使用的是作用域槽,我們將表單的狀態提供給父級,所以父級可以對有效性的變化做出反應。
例如,在App.vue
,我們想在表單無效時"禁用" 提交按鈕,可以這麼來寫
<template> <MyForm> <template slot:default="form"> <label for="name">Name:</label> <input id="name" name="name" required> <button type="submit" :class="{ disabled: form.isInvalid }" > Submit </button> </template> </MyForm> </template>
nice~.
#希望這篇文章能對你未來的開必有所幫助。
以上是如何監聽Vue的插槽變化?試試這一招!的詳細內容。更多資訊請關注PHP中文網其他相關文章!