VUE 开发求助 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
andyshz
V2EX    Vue.js

VUE 开发求助

  •  
  •   andyshz 69 天前 3401 次点击
    这是一个创建于 69 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问 VUE 佬们在开发大表单的时候怎么设计绑定对象的?直接在 data 中声明所有表单项来绑定吗?那岂不是会有很多冗余代码?而且如果多个组件都使用这个对象,对象在传递的时候是不是每个组件中又需要声明一次? 刚从后端学习前端,希望能有大哥指点指点,按照后端的逻辑,这个表单不是应该设计为一个对象,每个组件直接复用对象即可,传递也传递对象,但是现在开发过程中出现不少问题,搜了之后好像说不能绑定 js 的类对象。。。。。。

    18 条回复    2025-08-01 11:40:06 +08:00
    lyonbot
        1
    lyonbot  
       69 天前 via Android
    你需要的是不是 store 或者说是全局状态管理?
    andyshz
        2
    andyshz  
    OP
       69 天前
    并不全是吧,主要我只想要这个对象在一个模块中使用,并且希望做到的就是尽可能地减少冗余代码,我对这一块地设计不是很熟悉
    VUEX 和 PINIA 可以是模块级的吗
    Dlad
        3
    Dlad  
       69 天前
    1 、可以全局声明;
    2 、每个页面都声明一次,代码冗余了,因为做到了按需加载,程序执行效率反而更好。
    3 、我们项目中的实践是:element ui 打底,常用类型不自行开发了;复杂业务逻辑字段,定制成组件(我好兄弟用自己名字命名的组件,开始看着头痛,后来习惯了);整个表单需要复用,全局弹出呼出表单、逻辑全复用了。
    4 、有些变量,全局各处展示需要实时更新的,放在 pinia store 里面。

    我不是职业搞前端的,对最佳实践了解有限。我们自研的 vue 项目按一般软件工程逻辑优化到这个程度。
    M003
        4
    M003  
       69 天前
    方法 1. 父级声明出大对象,然后 v-model 将整个大对象 绑定到子组件;子组件内可以定义变量,也可以不声明变量,子组件可以监听到父组件传递给子组件的 value, 然后深拷贝覆盖子组件声明的变量(未声明直接赋值,当然必须声明个变量是 undefined ), 修改这个变量,监听变量变化,$emit 传递出去给父组件。

    方法 2. 父组件声明出大对象,对象结构明确。给每个子组件只传递需要的对象中的参数,只修改父组件对象中的某个参数,这样不方便于别的组件读取其他变量。(传递方法和上面一样。)


    就不用 store 了。

    我这是野路子,自己写代码摸索的。
    Elissa
        5
    Elissa  
       69 天前
    data 中一般放一个 form 对象,内部属性对应每个表单内容
    ```js
    data: {
    form: {
    name: undefine,
    age: undefine,
    ......
    }
    }
    ```

    优先用组件库的表单组件,这样直接 v-model 绑定 form.xxx 到组件库的组件上

    如果需要复杂填写,通过传参或将 form.xxx 传入自定义组件,组件内部自行实现 v-model 或通过事件总线修改值
    hafuhafu
        6
    hafuhafu  
       69 天前
    工厂模式。你可以写一个函数用来生成这个对象,而不是直接定义对象。
    SaigyoujiNono
        7
    SaigyoujiNono  
       69 天前 via Android
    我一般 export form
    然后 form: { ...form }
    wangtian2020
        8
    wangtian2020  
       69 天前
    多层数据传递直接扔 pinia store 里,组件要的时候自己去取,想当于一个全局共享的 ref 对象。单层就随便传传了,看你自己怎么方便,不要教条
    我甚至单层传递都不用 props 传,我用 ref 调用组件主动 expose 的方法,用方法传参一次性传递。
    watch props 的操作我觉得很蠢
    layxy
        9
    layxy  
       69 天前
    我也是后端,如果页面复杂,尤其有分步操作,建议上状态管理(vue2 的 vuex 或 vue3 的 pinia),但是使用状态管理也有个操蛋的事情,状态读数据和写数据时分开的,虽然可以在 computed 中 get,set,但是这个机制我没搞明白如果获取的对象是个复杂嵌套对象,我修改深层的属性值,这种用法是否正确
    heybwei
        10
    heybwei  
       69 天前
    其实你的问题描述得不是让人很明白,如果能贴一些大概的结构或伪代码就好了
    chenluo0429
        11
    chenluo0429  
       69 天前 via Android
    如果你有一个大的表单对象,有很多字段,然后需要用不同的表单组件去提供对应字段的编辑,正确的实践是子组件只关注它要显示和修改的字段值,并不需要关心原生的大对象。
    如果每个子组件都要关注原生的对象的话,应当用 provide/inject 实现局部的状态共享。如果状态是全局唯一的话,也可以使用 pinia 这种全局状态管理去做。
    faceRollingKB
        12
    faceRollingKB  
       69 天前
    表单设计不建议使用 vuex 或 pinia ,这两个都是用来管理全局变量的,管理局部模块化数据的话就有点吃力,我是使用 vue 自带的 providers ,再根据自己的想法封装了一套依赖注入来实现的,整体表单通过 FormModel 管理数据和表单项配置,并共享给整个组件树,每个表单项也都有专门的 FormControl 来对接表单的各种操作,但是从 0 到 1 的成本有点高,你要有心理准备
    SchwarzeR
        13
    SchwarzeR  
       69 天前
    vue3 如果需要局部状态管理,业务上存在大量复用有必要封装的话,并且不需要考虑 ssr 的情况下,可以通过声明一个 Composition api 的函数( hook )做一个局部的变量初始化,然后用在需要的地方。这个在 https://cn.vuejs.org/guide/reusability/composables 亦有记载

    但是如果会涉及到 ssr 的话,pinia 也可以做局部的模块化声明,就是麻烦一点
    ```
    // 需要传参根据情况改变内容上的时候就给函数加参数
    function useXXXFormData() {

    const OnShow= ref(true)

    const formCOntextState= reactive({
    xxx:12123,
    xxl:123,
    process:123,
    onSync: false
    })

    // 内部使用 vue 的生命周期 api 比如销毁时清理
    onBeforeUnmount(() => {
    console.log("unmounted!");

    })


    return {
    onShow,
    formContextState
    }
    }
    ```
    直接拿代码给你比方?
    在需要拿来初始化调用的时候直接
    const formstate = useXXXFormData()

    不知道我理解的正确不正确
    faceRollingKB
        14
    faceRollingKB  
       69 天前
    示例:

    <script setup lang="ts">
    const form = Provide(FormModel<TData>);
    form.mode = FormMode.edit;
    form.items = [
    describeControl({
    type: controlWrap('t-input'),
    label: 'xxx:',
    prop: 'yyy',
    value: '',
    validator: [FormValidator.required, FormValidator.max(50)],
    options: {
    placeholder: '请输入 xxx'
    }
    }),
    ];
    form.resetData();
    function onConfirm() {
    form
    .validate()
    .then(() => {
    return service.save(form.data);
    })
    .then(() => {
    MessagePlugin.success('操作成功');
    })
    .catch((err) => {
    MessagePlugin.error(err?.message || err);
    });
    };
    </script>

    <template>
    <div v-if="form.data" v-grid.form="2" class="ph-20 gr-24 gc-12 mb-24">
    <q-form-item prop="aaa"></q-form-item>
    <q-form-item prop="bbb"></q-form-item>
    <q-form-item v-if="form.data.bbb === '???'" prop="ccc"></q-form-item>
    <q-form-item prop="ddd"></q-form-item>
    </div>
    </template>

    <style scoped lang="less"></style>
    chobitssp
        15
    chobitssp  
       69 天前
    class + ref
    xingyuc
        16
    xingyuc  
       69 天前
    不同场景不同用法,写的再优雅也抵不过 AI 的冲击
    jspatrick
        17
    jspatrick  
       69 天前
    页面声明大对象,再 provide/inject ,跨页面考虑 store
    wentx
        18
    wentx  
       69 天前
    vibe 了。。 也不知道 cursor 是咋写的,但是能用
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2825 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 13:35 PVG 21:35 LAX 06:35 JFK 09:35
    Do have faith in what you're doing.
    ubao 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