美文网首页
vue 基于组件的二次封装

vue 基于组件的二次封装

作者: wxw_威 | 来源:发表于2023-06-27 16:19 被阅读0次

    组件不满足需求,要对当前组件再次封装,会遇到以下一些问题:

    1、原组件的Attributes怎么处理原组件属性可以通过透传

    $attrs,获取父组件的属性

    <el-input ref="childInputRef" v-bind="$attrs"></el-input>
    
    2、原组件的插槽怎么设置

    通过$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方法调用
    将原组件的提供的方法加入到当前组件中
    子组件: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>
    

    相关文章

      网友评论

          本文标题:vue 基于组件的二次封装

          本文链接:https://www.haomeiwen.com/subject/eddnydtx.html