【问题标题】:VueJS - How to use v-model in the right way when using child componentsVueJS - 使用子组件时如何正确使用v-model
【发布时间】:2021-06-10 07:39:51
【问题描述】:

嗯,我对 VueJS 有点陌生.. 现在我正在学习组件的工作方式。

当我尝试更新传递给在子组件中用作 v-model 的子组件的父数据参数时,我感到困惑。

我将添加一个示例,以便您理解我在说什么(我很难解释自己)

注意:我使用数组作为 v-model,因为我需要一种方法来遍历所有复选框 v-model 并稍后更新它们

我即将展示的示例是在旅途中编写的。所以它不是实际的代码,但你可以从中得到概念。

假设我们有以下模板:

<script type="x-template id="tree">
    <table>
        <thead>
            <tr>
                <th>Tree-Item</th>
                <th>check chilld</th>
            </tr>
        </thead>
        <tbody>
            <template v-for="child in item.childrens">
                <tr v-if="child.childrens.length <= 0">
                    <td>{{child.name}}</td>
                    <td>
                        <input type="checkbox" v-model="checkboxes[child.id].value" :value="1" />
                    </td>
                </tr>
                <tr v-else>
                    <td colspan="2">
                        <tree :item="child" :checkboxes="checkboxes"></tree>
                    </td>
                </tr>
            </template>
        </tbody>
    </table>
</script>

组件:

    Vue.component("tree", {
        template: "#tree",
        props: {
            item: Object,
            checkboxes: []
        }
    }

vue 对象

    var mainVue = new Vue({
        el: "#app",
        data: {
            treeData: {
                id: 0,
                name: "a name",
                childrens: [
                    {
                        id: 1,
                        name: "b name",
                        childrens: []
                    }, {
                        id: 2
                        name: "c name"
                        childrens: [
                            {
                                id: 3,
                                name: "d name",
                                childrens: []
                            },
                            {
                                id: 4,
                                name: "d name",
                                childrens: []
                            },
                            {
                                id: 5,
                                name: "d name",
                                childrens: []
                            }
                        ]
                    }
                ]
            },
            checkboxes: []
        }, mounted: function() {
            //looping all the childrens... setting checkboxes array to contain data for each index of child
            // checkboxes array now contains the objects of - [{value: 0},{value: 0},{value: 0},{value: 0},{value: 0},{value: 0}]
        }
    });

我的应用将如下所示:

    <div id="app">
        <tree :item="treeData" :checkboxes="checkboxes"></tree>
    </div>

现在它可以工作了。如果我将mounted函数中的数组值之一更改为1,它将被设置为选中。但我的问题是我也想实时更新它。

所以如果我有一个按钮,让我们说:

    <div id="app">
        <tree :item="treeData" :checkboxes="checkboxes"></tree>
        <button @click="changeCheckboxes">a button</button>
    </div>

我将添加一个方法来将“复选框”数组更改为新的:

changeCheckboxes: function() {
    this.checkboxes = [{value: 1}, {value: 0}, {value: 1}, {value: 0}, {value: 1}, {value: 0}];
}

它不会更新组件,我不会看到任何效果..即使我会使用 this.$forceUpdate()

所以在我向您简要介绍了详细信息之后。 是否有任何选项可以直接从根 vue 应用更新子组件中的 v-model?

感谢您的宝贵时间!希望我们能弄清楚:)

【问题讨论】:

  • 看看reactivity docs on arraysVue 无法检测到你的更改
  • 好的,注意了。尝试将复选框从 [] 更改为 {} 结果是一样的

标签: vue.js vue-component v-model


【解决方案1】:

https://vuejs.org/v2/guide/reactivity.html#For-Arrays

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

  1. 当您直接使用索引设置项目时,例如vm.items[indexOfItem] = newValue
  2. 当您修改数组的长度时,例如vm.items.length = newLength

问题是你在做v-model="checkboxes[child.id].value"。 V-model 真的只是一种花哨的做法:

 <input type="checkbox" :value="checkboxes[child.id].value" @input="checkboxes[child.id].value = $event"

v-model 中的 @input 部分是 Vue 无法检测到的。我认为对于这个问题,如果您需要将复选框和项目分开,并且您不想重写很多,则必须放弃 v-model 并分别使用 value 和 @input:

 <input type="checkbox" :value="checkboxes[child.id].value" @input="toggleCheckbox(child.id)"
methods: {
  toggleCheckbox(index) {
   this.checkboxes.splice(index, 1, !this.checkboxes[index].value)
  }
}

如果我正确理解你,child.id 与复选框数组中的索引相关联。

但是

我看到你实际上是在改变你的道具,这在 Vue 中是一种不好的做法。 您应该使用 prop/emit 工作流程。这意味着父级应始终对数据更改负责。

因此,最好的方法是更改​​上面的 toggleCheckbox 函数以发出更改,然后让父级更改复选框数组。一旦父母这样做了,孩子也会自动改变。

【讨论】:

  • 非常感谢您的详细回答。现在对我来说更清楚了。
【解决方案2】:

正如 Sølve Tornøe 已经回答的那样,反应性是 Vue 中需要注意的事情,尤其是对于 here 中的数组。这也是您更新的 Array 不起作用的原因。

但是,您的问题的解决方案非常简单,不需要太多。让我们仔细看看您的复选框。

<input type="checkbox" v-model="checkboxes[child.id].value" :value="1" />

虽然最初看起来不错,但由于上述反应性问题,您的 v-model 绑定不会更新您的数组值。相反,为您的循环添加一个额外的@update 绑定以及一个索引。

<input type="checkbox" v-model="checkboxes[child.id].value" :value="1" @input="updateCheckbox(i, child.id)" />

你的方法可能看起来像这样

updateCheckbox(i, id) {
  this.$set(item.childrens[i], id, 'some value here');
}

【讨论】:

  • 感谢您提供更多详细信息!非常感谢。
猜你喜欢
  • 2021-03-10
  • 2019-07-28
  • 1970-01-01
  • 1970-01-01
  • 2021-02-21
  • 2019-02-07
  • 2019-02-05
  • 2020-06-09
  • 2019-02-14
相关资源
最近更新 更多