你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

【Vue】如何更好的封装组件?几个小技巧助你成为组件封装达人,让我们封装的组件更加优雅易用

2021-11-29 22:42:05

目录

  • 一、$attrs
  • 二、$listeners

一、$attrs

我们在使用组件的过程中,有时需要给被封装的子组件传递Prop
例如:

<template>
    <el-input v-model="innerVal" placeholder="placeholder"
    @input="$emit('input',$event)"
    >
    </el-input>
</template>

<script>
  export default {
    name: "MyInput",
    data(){
      return{
        innerVal:this.value
      }
    },
    watch:{
      value(){
        if(this.value!==this.innerVal){
          this.innerVal=this.value
        }
      }
    }
  }
</script>

<style scoped>

</style>

我们二次封装了my-input组件
需求:通过my-input组件将el-input原有的clearable属性传递给它
原始做法:
我们可以在my-input组件中声明clearable属性,通过my-input组件接收clearable
在这里插入图片描述
再将它传递给el-input组件:
在这里插入图片描述
父组件未传递clearable值:
在这里插入图片描述

在这里插入图片描述

父组件传递clearable值:

在这里插入图片描述
在这里插入图片描述

但是如果每一个Prop都需要父组件声明,再一个一个传递给子组件,那就太麻烦了

此时我们可以利用组件实例上的$attrs属性来简化这个过程

请添加图片描述
这个属性包含了组件被传入,但没有被声明的Prop
我们可以打印这个属性来看一下:
第一步:清除之前的声明
第二步:在create钩子中打印$attrs属性
在这里插入图片描述
查看打印结果:
在这里插入图片描述
这里面就包含的有我们传入的clearable属性
接下来我们可以通过v-bind指令,以传入对象的方式将 $attrs中的属性,绑定到子组件上,这样父组件就无需声明,就可以轻松地将这些prop传递给子组件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样父组件就无需声明,就可以轻松地将这些prop传递给子组件

但需要注意的一点是,Vue会将组件被传入,但未声明的prop作为HTML属性绑定到组件的根元素上:
在这里插入图片描述

因此我们需要用下面的属性来处理这种情况
在这里插入图片描述
将其值设置为false来避免这种行为
在这里插入图片描述
解决:
在这里插入图片描述
$attrs其实相当于传输数据的一个桥梁

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Title</title>
</head>
<body>

<div id="app">
    <the-parent :rootData="rootData"></the-parent>

</div>
<template id="theParent">
    <the-children v-bind="$attrs"></the-children>
</template>
<template id="theChildren">
    <div>子组件展示:{{rootdata}}</div>
</template>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      rootData: "根组件的数据"
    },
    components: {
      theParent: {
        template: "#theParent",
        // inheritAttrs:false,
        created() {
          console.log(this.$attrs)
        },
        components: {
          theChildren: {
            template: "#theChildren",
            props: ['rootdata'],
          }
        }
      }
    }
  });
</script>
</body>
</html>

运行结果:
在这里插入图片描述

二、$listeners

刚才我们介绍了如何将prop传递给子组件,如果我们想将事件处理函数传递给子组件时

原始做法:
我们先将一个事件处理函数绑定到子组件上
在这里插入图片描述

再在事件处理函数中,触发事件
在这里插入图片描述

来触发绑定在父组件上的处理函数
在这里插入图片描述
结果:
在这里插入图片描述

新用法:

与 $attrs的用法类似,当我们需要将事件处理函数传递给子组件时,可以利用父组件实例上的 $listeners属性,这个属性包含了组件接收到的事件处理函数

现在我们给MyInput父组件绑定了clear事件的处理函数,
我们首先也在created钩子中打印一下 $listeners属性
在这里插入图片描述
这个 $listeners就包含我们传入的clear处理函数
去掉原始做法

现在我们配合v-on指令将这个处理函数直接转发给子组件
在这里插入图片描述
直接就能接收父组件的处理事件:
在这里插入图片描述

三、$slots