HintButton组件封装实现增删改查

605 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

HintButton组件效果图:

image.png image.png

需要用到的两个api:

image.png

image.png

  1. $listeners 会收集当前组件的所有自定义事件

  2. $attrs 会收集当前组件没有通过props接受的标签属性

  3. 在组件中props声明过xxx,那么$attrs里就不会出现xxx属性了 如果我们给child传props没有注册的属性,我们就要用$attrs来取了

需求:

  • 点击事件 以及很多属性都是绑定在子组件button上 image.png
  • 按照正常的写法过于臃肿 image.png

正常写法代码:

子组件:

<template>
  <div class="">
    <el-tooltip :effect="effect" :content="title" :placement="placement">
      <el-button
        :type="type"
        :icon="icon"
        :circle="circle"
        @click="tellParent"
      ></el-button>
    </el-tooltip>
  </div>
</template>

<script>
export default {
  props: {
    placement: {
      type: String,
      //    type: [Number, String],
      //  type: String | Number,
      //      type(){
      //     return Number | String
      //   },
      default: "top"
    },
    effect: {
      type: String,
      default: "dark"
    },
    title: {
      type: String
    },
    circle:{
        type:String,
        redirect: true
    },
    icon:{
        type:String,
        redirect: true
    },
    type:{
        type:String,
        redirect: true
    },
    
  },
  name: "HintButton",
  created() {},
  mounted() {},
  data() {
    return {};
  },
  computed: {},
  methods: {
    tellParent() {
      this.$emit("event-son", "子组件发送事件给父组件!!!");
    }
  }
};
</script>

<style scoped></style>


父组件:

ps: event-son是自定义的方法,其中参数一定要写$event参数。

  
<HintButton class="item" title="增加" effect="dark" placement="top" type="primary" icon="el-icon-circle-plus" circle  @event-son="handleAdd($event,scope.$index, scope.row)"></HintButton>
<HintButton class="item" title="删除" effect="light" placement="left" type="danger" icon="el-icon-delete" circle  @event-son="handleDelete($event,scope.$index, scope.row)"></HintButton>
<HintButton class="item" title="编辑" effect="dark" placement="right" type="warning" icon="el-icon-edit" circle @event-son="handleEdit($event,scope.$index, scope.row)"></HintButton>
<HintButton class="item" title="查找" effect="light" placement="bottom" type="info" icon="el-icon-search" circle  @event-son="handleSeach($event,scope.$index, scope.row)"></HintButton>

优化后代码:

image.png

  • 点击事件直接绑定到了子组件的button上
<template>
  <div class="">
    <el-tooltip :effect="effect" :content="title" :placement="placement">
       <el-button v-on="$listeners" v-bind="$attrs"></el-button>
    </el-tooltip>
  </div>
</template>

<script>
export default {
  props: {
    placement: {
      type: String,
      default: "top"
    },
    effect: {
      type: String,
      default: "dark"
    },
    title: {
      type: String
    },
    
  },
  name: "HintButton",
  created() {},
  mounted() {},
  data() {
    return {};
  },
  computed: {},
  methods: {
    tellParent() {
      this.$emit("event-son", "子组件发送事件给父组件!!!");
    }
  }
};
</script>

<style scoped></style>


父组件:

<HintButton class="item" title="增加" effect="dark" placement="top" type="primary" icon="el-icon-circle-plus" circle  @click="handleAdd($event,scope.$index, scope.row)"></HintButton>
<HintButton class="item" title="删除" effect="light" placement="left" type="danger" icon="el-icon-delete" circle  @click="handleDelete($event,scope.$index, scope.row)"></HintButton>
<HintButton class="item" title="编辑" effect="dark" placement="right" type="warning" icon="el-icon-edit" circle @click="handleEdit($event,scope.$index, scope.row)"></HintButton>
<HintButton class="item" title="查找" effect="light" placement="bottom" type="info" icon="el-icon-search" circle  @click="handleSeach($event,scope.$index, scope.row)"></HintButton>

当然这个$attrs是vue2.4才推出的,为了简化父组件和孙组件的传值

注:不可滥用,如果是明确的属性还是要声明的,否则代码会越来越难维护。有些属性是需要指定特殊类型的,有些属性为了安全起见是不可以直接传递给子元素的。

父组件和孙组件的传值

效果图:

image.png

图解:

image.png

代码:

child1(子):


<template>
  <div class="child1">
    <h2>子组件</h2>
    props:
    <span style="color:red">{{ name }},{{ age }}</span>
    或者
    <span style="color:red">{{ $props["name"] }},{{ $props["age"] }}</span>
    <br />
    在$attrs里面只会有props没有注册的属性 attrs:
    <span style="color:blue">{{ $attrs["gender"] }}</span>
    <h4 v-bind="$attrs">gender=“male”属性在我身上吗?在的</h4>
    <!-- 孙组件: -->
    <child2 v-bind="$attrs"></child2>
  </div>
</template>

<script>
import child2 from "../child2/index.vue";
export default {
  props: ["name", "age"],
  components: {
    child2
  },
  name: "",
  created() {},
  mounted() {},
  data() {
    return {};
  },
  computed: {},
  methods: {}
};
</script>

<style scoped>
.child1 {
  width: 100%;
  background-color: rgb(211, 205, 194);
  text-align: center;
}
</style>

child2(孙):

<template>
  <div class="child2">
    <!-- 在child2里面,就可以直接用props注册gender,来直接获取来自“祖父组件”的gender值了 -->
    <h3>孙组件</h3>
    <!-- <h4>直接用props注册gender:{{}}</h4> -->
    <h4 style="color:orange">{{gender}}</h4>
    <!-- 当然,不注册也是可以用$attrs来取值的 -->
    <!-- <h4>{{ $attrs.gender }}</h4> -->
  </div>
</template>

<script>
export default {
  props: ['gender'],
  name: "",
  created() {},
  mounted() {},
  data() {
    return {};
  },
  computed: {},
  methods: {}
};
</script>

<style scoped>
.child2 {
  margin: 0 auto;
  background-color: aqua;
  width: 500px;
  text-align: center;
}
</style>


父组件:

 <h3 style="background-color:orange;">父组件:</h3>
 <child1 name="rick" :age="18" gender="male"></child1>

拜~~~