自定义 vue 组件不更新值更改
Custom vue component not updating on value change
我在 https://codepen.io/james-hudson3010/pen/QWgarbr 有一个 codepen,它演示了这个问题。
我正在尝试创建和使用基于 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>
你是对的,罪魁祸首是这一行的反应性丧失:
this.boxvalues[index] = !this.boxvalues[ index ];
来自文档:
Vue cannot detect the following changes to an array:
When you directly set an item with the index, e.g.
vm.items[indexOfItem] = newValue
When you modify the length of the
array, e.g. vm.items.length = newLength
Vue 为这个用例提供了一个简单的解决方案:Vue.set()
(或this.$set()
)方法:
this.$set(this.boxvalues, index, !this.boxvalues[index]);
您可以阅读有关此主题的更多信息here
补充 Igor 所说的内容,您还可以重写整个数组以触发反应性。
例如:
boxValueChanged( index ) {
const boxvalues = [...this.boxvalues]
boxvalues[index] = !boxvalues[index]
this.boxvalues = boxvalues
},
我在 https://codepen.io/james-hudson3010/pen/QWgarbr 有一个 codepen,它演示了这个问题。
我正在尝试创建和使用基于 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>
你是对的,罪魁祸首是这一行的反应性丧失:
this.boxvalues[index] = !this.boxvalues[ index ];
来自文档:
Vue cannot detect the following changes to an array:
When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
When you modify the length of the array, e.g. vm.items.length = newLength
Vue 为这个用例提供了一个简单的解决方案:Vue.set()
(或this.$set()
)方法:
this.$set(this.boxvalues, index, !this.boxvalues[index]);
您可以阅读有关此主题的更多信息here
补充 Igor 所说的内容,您还可以重写整个数组以触发反应性。 例如:
boxValueChanged( index ) {
const boxvalues = [...this.boxvalues]
boxvalues[index] = !boxvalues[index]
this.boxvalues = boxvalues
},