美文网首页
vue element ui动态表单国际化问题解决方案

vue element ui动态表单国际化问题解决方案

作者: 码农梦醒 | 来源:发表于2021-06-10 06:51 被阅读0次

    问题概述

    基于element ui做了一个动态表单组件(根据配置,自动生成表单), 本来一切功能正常, 但由于项目需要支持国际化, 本来以为只是简单引入vue-i18n就行了, 没想到在国际化切换时, 表单的label, rule,placeholder并未同时切换

    问题原因

    自定义配置的label,placeholder和rule属性是纯粹的字符串和数组类型, 也就是说, 配置一旦创建, 实际上已经不具备自动响应式的能力. 那么解决方案就是让label, rule,placeholder能够在语言切换时, 进行自动响应, 从而重新生成对应值

    网上找到的解决办法

    方案一: 将rules或label等单独定义到computed中, 这样当国际化切换时, 会自动重新计算. 可行, 但会造成配置割裂, 原来的动态表单组件, 也会需要进行较大工作量的重构

    方案二: 监听语言变更, 手动更新表单配置信息. 理论上也是可行的, 但会增加很多的编程量

    这一刻陷入了僵局。难道就没有一个更好的方案?

    想起以前做angular项目也需要国际化支持, 用的好像是ng-zero, 国际化切换时, ng-zero的表头, 并未跟着一起切换(那时也是通过配置方式生成表,表头名称字段也是定义的字符串). 后来将表头名称字段改成了函数, 问题解决。vue是不是也可以用这种方式? 想到就试试. 最后验证通过, 果然是可以的.

    我的最终解决方案

    将需要国际化支持的配置, 都改为即能传入Function又能传入字符串

    • 传字符串用于普通的不需要国际化支持的情况, 简化配置编写
    • 传Function是用于需要国际化的情况

    简化代码如下:

    SimpleForm

    <template>
        <div>
            <el-form :model="ruleForm" ref="ruleForm" label-width="100px" :rules="realRules" class="demo-ruleForm"
                     v-if="editable">
                <el-form-item label="名称" prop="name">
                    <el-input v-model="ruleForm.name"></el-input>
                </el-form-item>
                <el-form-item label="爱好" prop="hobby">
                    <el-select v-model="ruleForm.hobby" placeholder="请选择">
                        <el-option
                                v-for="item in options"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
            </el-form>
            <ul v-else>
                <li>名称:{{ruleForm.name}}</li>
                <li>爱好:{{ruleForm.hobby}}</li>
                <li>年龄:{{ruleForm.age}}</li>
            </ul>
        </div>
    </template>
    
    <script>
        export default {
            name: "SimpleForm",
            components: {},
            created() {
            },
            props: {
                editable: {
                    type: Boolean,
                    default: false
                },
                data: {
                    type: Object,
                    default: () => {
                        return {}
                    }
                },
                rules: {
                    type: Object,
                    default: () => {
                        return {}
                    }
                },
                options: {
                    type: Array,
                    default: () => {
                        return []
                    }
                }
            },
            data() {
                return {
                    ruleForm: {...this.data},
                    // 最近的正确的表单数据
                    lastFormData: {...this.data},
                    realRules: {...this.rules},
                    realOptions: []
                };
            },
            watch: {
                data(newVal) {
                    console.log('data发生变化')
                    this.ruleForm = {...newVal}
                    this.lastFormData = {...newVal}
                },
                rules(newVal) {
                    console.log('rules发生变化')
                    this.realRules = {...newVal}
                },
                options(newVal) {
                    console.log('options发生变化')
                    this.realOptions = [...newVal]
                }
            },
            methods: {
                validateFormDataNotChange() {
                    if (this.ruleForm.name === this.lastFormData.name && this.ruleForm.hobby === this.lastFormData.hobby) {
                        // 没改
                        return {notChanged: true};
                    }
                    // 改了
                    return {notChanged: false, lastFormData: this.lastFormData};
                },
                submitForm(formName = 'ruleForm') {
                    return new Promise((reslove) => {
                        this.$refs[formName].validate((valid) => {
                            if (valid) {
                                reslove(this.ruleForm)
                            } else {
                                console.log('error submit!!');
                                return false;
                            }
                        });
                    })
                },
                resetForm(formName = 'ruleForm') {
                    this.$refs[formName].resetFields();
                },
                handleCusEvt() {
                    this.$refs['ruleForm'].validateField('org');
                }
            }
        }
    </script>
    
    <style scoped>
    
    </style>
    
    
    <template>
        <div class="hello">
            <el-button @click="editable=!editable">切换</el-button>
            <simple-form :data="data" :editable="editable" :field-config-arr="fieldConfigArr"></simple-form>
        </div>
    </template>
    
    <script>
        import SimpleForm from "@/components/SimpleForm";
    
        export default {
            name: "HelloWorld",
            components: {
                SimpleForm
            },
            props: {
                msg: String
            },
            data() {
                return {
                    i18nMsg: {
                        i18nVal: () => this.$t('lang')
                    },
                    data: {},
                    editable: true,
                    fieldConfigArr: [
                        {
                            prop: 'name',
                            label: () => this.$t('name'),
                            rules: () => [{required: true, message: this.$t('mustInput'), trigger: 'blur'}],
                            placeholder: () => this.$t('placeholder')
                        },
                        {
                            prop: 'age',
                            label: this.$t('age'),
                            rules: [{required: true, message: this.$t('mustInput'), trigger: 'blur'}],
                            placeholder: this.$t('placeholder')
                        }
                    ]
                }
            }
        };
    </script>
    
    <style scoped lang="scss">
    </style>
    

    上面的例子中, 姓名配置用的是Function, 年龄配置用的是字符串, 所以,姓名的相关信息, 是能完全支持国际化的, 年龄就不行了.

    相关文章

      网友评论

          本文标题:vue element ui动态表单国际化问题解决方案

          本文链接:https://www.haomeiwen.com/subject/qxfqeltx.html