请教一个前端写组件拆分的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
redbeanzzZ
V2EX    问与答

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

  •  
  •   redbeanzzZ 2024-06-07 16:02:33 +08:00 1528 次点击
    这是一个创建于 566 天前的主题,其中的信息可能已经有所发展或是发生改变。
    用 vue 写前端业务时候,我经常会遇到什么内容需要提出来写组件的问题。如果业务中这个组件比较复杂,复用性高,我肯定会把他拿出来写个组件复用。
    我现在有一个场景想问下大家会怎么写:一个列表页有多个按钮,都是展开一个抽屉进行表单填写的,一共有七八个按钮。我把抽屉的框架拿出来写个组件(比如标题,确认框这样),内部的表单内容再根据业务不同单个文件引入。同事认为这七八个表单有两三个还有相似的地方,还是可以复用,还要继续把相似的表单继续拿出来写个组件用。

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

    不知道你说的"还可以复用",是指什么
    Xu3Xan89YsA7oP64
        7
    Xu3Xan89YsA7oP64  
       2024-06-07 17:29:50 +08:00
    除非你说的『相似』是指类似于新增与更新这种填写内容几乎没差别的,否则没必要。
    Adyi
        8
    Adyi  
       2024-06-07 17:30:42 +08:00
    参考 elementUI
    vczyh
        9
    vczyh  
       2024-06-07 17:55:55 +08:00
    简单表单没必要复用,除非 FormItem 比较复杂,比如是个从接口获取的 Select List 这样才有必要复用。
    jim1874
        10
    jim1874  
       2024-06-07 18:09:59 +08:00
    不要过度抽象、业务剥离、纯粹性、易用(心智负担)
    redbeanzzZ
        11
    redbeanzzZ  
    OP
       2024-06-07 18:40:59 +08:00
    @shilianmlxg 我实际业务中,这个抽屉就是一个 header content footer 的结构。header 和 footer 完全一样,我拿出来携程组件了。每个按钮对应抽屉的 content 是一个表单,他们不一样,这里我把每个 content 单独拿出来写成组件。其中会有两个表单中 content 内容是一样的,但是校验不同、个别项为 disabled 无法编辑这样。
    redbeanzzZ
        12
    redbeanzzZ  
    OP
       2024-06-07 18:42:19 +08:00
    @66beta 就是两个表单,比如有三个 item ,对应国家选择器、货币选择器、时间选择器,但是两个表单的校验规则不同,还有其中一个时间选择器可能是 disabled 无法选择这样。
    redbeanzzZ
        13
    redbeanzzZ  
    OP
       2024-06-07 18:55:09 +08:00
    https://i2.mjj.rip/2024/06/07/18bc9ff508d25a5ac112a0d7cfd78953.png 我直接把图放出来咯,我已经把外面那个抽屉框子封好组件了。这俩表单虽然一样,但是否可编辑不同,校验规则不同,内容又这么少我还不如直接写吧?以后新需求基本也不可能再有一样表单。
    @zcf0508
    @shilianmlxg
    @66beta
    @shizhibuyu2023
    @vczyh
    shilianmlxg
        14
    shilianmlxg  
       2024-06-07 23:14:57 +08:00
    @redbeanzzZ #12 你可以看下动态表单 form 低代码的文档,看下人家是抽离的什么,相信你现在再看会有些灵感。https://www.form-create.com/v3/instance#%E7%BB%84%E4%BB%B6%E6%96%B9%E6%B3%95
    redbeanzzZ
        15
    redbeanzzZ  
    OP
       2024-06-07 23:49:23 +08:00
    @shilianmlxg 好的!谢谢
    Charrlles
        16
    Charrlles  
       2024-06-08 01:50:14 +08:00 via iPhone
    不是说长的像就要抽象的,这种和业务相关的组件开发说了不算,得拉通产品和设计,讨论清楚到底会有几种场景几种样式,然后制定组件规范才行,不然后面产品提一个组件满足不了的需求,就傻眼了
    redbeanzzZ
        17
    redbeanzzZ  
    OP
       2024-06-08 02:48:15 +08:00
    @Charrlles 我知道你说的意思,我说的不是产品的那些大的组件,而是自己开发时候方便自己使用封装的组件
    lDqe4OE6iOEUQNM7
        18
    lDqe4OE6iOEUQNM7  
       2024-06-08 17:03:26 +08:00
    <!-- 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
        19
    lDqe4OE6iOEUQNM7  
       2024-06-08 17:03:50 +08:00
    <!-- 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
        20
    lDqe4OE6iOEUQNM7  
       2024-06-08 17:05:17 +08:00
    具体业务:<!-- 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>
    vczyh
        21
    vczyh  
       2024-06-12 10:59:20 +08:00
    校验规则不一样就别强求写到一起,我个人觉得前端需求比较复杂,容易发生变化,多使用组合,比如组件复用不太容易满足的时候,可以往更细的方面去做复用,比如用户选择,<Select/> 不好做成复用的话,可以做一个更细致的 useUsers hook ,这样数据有了,做一个新组件也很容易,用户列表都可以用这个 hook 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2671 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 15:10 PVG 23:10 LAX 07:10 JFK 10:10
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86