请教一个前端写组件拆分的问题

198 天前
 redbeanzzZ
用 vue 写前端业务时候,我经常会遇到什么内容需要提出来写组件的问题。如果业务中这个组件比较复杂,复用性高,我肯定会把他拿出来写个组件复用。
我现在有一个场景想问下大家会怎么写:一个列表页有多个按钮,都是展开一个抽屉进行表单填写的,一共有七八个按钮。我把抽屉的框架拿出来写个组件(比如标题,确认框这样),内部的表单内容再根据业务不同单个文件引入。同事认为这七八个表单有两三个还有相似的地方,还是可以复用,还要继续把相似的表单继续拿出来写个组件用。

我觉得那七八个页面已经很简单,我直接写逻辑会更清晰一些。这种情况哪种才是对的呢?
997 次点击
所在节点    问与答
21 条回复
ljsh093
198 天前
领导要求看着做,不是领导要求的那谁提谁干呗
zcf0508
198 天前
不要过度抽象
shilianmlxg
198 天前
抽离的话,最好先问问自己:
1. 是否有逻辑上共用并且依赖 UI 交互,比如需要弹出框的确认和关闭按钮,都会有异步关闭。单把这个 dialog 封装成一个组件。
2. 这个逻辑共用但不依赖 UI 交互,可以抽成 hooks
3.是否可以把内部业务,拆成 slot 。
你这个可以写个公用 wrap 组件,然后里面再 slot 插槽不同的业务组件。个人的愚见,这样是我能想到的最好了。蹲下其他大佬的最优解。
ruoxie
198 天前
不要过度抽象
MrLeo
198 天前
不要过度抽象
66beta
198 天前
表单在拆分,那就是通用组件了呗,比如:国家选择器、货币选择器

不知道你说的"还可以复用",是指什么
Xu3Xan89YsA7oP64
198 天前
除非你说的『相似』是指类似于新增与更新这种填写内容几乎没差别的,否则没必要。
Adyi
198 天前
参考 elementUI
vczyh
198 天前
简单表单没必要复用,除非 FormItem 比较复杂,比如是个从接口获取的 Select List 这样才有必要复用。
Jarme
198 天前
不要过度抽象、业务剥离、纯粹性、易用(心智负担)
redbeanzzZ
198 天前
@shilianmlxg 我实际业务中,这个抽屉就是一个 header content footer 的结构。header 和 footer 完全一样,我拿出来携程组件了。每个按钮对应抽屉的 content 是一个表单,他们不一样,这里我把每个 content 单独拿出来写成组件。其中会有两个表单中 content 内容是一样的,但是校验不同、个别项为 disabled 无法编辑这样。
redbeanzzZ
198 天前
@66beta 就是两个表单,比如有三个 item ,对应国家选择器、货币选择器、时间选择器,但是两个表单的校验规则不同,还有其中一个时间选择器可能是 disabled 无法选择这样。
redbeanzzZ
198 天前
https://i2.mjj.rip/2024/06/07/18bc9ff508d25a5ac112a0d7cfd78953.png 我直接把图放出来咯,我已经把外面那个抽屉框子封好组件了。这俩表单虽然一样,但是否可编辑不同,校验规则不同,内容又这么少我还不如直接写吧?以后新需求基本也不可能再有一样表单。
@zcf0508
@shilianmlxg
@66beta
@shizhibuyu2023
@vczyh
shilianmlxg
197 天前
@redbeanzzZ #12 你可以看下动态表单 form 低代码的文档,看下人家是抽离的什么,相信你现在再看会有些灵感。https://www.form-create.com/v3/instance#%E7%BB%84%E4%BB%B6%E6%96%B9%E6%B3%95
redbeanzzZ
197 天前
@shilianmlxg 好的!谢谢
Charrlles
197 天前
不是说长的像就要抽象的,这种和业务相关的组件开发说了不算,得拉通产品和设计,讨论清楚到底会有几种场景几种样式,然后制定组件规范才行,不然后面产品提一个组件满足不了的需求,就傻眼了
redbeanzzZ
197 天前
@Charrlles 我知道你说的意思,我说的不是产品的那些大的组件,而是自己开发时候方便自己使用封装的组件
lDqe4OE6iOEUQNM7
197 天前
<!-- DrawerForm.vue -->
<template>
<el-drawer :visible.sync="visible" title="Form Drawer">
<header>
<slot name="header"></slot>
</header>
<div>
<slot></slot>
</div>
<footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</footer>
</el-drawer>
</template>

<script>
export default {
props: {
visible: Boolean
},
methods: {
handleSubmit() {
this.$emit('submit');
}
}
};
</script>
lDqe4OE6iOEUQNM7
197 天前
<!-- CommonFormFields.vue -->
<template>
<el-form :model="formData" :rules="rules" ref="form">
<el-form-item label="整改部门" prop="department">
<el-select v-model="formData.department" :disabled="isDepartmentDisabled">
<!-- Options -->
</el-select>
</el-form-item>
<el-form-item label="整改人" prop="person">
<el-select v-model="formData.person">
<!-- Options -->
</el-select>
</el-form-item>
<el-form-item label="计划完成时间" prop="date">
<el-date-picker v-model="formData.date" :disabled="isDateDisabled">
</el-date-picker>
</el-form-item>
</el-form>
</template>

<script>
export default {
props: {
formData: Object,
rules: Object,
isDepartmentDisabled: Boolean,
isDateDisabled: Boolean
},
methods: {
validate(callback) {
this.$refs.form.validate(callback);
}
}
};
</script>
lDqe4OE6iOEUQNM7
197 天前
具体业务:<!-- SomePage.vue -->
<template>
<div>
<el-button @click="showDrawer1 = true">Open Drawer 1</el-button>
<el-button @click="showDrawer2 = true">Open Drawer 2</el-button>

<DrawerForm :visible.sync="showDrawer1" @submit="handleFormSubmit1">
<template #header>
认领
</template>
<CommonFormFields
:formData="formData1"
:rules="rules1"
:isDepartmentDisabled="true"
:isDateDisabled="false" />
</DrawerForm>

<DrawerForm :visible.sync="showDrawer2" @submit="handleFormSubmit2">
<template #header>
指派
</template>
<CommonFormFields
:formData="formData2"
:rules="rules2"
:isDepartmentDisabled="false"
:isDateDisabled="false" />
</DrawerForm>
</div>
</template>

<script>
import DrawerForm from './DrawerForm.vue';
import CommonFormFields from './CommonFormFields.vue';

export default {
components: {
DrawerForm,
CommonFormFields
},
data() {
return {
showDrawer1: false,
showDrawer2: false,
formData1: {
department: '',
person: '',
date: ''
},
formData2: {
department: '',
person: '',
date: ''
},
rules1: {
department: [{ required: true, message: '请选择部门', trigger: 'change' }],
person: [{ required: true, message: '请选择认领人', trigger: 'change' }],
date: [{ required: true, message: '请选择日期', trigger: 'change' }]
},
rules2: {
department: [{ required: true, message: '请选择部门', trigger: 'change' }],
person: [{ required: true, message: '请选择指派人', trigger: 'change' }],
date: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
};
},
methods: {
handleFormSubmit1() {
this.$refs.form1.validate((valid) => {
if (valid) {
// 提交逻辑
}
});
},
handleFormSubmit2() {
this.$refs.form2.validate((valid) => {
if (valid) {
// 提交逻辑
}
});
}
}
};
</script>

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1047730

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX