文章目录
- vue组件封装技巧
- 1.props参数
- 2.$attrs
- 3.$emit
- 4.$listeners
- 5.插槽
vue组件封装技巧
1.props参数
最简单父传子的技巧,在父组件传入值,子组件声明props接收就可以了
如下:
父组件:
<template>
<div id="app">
<Table content="外面调用的"></Table>
</div>
</template>
<script>
import Table from './components/Table.vue';
export default {
name: 'App',
components: {
Table
}
}
</script>
子组件:
<template>
<div>{{content}}</div>
</template>
<script>
export default {
data() {
return {
}
},
props:['content'],
mounted() {
console.log("父亲过来的",this.$attrs);
},
}
</script>
上面是用的props的数组语法,下面是对象语法,做更近一步处理时可以使用
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true,
},
// 带有默认值的数字
propD: {
type: Number,
default: 100,
},
// 具有默认值的数组写法
propK: {
type: Array,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return ["张三"];
},
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: "hello" };
},
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ["success", "warning", "danger"].indexOf(value) !== -1;
},
},
},
2.$attrs
用途:在对组件进行二次封装的时候会出现孙子组件的传值问题,如果都通过prop进行层层传递太过麻烦,可以选择不使用props传值而通过$attrs传递
定义:包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件——在创建更高层次的组件时非常有用。
用法:父组件正常传入数据,子组件通过在孙组件上v-bind=:" a t t r s " 将未 p r o p s 声明的数据传递,孙组件通过 t h i s . attrs"将未props声明的数据传递,孙组件通过this. attrs"将未props声明的数据传递,孙组件通过this.atrs.xxx进行使用
父组件:
<template>
<div id="app">
<Table content="外面调用的" msg="这是测试attrs"></Table>
</div>
</template>
<script>
import Table from './components/Table.vue';
export default {
name: 'App',
components: {
Table
}
}
</script>
子组件:
<template>
<div v-bind="$attrs">{{this.$attrs.content}}</div>
</template>
<script>
export default {
data() {
return {};
},
mounted() {
console.log("父亲过来的", this.$attrs);
}
};
</script>
打印台信息:
但这有一个需要注意的点:$attrs将propos未声明的属性会作为HTML属性绑定到组件的根元素上
这时候需要添加:
inheritAttrs:false
3.$emit
可以用于子组件向父组件传递消息,触发定义的事件
父组件:
<template>
<div >
<last @msgA="msgA"></last>
</div>
</template>
<script>
import last from '@/components/last.vue'
export default {
data() {
return {};
},
components:{
last
},
methods:{
msgA(name){
console.log("事件被调用了",name);
}
}
};
</script>
子组件:
<template>
<div></div>
</template>
<script>
export default {
created(){
this.$emit('msgA','sssss')
},
}
</script>
可以看到控制台输出的内容
4.$listeners
与 $attrs的用法类似,当我们需要将事件处理函数传递给子组件时,可以利用父组件实例上的 l i s t e n e r s 属性,这个属性包含了组件接收到的事件处理函数 , 需要在子组件上绑定: v − o n = " listeners属性,这个属性包含了组件接收到的事件处理函数,需要在子组件上绑定:v-on=" listeners属性,这个属性包含了组件接收到的事件处理函数,需要在子组件上绑定:v−on="listeners"
父组件:
<template>
<div >
<last @msgA="msgA"></last>
</div>
</template>
<script>
import last from '@/components/last.vue'
export default {
data() {
return {};
},
components:{
last
},
methods:{
msgA(name){
console.log("事件被调用了",name);
}
}
};
</script>
子组件:
<template>
<div v-bind="$attrs" v-on="$listeners"></div>
</template>
<script>
export default {
created(){
this.$emit('msgA','sssss')
},
mounted() {
console.log("父亲过来的值", this.$attrs);
console.log("父亲传过来的事件",this.$listeners);
this.$listeners.msgA('sdddddddd')
},
}
</script>
可以看到控制台打印的信息
简单来说: a t t r s 与 attrs与 attrs与listeners 是两个对象, a t t r s 里存放的是父组件中绑定的非 P r o p s 属性, attrs 里存放的是父组件中绑定的非 Props 属性, attrs里存放的是父组件中绑定的非Props属性,listeners里存放的是父组件中绑定的非原生事件。
5.插槽
一个通用组件,往往不能够适应所有应用场景,所以在封装组件的时候只需要完成组件 80% 的功能,剩下的 20% 让父组件通过 solt 解决。比如:某一个公共组件中有两个按钮,一个是“新增”,一个是“删除”,但是在另外的场景中使用这个组件时,两个按钮需要做的事情是不一样的,比如是“查看”和“修改”。所以,我们在封装组件的时候就不要直接写按钮了,而是在合适的位置放置一个slot,其实是一个占位的作用,给按钮的设置提前预留一个位置,然后在父组件中写入按钮即可。
具体插槽如何使用我之前发过一篇文章,见下方链接
插槽