對於第三方元件,如何在保持第三方元件原始功能(屬性props、事件events、插槽slots、方法methods)的基礎上,優雅地進行功能的擴充了?
以Element Plus的el-input為例:
很有可能你以前是這樣玩的,封裝一個MyInput元件,把要使用的屬性props、事件events和插槽slots 、方法methods根據自己的需要再寫一遍:
// MyInput.vue <template> <div class="my-input"> <el-input v-model="inputVal" :clearable="clearable" @clear="clear"> <template #prefix> <slot name="prefix"></slot> </template> <template #suffix> <slot name="suffix"></slot> </template> </el-input> </div> </template> <script setup> import { computed } from 'vue' const props = defineProps({ modelValue: { type: String, default: '' }, clearable: { type: Boolean, default: false } }) const emits = defineEmits(['update:modelValue', 'clear']) const inputVal = computed({ get: () => props.modelValue, set: (val) => { emits('update:modelValue', val) } }) const clear = () => { emits('clear') } </script>
可過一段時間後,需求變更,又要在MyInput組件上添加el-input組件的其它功能,可el-input組件總共有20個多屬性,5個事件,4個插槽,那該怎麼辦呢,難道一個個傳進去,這樣不僅繁瑣而且可讀性差。
在Vue2中,我們可以這樣處理,點擊這裡查看封裝Vue第三方組件
此文詣在幫助大家做一個知識的遷移,探究如何使用Vue3 CompositionAPI優雅地封裝第三方元件~
在Vue2中
$attrs: 包含了父作用域中不作為prop 被識別(且獲取) 的attribute 綁定(class 和style 除外)。當一個元件沒有宣告任何prop 時,這裡會包含所有父作用域的綁定(class 和style 除外),並且可以透過v-bind="$attrs" 傳入內部元件
//MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"></el-input> </div> </template> <script setup> import { useAttrs } from 'vue' const attrs = useAttrs() </script>
下面我們來看看Vue3文件對inheritAttrs的解釋
預設情況下父作用域的不被認定props 的attribute 綁定(attribute bindings) 將會「回退」且作為普通的HTML attribute 應用在子元件的根元素上。當撰寫包裹一個目標元素或另一個元件的元件時,這可能不會總是符合預期行為。透過設定 inheritAttrs 到 false,這些預設行為將會被去掉。而透過實例 property $attrs 可以讓這些 attribute 生效,且可以透過 v-bind 顯性的綁定到非根元素上。
於是,我們對於第三方元件的屬性props、事件events處理,可以寫成如下程式碼:
// MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"></el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs } from 'vue' const attrs = useAttrs() </script>
二、對於第三方元件的插槽slots
//MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"> <template v-for="k in Object.keys(slots)" #[k] :key="k"> <slot :name="k"></slot> </template> </el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs, useSlots } from 'vue' const attrs = useAttrs() const slots = useSlots() </script>
如果不滿足以上條件的話,咱還得老實在子元件中手動新增需要的第三方元件的插槽~
三、對於第三方元件的方法methods
子元件:MyInput.vue
// MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs" ref="elInputRef"> <template v-for="k in Object.keys(slots)" #[k] :key="k"> <slot :name="k"></slot> </template> </el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs, useSlots } from 'vue' const attrs = useAttrs() const slots = useSlots() const elInputRef = ref(null) defineExpose({ elInputRef // <script setup>的组件里的属性默认是关闭的,需通过defineExpose暴露出去才能被调用 }) </script>
父親頁面:Index.vue的呼叫程式碼如下:
// Index.vue <template> <my-input v-model='input' ref="myInput"> <template #prefix>姓名</template> </my-input> </template> <script setup> import MyInput from './components/MyInput.vue' import { ref, onMounted } from 'vue' const input = ref('') const myInput = ref(null) // 组件实例 onMounted(()=> { myInput.value.elInputRef.focus() // 初始化时调用elInputRef实例的focus方法 }) </script>
以上是Vue3 Composition API怎麼優雅封裝第三方元件的詳細內容。更多資訊請關注PHP中文網其他相關文章!