小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
HintButton组件效果图:
需要用到的两个api:
-
$listeners 会收集当前组件的所有自定义事件
-
$attrs 会收集当前组件没有通过props接受的标签属性
-
在组件中
props
声明过xxx
,那么$attrs
里就不会出现xxx
属性了 如果我们给child传props没有注册的属性,我们就要用$attrs来取了
需求:
- 点击事件 以及很多属性都是绑定在子组件button上
- 按照正常的写法过于臃肿
正常写法代码:
子组件:
<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>
优化后代码:
- 点击事件直接绑定到了子组件的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才推出的,为了简化父组件和孙组件的传值
注:不可滥用,如果是明确的属性还是要声明的,否则代码会越来越难维护。有些属性是需要指定特殊类型的,有些属性为了安全起见是不可以直接传递给子元素的。
父组件和孙组件的传值
效果图:
图解:
代码:
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>