天天看點

關于重寫 v-model 的一點感想

最近使用element-ui開發時總有一個問題困擾着我。

當時要寫一個遠端搜尋選擇框元件, 這個元件關聯了一個後端的接口, 将後端傳回的值映射到,綁定的對象上,

代碼類似

<template>
    <el-select remote :remote-method="getList" v-model="foo.name"  key-value="name">
        <el-option v-for="item in list" :value="item" :label="item.name"/>
    </el-select>
</template>

<script>
    export default {
        data() {
            return {
                list: [],
                foo: {
                    name: '',
                    gender: '',
                    email: '',
                    ...
                }
            }
        },
        methods: {
            async getList(searchWord) {
                const list = await get(searchWord)
                // 傳回的 list 的每一項的結構類似foo, 但有差別, 包含一些必要的資訊.
                this.list = list
            }
        }
    }
<script>


           

注意: 我将 option的value值綁定成了一個對象, 而 foo.name 本來是字元串, 這樣的後果就是, 每次使用者點選選擇後 foo.name就會變為對象, 對後續的儲存造成了不友善,也破壞了原來的資料結構, 但如果不這麼做,又無法拿到使用者選擇項對應的所有的資料.這樣就造成了一個兩難的境地.

好在vue在文檔中指出 v-model 實際就是vue封裝的文法糖.看這裡

<input v-model="bar">
           

相當于

<input :value="bar" @input="bar=arguments[0]">

           

是以我對程式做了如下的修改:

<template>
    <el-select remote :remote-method="getList" :value="foo.name" @input="handleSelect(arguments[0])">
        <el-option v-for="item in list" :value="item.name" :key="item.name" :label="item.name"/>
    </el-select>
</template>

<script>
    export default {
        data() {
            return {
                list: [],
                foo: {
                    name: '',
                    gender: '',
                    email: '',
                    ...
                },
                bar: null
            }
        },
        methods: {
            async getList(searchWord) {
                const list = await get(searchWord)
                this.list = list
            },
            handleSelect(val) {
                this.foo.name = val.name
                // 在input事件回調中将使用者選中的對象指派給一個準備好的變量
                // 這樣就既可以拿到想要的對象又不會破壞 foo 對象原有的結構
                this.bar = val
            }
        }
    }
<script>
           

通過自定義 v-model 解決了一個常見到的小問題, 希望能給遇到相同問題的小夥伴一點幫助.

繼續閱讀