element-ui中select下拉框,選擇后賦值成功,但是框上不顯示的坑


這個是今天遇到一個坑,因為也是第一次使用vue+element-ui開發,所以記錄一下自己遇到的一些問題。
這個問題是在開發省市區三級聯動組件的時候遇到的,具體的情況如下發的gif圖,雖然解決了問題,但是還是沒有懂是為什么這樣,有人說是element的bug,不過我覺得不像,可能是用法的問題吧,希望知道原因的博友們可以告知,現在先上下代碼;

1.首先address.json的格式是:

[
{ "name": "北京", "city":[{"name":"北京", "area":["東城區","西城區","崇文區","宣武區","朝陽區","豐台區","石景山區","海淀區","門頭溝區","房山區","通州區","順義區","昌平區","大興區","平谷區","懷柔區","密雲縣","延慶縣"]}]},

{ "name": "天津", "city":[{"name":"天津", "area":["和平區","河東區","河西區","南開區","河北區","紅橋區","塘沽區","漢沽區","大港區","東麗區","西青區","津南區","北辰區","武清區","寶坻區","寧河縣","靜海縣","薊  縣"]}]}
]

1.然后就是組件的代碼了,功能很簡單,也加了一些注釋

<template>
    <div class="ad-box">
        <el-select v-model="province" placeholder="選擇省" style="width: 150px;">
            <el-option :label="item.name" @click.native="provinceChange(item)" :key="item.name" v-for="item in data" :value="item.name"></el-option>
        </el-select>
        <el-select v-model="city" placeholder="選擇市" style="width: 150px;">
            <el-option :label="item.name" v-for="item in citylist" @click.native="cityChange(item)" :key="item.name" :value="item.name"></el-option>
        </el-select>
        <el-select v-model="area" placeholder="選擇區/鄉鎮" style="width: 150px;">
            <el-option :label="item" @click.native="emitData" v-for="item in arealist" :key="item" :value="item"></el-option>
        </el-select>
    </div>
</template>
<script>
    // 獲取地址JSON
    import addressJSON from './address.json';
    export default {
        data() {
            return {
                onecetime: true,
                province: '',
                city: '',
                area: '',
                data: addressJSON,
                citylist: [],
                arealist: [],
            }
        },
        props: {
            address: {
                type: Object,
                default: function () {
                    return { 
                        province: '',
                        city: '',
                        area: ''
                    }
                }
            }
        },
        watch: {
            'address.province': function(val, oldVal) {
                if (val && this.onecetime) {
                    this.data.map(item => {
                        if (item.name == this.address.province) {
                            this.citylist = item.city;
                            if (this.address.city) {
                                this.citylist.map(item => {
                                    if (item.name == this.address.city) {
                                        this.arealist = item.area;
                                    }
                                })
                            }
                            return false;
                        }
                    })

                    this.area = this.address.area;
                    this.city = this.address.city;
                    this.province = this.address.province;

                    this.onecetime = false;
                }
            },
        },
        // 通過默認值獲取初始的三欄下拉列表
        created() {
            this.area = this.address.area;
            this.city = this.address.city;
            this.province = this.address.province;
        },
        methods: {
            // 選擇省份后清空市和區
            provinceChange(item) {
                this.city = '';
                this.area = '';
                this.getList('citylist', item, 'city')
                this.emitData();   //因為需求是可以不用填寫完整的,所以每填一欄上傳一次結果
            },
            // 選擇市后情況區/縣
            cityChange(item) {
                this.area = '';
                this.getList('arealist', item, 'area')
                this.emitData();
                    
            },
            // 聯動獲取下一欄中的選項列表,參考地址的JSON格式
            getList(prop, data, name) {
                this[prop] = data[name];
            },
            // 向父級組件發送自定義事件,提交選擇結果
            emitData() {
                let data = {
                    province: this.province,
                    city: this.city,
                    area: this.area
                };
                this.$emit('getAddress', data);
            }
        }
    }
</script>
<style scoped lang="scss">
    .ad-box {
        display: inline-block;
    }
</style>

1.組件的使用方式:

//先注入組件后:
<address3 @getAddress="changeAddress" :address="{province: '福建', city: '漳州', area: '薌城區'}"></address3>

其實是很簡單的一個組件,為什么要寫這博客記錄呢,其實就是跟標題說的一樣,element-ui中的select的賦值問題:

如果 el-select 上 v-model="" 綁定的這個字段沒有事先定義好的話,而且你的option是通過請求到的數組v-for出來的話(如果option是寫死的就不會有這個問題),就會出現選擇后,select元素上無法展示,但是其實數值已經綁定上去了的后果

舉個例子:
比如 我有個 用戶信息編輯頁面, this.info通過請求獲取, banklist也是通過請求獲取銀行列表的

 <el-select v-model="info.bankId" placeholder="選擇開戶銀行">
    <el-option :label="item.bankName" :key="item.bankId" v-for="item in banklist" :value="item.bankId"></el-option>
</el-select>
//這時候,就會出現標題上的坑,選擇選項后,從vue dev-tools看發現值已經賦進去了,但是select上就是不顯示選中的label
//處理的方法還是 在 data中事先申明一個屬性,不要再v-model中綁定不存在的屬性就不會出現這種情況,但是現實開發中這樣又很麻煩,要多賦值一遍

2017.08.30:
回復之前的賦值無效的問題,因為之前的方式是從props拿到值后,就直接賦值給對應的屬性,但是當props是異步請求回去的,那么他的第一次的值就為我們定義的初始值,沒定義就是undefined,等異步親貴回來之后,它早在第一次的時候,就把初始值賦值過了,請求回來后不再執行賦值了,所以就賦值不了返回后的結果,現已更改為使用watch來監聽props的改變,這里有個注意點:props綁定的父級屬性不能是返回結果后改變的屬性,比如說
···
<address @success="callback" :address="defaultVal">

//父級methods中
callback(val) {
    this.defaultVal = val;     //這樣是不對的, 因為你再子組件中watch了address相當於是defaultVal,如果你再callback中講子組件傳過來的值又賦值回去給defaultVal,就相當於又觸發了watch,
    this.addressVal = val;   //這樣才對。
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM