美文网首页前端大杂烩
如何封装一个vue v-model语法糖

如何封装一个vue v-model语法糖

作者: 写写而已 | 来源:发表于2022-10-18 22:49 被阅读0次

    此项目基于element-ui,意在封装可创建目录的下拉框,返回数组形式的值
    主页面

    <template>
    <div id="app">
        <model-select v-model="form.datas"></model-select>
        <el-button @click="show">show</el-button>
        <router-view/>
    </div>
    </template>
    <script>
    import modelSelect from './model-select.vue'
    export default {
        components: { modelSelect },
        data() {
            return {
                form: {
                    datas: [{
                        key: '101',
                        value: '马化腾'
                    }, {
                        key: '102',
                        value: '李彦宏'
                    }]
                }
            }
        },
        methods: {
            show() {
                console.log(this.form.datas)
            }
        }
    }
    
    </script>
    

    子组件model-select.vue

    <template>
        <el-select @change="change" v-model="selVal" multiple collapse-tags filterable allow-create default-first-option placeholder="请选择">
            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
        </el-select>
    </template>
    <script>
    export default {
        props: ['value'],
        data() {
            return {
                selVal: [],
                options: []
            }
        },
        methods: {
            change(vals) {
                this.options = vals.map(item => {
                    return {
                        key: this.findIdByName(item),
                        value: item
                    }
                })
                this.$emit('input', this.options)
            },
            /** 从历史数据中找到原有id */
            findIdByName(name) {
                let obj = this.value.find(item => item.value === name)
                return obj ? obj.key : undefined
            }
        },
        watch: {
            "value": {
                handler(vals) {
                    if(vals) {
                        this.options = JSON.parse(JSON.stringify(vals))
                        this.selVal = vals.map(item => item.value)
                    }
                },
                deep: true,
                immediate: true
            }
        }
    }
    </script>
    <style lang="scss">
    
    运行结果

    看起来已经满足需求,如果用计算属性好像更简便一点

    <template>
        <el-select @change="change" v-model="selVal" multiple collapse-tags filterable allow-create default-first-option placeholder="请选择">
            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
        </el-select>
    </template>
    <script>
    export default {
        props: ['value'],
        data() {
            return {
                selVal: [],
            }
        },
        computed: {
            options() {
                return this.selVal.map(item => {
                    return {
                        key: this.findIdByName(item),
                        value: item
                    }
                })
            }
        },
        methods: {
            change(vals) {
                this.$emit('input', this.options)
            },
            /** 从历史数据中找到原有id */
            findIdByName(name) {
                let obj = this.value.find(item => item.value === name)
                return obj ? obj.key : undefined
            }
        },
        watch: {
            value: {
                handler(vals) {
                    if(vals) {
                        this.selVal = vals.map(item => item.value)
                    }
                },
                deep: true,
                immediate: true
            }
        }
    }
    </script>
    

    相关文章

      网友评论

        本文标题:如何封装一个vue v-model语法糖

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