computed property set not called in Vue

后端 未结 6 2071
没有蜡笔的小新
没有蜡笔的小新 2021-01-11 16:19

According to the documentation I should be able to use computed properties as v-model in Vue as long as I define get/set methods, but in my case it doesn\'t wor

6条回答
  •  不知归路
    2021-01-11 17:25

    Edit: After reading in the comments that you rely on the localstorage, I can only suggest you to take the Vuex approach and use a persistence library to handle the localstorage. (https://www.npmjs.com/package/vuex-persist) This way, your localstorage will always be linked to your app and you don't have to mess with getItem/setItem everytime.

    Looking at your approach, I assume you have your reasons to use a computed property over a data property.

    The problem happens because your computed property returns an object defined nowhere but in the get handler. Whatever you try, you won't be able to manipulate that object in the set handler.

    The get and set must be linked to a common reference. A data property, as many suggested, or a source of truth in your app (a Vuex instance is a very good example).

    this way, your v-model will work flawlessly with the set handler of your computed property.

    Here's a working fiddle demonstrating the explanation:

    With Vuex

    const store = new Vuex.Store({
      state: {
        // your options object is predefined in the store so Vue knows about its structure already
        options: {
          isChecked: false
        }
      },
      mutations: {
        // the mutation handler assigning the new value
        setIsCheck(state, payload) {
          state.options.isChecked = payload;
        }
      }
    });
    
    new Vue({
      store: store,
      el: "#app",
      computed: {
        options: {
          get() {
            // Here we return the options object as depicted in your snippet
            return this.$store.state.options;
          },
          set(checked) {
            // Here we use the checked property returned by the input and we commit a Vuex mutation which will mutate the state
            this.$store.commit("setIsCheck", checked);
          }
        }
      }
    })
    body {
      background: #20262E;
      padding: 20px;
      font-family: Helvetica;
    }
    
    #app {
      background: #fff;
      border-radius: 4px;
      padding: 20px;
      transition: all 0.2s;
    }
    
    h2 {
      font-weight: bold;
      margin-bottom: 15px;
    }

    isChecked: {{ options.isChecked }}

    With a data property

    new Vue({
      el: "#app",
      data: {
        options: {
          isChecked: false
        }
      },
      computed: {
        computedOptions: {
          get() {
            return this.options;
          },
          set(checked) {
            this.options.isChecked = checked;
          }
        }
      }
    })
    body {
      background: #20262E;
      padding: 20px;
      font-family: Helvetica;
    }
    
    #app {
      background: #fff;
      border-radius: 4px;
      padding: 20px;
      transition: all 0.2s;
    }
    
    h2 {
      font-weight: bold;
      margin-bottom: 15px;
    }

    isChecked: {{ computedOptions.isChecked }}

    Your approach is a bit special IMHO but, again, you must have your reasons to do so.

提交回复
热议问题