Vue 響應式短文

故事前言

工作碰上一個問題,就是我在模擬一份資料。這份資料長度不明,但我會需要自己新增屬性。問題在於,如果我想更改狀態,啥都沒有。因為想先快回家,所以這個問題只好留著不解決(我的頭……)。

你怎麼了?

程式如下:

<div v-for="(odd, idx) in i.odds">
    <div id="app" v-bind:class="{ active : foobar( input ) , box : true }">
        <div v-on:click="fbz( input )"> <!-- active -->
            <p> {{ idx + 1 }} </p>
            <p class=""> {{ odd }} </p>
        </div>
    </div>
</div>

var app =  new Vue({
    el:"#app",
    data: { odds:[] },
    methods: {
        foobar: function(x,y){},
        fbz: function(x,y){}
    },
    computed: {
        other_methods: function(x,y){}
    },
    mounted: function() {
        // AJAX
        app.odds = AJAX.recived;
        app.odds.forEach( (el,idx) => { app.odds[idx].b = false; } )
    }
});
/*
    我想透過點選 fbz 函式變換 #app 的 input 狀態,再透過 .active 參照 #app 的狀態。
    但是我發現 .active 無論選 fbz 還是 other_methods 如何都不會變動……
*/

回去看資料,發現有人想用 watch 解決。不過我看不懂程式碼,所以決定先放著。

直到我看見 Github 的某人提出 issue 才發現曙光。

簡單來說,你有什麼發現?

關鍵字是 Reactivity。解法是 .$set

所以我說為什麼?

問題是在「自己新增屬性」這點,因為 Vue「不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property。)」。所以我想透過 mounted 新增屬性會變得徒勞無功。

另外我也很好奇:Vue 官方說明之所以有這麼詭異的問題,是「受现代 JavaScript 的限制 (以及废弃 Object.observe)」。但,那個「限制」是什麼?可能要看 getter setter 了。

那怎麼辦?

mounted 新增屬性時設定 .$set。上例就是改為 app.odds.forEach( (el,idx) => { this.$set( this.odds[idx] , 'b', false); )

mounted: function() {
    // AJAX
    app.odds = AJAX.recived;
    app.odds.forEach( (el,idx) => { this.$set( this.odds[idx] , 'b', false); } )
}

後記

幹,我頭超級痛。我覺得我好像要看醫生。

20180701 增筆

我想起有人告訴我:「你可以用 computed 實例,這樣的話就能響應了。」——但是我最後沒有採用 computed 實例,理由是 computed 實例無法傳送參數。這樣的話 computed 對上例就無能為力。

可以看看 Stack Overflow 還有 Laracasts 上面的回答。

參考資料