vue3组件二次封装Ui处理

vue 组件二次封装Ui处理

vue 组件二次封装Ui处理

在Vue开发中,我们常常需要使用UI框架提供的组件。但是UI框架的组件可能并不符合我们的需求,这时候就需要进行二次封装。下面是一些关于Vue组件二次封装Ui处理的技巧:

常规时候咱们使用组件的props、events、slot等属性的传递

子组件代码:

<template>
  <div class="my-input">
    <el-input></el-input>
  </div>
</template>

<script setup>
export default {
  props:[]
}
</script>

<style scoped>
.my-input {
  transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>

父组件使用:

<my-input v-model="value"></my-input>

如果使用props接收弊端:

  1. 基本上组件不会只有一两个属性,属性多的话接收的数据量多,需要写大量的无用代码
  2. 如果存在多级组件嵌套传值,又是重复代码,并且维护性差

$attrs$listeners 解决数据穿透问题

因为vue2和vue3有些不同咱分开讲:

vue2的介绍和使用:

在这里插入图片描述

上面感觉很难懂:简单来说就是**$attrs** 接收传递过来的props的值。**$listeners** 当 inheritAttrs:true 继承除props之外的所有属性;inheritAttrs:false 只继承class属性

vue2的代码:

father.vue 组件:

<template>
   <child :name="name" :age="age" :infoObj="infoObj" @updateInfo="updateInfo" @delInfo="TodelInfo" />
</template>
<script>
    import Child from '../components/child.vue'

    export default {
        name: 'father',
        components: { Child },
        data () {
            return {
                name: 'zhangyangguang',
                age: 24,
                infoObj: {
                    from: '济南',
                    job: 'policeman',
                    hobby: ['reading', 'writing', 'skating']
                }
            }
        },
        methods: {
            updateInfo() {
                console.log('update info');
            },
            TodelInfo() {
                console.log('delete info');
            }
        }
    }
</script>

child.vue 组件:

<template>
    <son :height="height" :weight="weight" @addInfo="addInfo" v-bind="$attrs" v-on="$listeners"  />
    // 通过 $listeners 将父作用域中的事件,传入 grandSon 组件,使其可以获取到 father 中的事件
</template>
<script>
    import Son from '../components/Son.vue'
    export default {
        name: 'child',
        components: { Son },
        props: ['name'],
        data() {
          return {
              height: '183cm',
              weight: '76kg'
          };
        },
        created() {
            console.log(this.$attrs); 
       // 结果:age, infoObj, 因为父组件共传来name, age, infoObj三个值,由于name被 props接收了,所以只有age, infoObj属性
            console.log(this.$listeners); // updateInfo: f, TodelInfo: f
        },
        methods: {
            addInfo () {
                console.log('add info')
            }
        }
    }
</script>

son.vue 组件:

<template>
    <div>
        {{ $attrs }} --- {{ $listeners }}
    <div>
</template>
<script>
    export default {
        ... ... 
        props: ['weight'],
        created() {
            console.log(this.$attrs); // age, infoObj, height 
            console.log(this.$listeners) // updateInfo: f, TodelInfo: f, addInfo: f
            this.$emit('updateInfo') // 可以触发 father 组件中的updateInfo函数
        }
    }
</script>

一般不常用,可读性不是很好。但是组件嵌套层比较深,props很繁琐,可以使用。

vue3的使用和介绍:
 $listeners
在这里插入图片描述

代码:

<template>
  <div class="my-input">
    <el-input v-bind="$attrs"></el-input>
  </div>
</template>

<script setup></script>

<style scoped>
.my-input {
  transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>

直接 通过**$attrs** 接收属性和方法。后面在详细介绍vue3的Attributes

这样到这里已经解决属性和方法的问题了。

解决传值和方法问题,还有一个slot插槽

比如elementPlus的input 有如下插槽:
在这里插入图片描述

初步解决方法:

封装组件里定义对应数量的插槽然后再次传递

<template>
  <div class="my-input">
    <el-input v-bind="$attrs">
      <template #prefix>
        <slot name="prefix"></slot>
      </template>
      <template #suffix>
        <slot name="suffix"></slot>
      </template>
      <template #prepend>
        <slot name="prepend"></slot>
      </template>
      <template #append>
        <slot name="append"></slot>
      </template>
    </el-input>
  </div>
</template>

<script setup></script>

<style scoped>
.my-input {
  transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>

这里定义了四个插槽然后再次传递,确实解决了插槽问题。但是使用的组件不一定会使用全部的插槽。如果使用一个那咱们封装的组件就把其他插槽给传递了过去。这样很不保险,并且也不对

解决思路:父级传递几个插槽,咱就传递几个给子组件,不全部传递

进阶解决方法:使用$slots

在这里插入图片描述

也就是说**$slots**可以获取父级组件传递的插槽。

vue3代码:

<template>
  <div class="my-input">
    <el-input v-bind="$attrs">
      <template v-for="(val, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData || {}"></slot>
      </template>
    </el-input>
  </div>
</template>

<script>
export default {
  created() {
    console.log(this.$slots);
  },
};
</script>

<style scoped>
.my-input {
  transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>

这样就是父级传递啥那就传递啥插槽。到此解决了插槽问题。

到这里还有个最难的**ref 问题:**

因为ref只能作用于当前无法作用到孙组件

对于ref传递问题vue无法解决。但是咱可以换一个思路。使用ref无非是为了使用孙组件暴露的一些方法。那咱就可以吧孙组件的方法提取到子组件

说白了吧孙组件的方法提取到当前实例

代码:

<template>
  <div class="my-input">
    <el-input ref="inp" v-bind="$attrs">
      <template v-for="(val, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData || {}"></slot>
      </template>
    </el-input>
  </div>
</template>

<script>
export default {
  created() {
    console.log(this.$slots);
  },
  mounted() {
    console.log(this.$refs.inp);
    const entries = Object.entries(this.$refs.inp);
    for (const [key, value] of entries) {
      this[key] = value;
    }
  },
};
</script>

<style scoped>
.my-input {
  transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>

这样就完美解决了组件的Ui封装。

以上是一些关于Vue组件二次封装Ui处理的技巧。通过二次封装,我们可以更好地满足我们的需求,提高开发效率。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue2中,对于element-ui组件二次封装,可以按照以下步骤进行: 1. 需求分析:明确需要封装的element-ui组件,以及需要添加的功能和配置项。 2. 创建父组件:编写父组件的template和script代码,其中template中调用封装组件,script中定义需要传递给封装组件的props属性。 3. 创建封装组件:编写封装组件的template和script代码。在template中使用element-ui组件,并根据需要进行样式和布局的调整。在script中定义props属性,接收父组件传递的值,并监听element-ui组件的事件,触发update事件给父组件。 4. 通过临时变量传递值:由于父组件传递给封装组件的props不能直接作为封装组件的v-model属性传递给element-ui组件,所以需要在封装组件中定义一个临时变量来存储值,并将该变量与element-ui组件进行绑定。 5. 完成打通:在封装组件中监听中间件,接收到element-ui组件的update事件后,再将该事件传递给父组件。 总结来说,Vue2中对于element-ui组件二次封装,需要创建父组件封装组件,通过props属性传递值,并在封装组件中监听element-ui组件的事件并触发update事件给父组件。同时,需要使用临时变量来传递值给element-ui组件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Vue3+ts+element-plus 组件二次封装-- 页脚分页el-pagination的二次封装](https://blog.csdn.net/cs492934056/article/details/128096257)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值