首页 > 解决方案 > 自定义 vue 组件不会在值更改时更新

问题描述

我在https://codepen.io/james-hudson3010/pen/QWgarbr有一个代码笔,它演示了这个问题。

我正在尝试基于使用 v-btn 和 v-icon 创建和使用自定义复选框组件。

当我点击复选框时,我得到了输入事件并且数据发生了变化,但复选框的外观没有改变。我确定这是因为我调用获取值的方法不是“反应式”的。因此,在值更改时,不会重新渲染。

我需要调用一个方法来获取值,因为获取值可能很复杂,并且取决于单击了哪个框。有未知数量的盒子。

但是,我在这里缺少一些基本概念,但我不确定它是什么。

我需要在我的代码中进行哪些更改才能使其正常工作?

(不,我不想使用 v-checkbox ......在某种程度上,这是为了我自己对如何创建这些东西的启发。)

Javascript

Vue.component('mybox', {
    props: ['value'],

    data() {
      return  {
        selected: null,
      }
    },
  
    template: `
        <v-btn v-if="value" @click="clicked()" icon dense>
          <v-icon color="#f9a602">check_box</v-icon>
        </v-btn>
        <v-btn v-else @click="clicked()" icon dense>
          <v-icon color="#f9a602">check_box_outline_blank</v-icon>
        </v-btn>
    `,

    methods: {
      clicked() {
        console.log( "clicked", this.selected, this.value );
        this.selected = !this.value;
        console.log( "clicked", this.selected, this.value );
        this.$emit( "input", this.selected );
      }
    },

    watch: {
      selected() {
        console.log("selected:", this.selected);
        // this.$emit("input", this.selected);
      },
  }
});


new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  
  data: {
    boxvalues: [true, false],
  },
  
  methods: {
    boxValueChanged( index ) {
      console.log( "boxValueChanged", index, this.boxvalues[ index ] );
      this.boxvalues[ index ] = !this.boxvalues[ index ];
      console.log( "boxValueChanged", index, this.boxvalues[ index ] );
    },
    
    boxValue( index ) {
      return this.boxvalues[ index ];
    }
  },
})

HTML

<div id="app">
  <mybox v-for="(value, index ) in boxvalues" 
         :value="boxValue( index )" 
         @input="boxValueChanged( index )"
         :key="index"
         :id="index"/>
</div>

标签: vue.jsvue-component

解决方案


你是正确的,罪魁祸首是这条线的反应性丧失:

this.boxvalues[index] = !this.boxvalues[ index ];

从文档:

Vue 无法检测到数组的以下更改:

当您直接设置带有索引的项目时,例如 vm.items[indexOfItem] = newValue

当你修改数组的长度时,例如 vm.items.length = newLength

Vue为此用例提供了一个简单的解决方案:(Vue.set()this.$set())方法:

this.$set(this.boxvalues, index, !this.boxvalues[index]);

您可以在此处阅读有关此主题的更多信息


推荐阅读