V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
redbeanzzZ
V2EX  ›  问与答

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

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

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

    不知道你说的"还可以复用",是指什么
    Xu3Xan89YsA7oP64
        7
    Xu3Xan89YsA7oP64  
       198 天前
    除非你说的『相似』是指类似于新增与更新这种填写内容几乎没差别的,否则没必要。
    Adyi
        8
    Adyi  
       198 天前
    参考 elementUI
    vczyh
        9
    vczyh  
       198 天前
    简单表单没必要复用,除非 FormItem 比较复杂,比如是个从接口获取的 Select List 这样才有必要复用。
    Jarme
        10
    Jarme  
       197 天前
    不要过度抽象、业务剥离、纯粹性、易用(心智负担)
    redbeanzzZ
        11
    redbeanzzZ  
    OP
       197 天前
    @shilianmlxg 我实际业务中,这个抽屉就是一个 header content footer 的结构。header 和 footer 完全一样,我拿出来携程组件了。每个按钮对应抽屉的 content 是一个表单,他们不一样,这里我把每个 content 单独拿出来写成组件。其中会有两个表单中 content 内容是一样的,但是校验不同、个别项为 disabled 无法编辑这样。
    redbeanzzZ
        12
    redbeanzzZ  
    OP
       197 天前
    @66beta 就是两个表单,比如有三个 item ,对应国家选择器、货币选择器、时间选择器,但是两个表单的校验规则不同,还有其中一个时间选择器可能是 disabled 无法选择这样。
    redbeanzzZ
        13
    redbeanzzZ  
    OP
       197 天前
    https://i2.mjj.rip/2024/06/07/18bc9ff508d25a5ac112a0d7cfd78953.png 我直接把图放出来咯,我已经把外面那个抽屉框子封好组件了。这俩表单虽然一样,但是否可编辑不同,校验规则不同,内容又这么少我还不如直接写吧?以后新需求基本也不可能再有一样表单。
    @zcf0508
    @shilianmlxg
    @66beta
    @shizhibuyu2023
    @vczyh
    shilianmlxg
        14
    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
        15
    redbeanzzZ  
    OP
       197 天前
    @shilianmlxg 好的!谢谢
    Charrlles
        16
    Charrlles  
       197 天前 via iPhone
    不是说长的像就要抽象的,这种和业务相关的组件开发说了不算,得拉通产品和设计,讨论清楚到底会有几种场景几种样式,然后制定组件规范才行,不然后面产品提一个组件满足不了的需求,就傻眼了
    redbeanzzZ
        17
    redbeanzzZ  
    OP
       197 天前
    @Charrlles 我知道你说的意思,我说的不是产品的那些大的组件,而是自己开发时候方便自己使用封装的组件
    lDqe4OE6iOEUQNM7
        18
    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
        19
    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
        20
    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>
    vczyh
        21
    vczyh  
       193 天前
    校验规则不一样就别强求写到一起,我个人觉得前端需求比较复杂,容易发生变化,多使用组合,比如组件复用不太容易满足的时候,可以往更细的方面去做复用,比如用户选择,<Select/> 不好做成复用的话,可以做一个更细致的 useUsers hook ,这样数据有了,做一个新组件也很容易,用户列表都可以用这个 hook 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2735 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 10:02 · PVG 18:02 · LAX 02:02 · JFK 05:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.