前端大杂烩

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

2022-10-18  本文已影响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>
上一篇下一篇

猜你喜欢

热点阅读