iT邦幫忙

0

Vue 生命週期問題

  • 分享至 

  • xImage

這是一個編輯頁,編輯頁中有一個下拉選單,必須先在下拉選單選擇地區(area)之後才會出現縣市(city)checkbox,然後checkbox可以做全選功能

我的預想是

  1. getInfo抓資料庫裡的資料(methods --- getInfo)
  2. getters info (computed --- info)
  3. 之後area變動(watch --- area)
  4. 抓縣市city_list跟全選checkList的資料(methods --- getCityList)
  5. getters city_list(computed --- city)
  6. getters checkList(computed --- checkList)
  7. watchcity的值,如果city的值等於checkList的話就是全選watch --- city

但是在實作的時候4~7的順序就倒過來了(下圖是執行結果),還沒getters就先watch資料,變成watch不到值,所以沒辦法在初始的時候就勾成全選
https://ithelp.ithome.com.tw/upload/images/20230810/201616457ho3epGd88.png

想知道是哪裡出了問題

下面放程式碼

export default{
    data() {
        return {
            area: 0,
            city: [],
            checked: false,
        }
    },
    async created() {
        console.log('--- create --- ');

        // 後來修改部分
        await this.getCityList();
        this.getInfo();
    },
    computed: {
        info: function () {
            console.log('computed --- info');
            
            return this.$store.getters["admin/test/info"];
        },

        city_list: function () {
            console.log('computed --- city');
        
            return this.$store.getters["admin/city/list"];
        },
        checkList: function () {
            console.log('computed --- checkList');
            
            return this.$store.getters["admin/city/checkList"];
        },
    },
    watch: {
        'info': {
            handler(current, previous) {
                this.area = current.area;
            },
            immediate: false,
            deep: true
        },
        // 後來修改部分
        'checkList': function(val){
            console.log('watch --- checkList');
            
            if(val.length == this.city.length){
                this.checked = true;
            }else{
                this.checked = false;
            }
        },
        'area': function(){
            console.log('watch --- area');

            this.getCityList();
        },
        'city': function(val){
            console.log('watch --- city');
            
            if(val.length == this.checkList.length){
                this.checked = true;
            }else{
                this.checked = false;
            }
        },
    },
    methods: {
        getInfo(): void {
            console.log('methods --- getInfo');
            
            this.$store.dispatch("admin/test/getInfo");
        },
        getCityList(): void{
            console.log('methods --- getCityList');

            this.$store.dispatch("admin/city/getCityList", this.area);
        },
    }
}

修改後的console.log
https://ithelp.ithome.com.tw/upload/images/20230811/20161645xUXqbH91DM.png

DanSnow iT邦好手 1 級 ‧ 2023-08-11 08:48:25 檢舉
執行的順序我認為是沒有問題的,建議你看一下 ckechList 跟 city_list 的實作確定為什麼當下的狀態不合你的預期

Vue 中的 computed 是 lazy 的,這代表雖然它會知道自己用到的資料改變了,該重新計算了,它也不會真的重新計算,而是一直等到有人使用到它時才開始計算

所以你看到的 computed 的 log ,實際上是 watch 中使用到了 computed 的值當下才觸發重新計算,這點可以透過在 watch 的結尾也加上 log 確定 computed 是在 watch 的過程中被觸發的來確認
DDDo iT邦新手 5 級 ‧ 2023-08-11 12:08:04 檢舉
我修改之後在create()裡先getCityList,也在watch新增一個監聽checkList

這樣照理說,create後就會先get到city_list跟checkList,然後因為監聽了checkList(使用到了 computed 的值),應該會在methods --- getCityList後出現computed 的 log ,但實際上卻沒有compute進行,一樣在最後才進行compute(後面有補上修改後的console截圖)

雖然最後有達成我要的功能,但還是想知道為什麼會這樣,是我有地方沒理解到嗎
froce iT邦大師 1 級 ‧ 2023-08-11 16:02:06 檢舉
https://ithelp.ithome.com.tw/articles/10239545

我猜是你 immediate 設成false的原因。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友回答

立即登入回答