組件不滿足需求词裤,要對當前組件再次封裝黍判,會遇到以下一些問題:
1豫尽、原組件的Attributes怎么處理原組件屬性可以通過透傳
$attrs,獲取父組件的屬性
<el-input ref="childInputRef" v-bind="$attrs"></el-input>
2顷帖、原組件的插槽怎么設(shè)置
通過$slots獲取當前組件所有的插槽對象美旧,通過遍歷添加到原組件插槽
子組件:searchInput.vue
<el-input ref="childInputRef" v-bind="$attrs">
<template v-for="(value, name) in $slots" #[name]>
<slot :name="name"></slot>
</template>
</el-input>
父組件
<SearchInput >
<template #append">
<el-button>Search</el-button>
</template>
</SearchInput>
效果:
1687939543818.png
具名作用域插槽
子組件:searchInput.vue
<el-input ref="childInputRef" v-bind="$attrs">
<template v-for="(value, name) in $slots" #[name]>
<slot :name="name" :slotData="slotData">></slot>
</template>
</el-input>
...
....
const slotData = reactive({
msg: 'aaaa'
})
父組件
<SearchInput>
<template #append="{slotData}">
{{ slotData.msg }}
<el-button>Search</el-button>
</template>
</SearchInput>
效果:
1687939766543.png
3渤滞、原組件的ref方法調(diào)用
將原組件的提供的方法加入到當前組件中
子組件:searchInput.vue
<el-input ref="childInputRef" v-bind="$attrs"></el-input>
<script setup lang="ts">
import { useAttrs, ref, onMounted, reactive, useSlots } from 'vue'
const childInputRef = ref()
const options = reactive<{[key: string]: any}>({})
const slotData = reactive({
msg: 'aaaa'
})
onMounted(() => {
const entries = Object.entries(childInputRef?.value)
console.log('entries:', entries)
for (const [key, value] of entries) {
if (!value || typeof value !== 'function') {
continue
}
options[key] = value
}
})
父組件:
<template>
<div>
<SearchInput
ref="searchInput"
>
</SearchInput>
<el-button @click="changeFocus">Focus</el-button>
</div>
</template>
<script setup lang="ts">
const searchInput = ref()
function changeFocus() {
searchInput.value.focus()
}
</script>
完整代碼:
子組件:searchInput.vue
<template>
<div>
<el-input ref="childInputRef" v-bind="$attrs">
<template v-for="(value, name) in slots" #[name]>
<slot :name="name" :slotData="slotData"></slot>
</template>
</el-input>
</div>
</template>
<script setup lang="ts">
import { useAttrs, ref, onMounted, reactive, useSlots } from 'vue'
// const attrs = useAttrs()
const slots = useSlots()
const childInputRef = ref()
const options = reactive<{[key: string]: any}>({})
const slotData = reactive({
msg: 'aaaa'
})
onMounted(() => {
const entries = Object.entries(childInputRef?.value)
console.log('entries:', entries)
for (const [key, value] of entries) {
if (!value || typeof value !== 'function') {
continue
}
options[key] = value
}
})
defineExpose(options)
</script>
父組件:index.vue
<template>
<div>
<SearchInput
ref="searchInput"
v-model="searchForm.keyword"
placeholder="請輸入"
active-value
show-password
clearable
@change="handleChange">
<template #append="{slotData}">
{{ slotData.msg }}
<el-button>Search</el-button>
</template>
</SearchInput>
<el-button @click="changeFocus">Focus</el-button>
</div>
</template>
<script setup lang="ts">
import SearchInput from './views/layout/components/searchInput.vue'
import { onMounted, reactive, ref, toRef, toRefs, getCurrentInstance } from 'vue';
const searchInput = ref()
const searchForm = reactive({
keyword: ''
})
function changeFocus() {
console.log('keyword:', searchForm.keyword)
searchInput.value.focus()
}
function handleChange(v: string) {
console.log('input:', v)
}
</script>
<style lang="scss" scoped>
</style>