【问题标题】:VUE Js child is not updating when parent updates父更新时VUE Js子不更新
【发布时间】:2020-10-26 21:30:03
【问题描述】:

我正在使用 VUE JS,我想要一组复选框,如下所示。当有人单击主复选框时,应选中该复选框下的所有复选框。请找到附件图片供您参考

为了完成这个场景,我使用了 2 个主要组件。当有人单击一个组件时,我将该组件添加到 selectedStreams 数组中。选择的流数组结构类似于下面的结构

  checked: {
        g1: ['val1'],
        g2: []
    }

当我点击标题复选框时,我正在触发功能

clickAll 并尝试更改 selectedStreams[keyv]。

但是这个动作并没有触发子组件,而是自动勾选了复选框。

我可以知道为什么当我更改父 v-model 值时它在子 UI 中不可见。

父组件

 <template>
    <div>
        <b-form-group>
            <StreamCheckBox
                    v-for="(opts, keyv) in loggedInUsernamesf"
                    :key="keyv"
                    :name="opts"
                    :main="keyv"
                    v-model="selectedStreams[keyv]"
                    @clickAll="clickAll($event, keyv)"
            ></StreamCheckBox>
        </b-form-group>
    </div>
</template>
<script>import StreamCheckBox from "./StreamCheckBox";
export default {
        name: "GroupCheckBox",
        components: {StreamCheckBox},
        data(){
          return {
            selectedStreams:{}
          }
        },
        computed: {
            loggedInUsernamesf() {
                var username_arr = JSON.parse(this.$sessionStorage.access_info_arr);
                var usernames = {};
                if (!username_arr) return;
                for (let i = 0; i < username_arr.length; i++) {
                    usernames[username_arr[i].key] = [];
                    var payload = {};
                    payload["main"] = username_arr[i].val.name;
                    payload["type"] = username_arr[i].val.type;
                    if (username_arr[i].val.permissions) {
                        for (let j = 0; j < username_arr[i].val.permissions.length; j++) {
                            payload["value"] = username_arr[i].key + username_arr[i].val.permissions[j].streamId;
                            payload["text"] = username_arr[i].val.permissions[j].streamId;
                        }
                    }
                    usernames[username_arr[i].key].push(payload);
                }
                return usernames;
            },
        },

        methods: {
            
            clickAll(e, keyv) {
                if (e && e.includes(keyv)) {
                    this.selectedStreams[keyv] = this.loggedInUsernamesf[keyv].map(
                        opt => {
                            return opt.value
                        }
                    );
                }
                console.log(this.selectedStreams[keyv]);
            }
        }
    }
</script>

<style scoped>

</style>

子组件

    <template>
    <div style="text-align: left;">
        <b-form-checkbox-group style="padding-left: 0;"
                               id="flavors"
                               class="ml-4"
                               stacked
                               v-model="role"
                               :main="main"
        >
            <b-form-checkbox
                    class="font-weight-bold main"
                    :main="main"
                    :value="main"
                    @input="checkAll(main)"
            >{{ name[0].main }}</b-form-checkbox>
                <b-form-checkbox
                        v-for="opt in displayStreams"
                        :key="opt.value"
                        :value="opt.value"
                >{{ opt.text }}</b-form-checkbox>
            </b-form-checkbox-group>
    </div>
</template>

<script>
    export default {
        name:"StreamCheckBox",
        props: {
            value: {
                type: Array,
            },
            name: {
                type: Array,
            },
            main:{
                type:String
            }

        },
        computed:{
            role: {
                get: function(){
                    return this.value;
                },
                set: function(val) {
                    this.$emit('input', val);
                }
            },
            displayStreams: function () {
                return this.name.filter(i => i.value)
            },
        },
        methods:{
            checkAll(val)
            {
                this.$emit('clickAll', val);
            }
        }
    }
</script>

【问题讨论】:

  • 您可以将该值传递给孩子,如果该值为真,则检查它们。如果您将它作为道具传递给孩子,您还可以在其上放置一个观察者并运行一个函数,从而在道具值发生变化时进行更新
  • @AaronAngle 我正在使用一个数组,如果选中任何复选框,则将其推入。

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


【解决方案1】:

首先,我不确定在您的父组件中添加props 的目的是什么。我认为您可以从父组件中删除 props 并仅保留在子组件中。

其次,不触发更改的原因可能是您正在处理数组,因为您可以在子组件中设置deep watcher

export default {
  props: {
    value: {
      type: Array,
      required: true,
    },
  },
  watch: {
    value: {
      deep: true,
      //handle the change
      handler() {
        console.log('array updated');
      }
    }
  }
}

您可以找到更多信息herehere

【讨论】:

  • 非常感谢您的回答。我已经在我的代码中添加了 watch 功能,当我点击一个复选框时,该功能就会触发。但在这里我关心的是在父类中使用 ClickAll 方法将子元素也推送到选定的数组中。因此,当有人单击父复选框时,应检查所有子复选框。数组中的变化 this.selectedStreams[keyv] 在子级中不可见。如果您能帮我解决这个问题,那就太好了。
  • selectedStreams 似乎是computed property。如果您希望返回的数组在子组件中可见,您将返回某种data property 并将其作为prop 传递,然后您可以再次在您的子组件中使用watch。这可能是在您的子组件中查看从 selectedStreams 返回的数组更改的一种方法,或者 checkAll 可以返回这样的数组,您将使用 prop
  • 我已更改代码以将 selectedStreams 作为数据属性。 (返回 selectedStreams:{})。但是对于 v-model,我传递了 selectedStreams[key] ,它应该返回一个数组。对此 selectedStream 对象的更改仍然不可见。我是 vuejs 的新手,我无法弄清楚这个问题。
  • 如果您希望我研究特定场景,那么如果您可以在 CodeSandbox (codesandbox.io/s/vue) 中重新创建它会很有帮助。
猜你喜欢
  • 2019-05-02
  • 2020-10-01
  • 1970-01-01
  • 2017-12-31
  • 2020-06-28
  • 1970-01-01
  • 2017-09-09
  • 2021-10-03
  • 2020-05-23
相关资源
最近更新 更多