Ant Design 组件二次封装

Ant Design 组件二次封装

为什么需要二次封装:

  1. 减少重复工作量
  2. 统一风格
  3. 补充需求功能
  4. 方便一键式更改(如果样式变更,减少工作量)

二次封装的原则:

1. 暴露组件库本身的属性:

  • 绑定$attrs暴露props
1
2
3
<template>
<a-table v-bind="$attrs"></a-table>
</template>
  • 把子组件的props赋给当前组件的props
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<a-table v-bind="$props"></a-table>
</template>

<script>
import {Table} from 'ant-design-vue'

export default {
props: {
...Table.props,
...myProps
}
}
</script>

2. 暴露组件库本身的事件:

  • 绑定$listeners暴露事件
1
2
3
<template>
<a-table v-on="$listeners"></a-table>
</template>
  • v-on=“$listeners“与重写事件有冲突,会执行两次:第一个是v-on=”$listeners”,第二个是@change=”onSelectChange
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//change 事件重写,返回更多的参数
//组件
<template>
<a-table @change="changeSelect" v-on="$listeners"></a-table>
</template>

<script>
method: {
changeSelect(val) {
this.$emit('change', val)
}
}
</script>

//父组件
<template>
<MyTable @change="selectChange"></MyTable>
</template>
  • 解决:去掉 @change=“changeSelect”, 使用 new$listeners 继承原有属性,并覆盖原有事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<a-table v-on="new$listeners"></a-table>
</template>

<script>
computed: {
new$listeners() {
return Object.assign(this.$listeners, {
//在这里覆盖原有的change事件
change: this.changeSelect
})
}
},
method: {
changeSelect(val) {
this.$emit('change', val)
}
}
</script>

3. 绑定slots和scopedSlots暴露插槽:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<a-table>
<slot></slot>
<!-- 处理 scopedSlots -->
<template v-for="slotName of scopedSlotsKeys" :slot="slotName">
<slot :name="slotName"></slot>
</template>

<!-- 处理 slots -->
<template v-for="slotName of slotsKeys" v-slot:[slotName]>
<slot :name="slotName"></slot>
</template>
</a-table>
</template>

<script>
computed: {
slotsKeys() {
return Object.keys(this.$slots).filter((key) => !this.usedSlots.includes(key))
},
scopedSlotsKeys() {
return Object.keys(this.$scopedSlots).filter((key) => !this.usedSlots.includes(key))
},
},
</script>

4. 暴露实例的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//组件
methods:{
getRefTable(){
return this.$refs.refTable
}
}
}

//父组件
methods:{
loadData(){
this.$nextTick(() => {
//只要拿到这个实例,this.$refs.child.getRefTable(),想调方法后面跟链式调用即可
this.$refs.child.getRefTable().getCheckedNodes()
})
}
}
}

二次封装的注意点:

  • 不要修改props的数据

    • 如果业务接口更新的是props中的数据,那就不要这段业务代码,放到父组件去做更好。
  • 不要在vue文件里封装多个数据入口

    • 当一个组件要耦合多个数据入口时,就不要把请求写在子组件里面,而是把这个组件改造为纯展示组件,跟业务解耦,把业务请求交给父组件。
    • 组件里面最好都用静态。
  • 载体分离原则

    • 载体是展示的方式,例如弹窗、抽屉等等,最好把内容和载体分离,便于修改和维护。
  • 实现双向绑定,简化事件处理

    • 封装输入框、复选框这种组件的时候,需要保留 v-model 。
  • 修改组件库的样式

    • 修改单个文件的样式,可以使用 /deep/ 来深度选择到你要修改的样式(能省去一大串的类名)。
    • 修改全局的样式,可以在全局样式文件中写样式覆盖,引入到 main.js 中即可全局生效。
作者

冷冷

发布于

2023-04-19

更新于

2023-04-27

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×