首页 > 解决方案 > Vuejs - 观察嵌套对象更改不适用于动态对象创建

问题描述

我正在尝试监视一个嵌套对象,但它不会检测到它的属性的变化,我知道以前有人问过这个问题,我尝试了一些没有运气的解决方案,所以让我先详细解释一下我是什么我试图做:

我有一个多选输入,您可以在其中选择多个房间进行酒店预订:

在此处输入图像描述

因此,当您选择房间时,表单会为每个房间创建新的输入以提供更多信息:

在此处输入图像描述

这是该功能的代码:

<div class="row container-fluid mr-auto ml-auto" v-for="room in extraRooms">
                <div class="col-4">
                  <ValidationProvider
                    name="Pax hab. adicional"
                    rules="required"
                    v-slot="{ passed, failed, errors }"
                  >
                    <base-input
                      :label="'Pax hab. * ' + room "
                      :error="errors[0]"
                      :class="[{ 'has-success': passed }, { 'has-danger': failed }]"
                    >
                      <el-select
                        :class="!!errors[0] ? 'select-danger' : 'select-primary'"
                        placeholder="Seleccionar"
                        filterable
                        collapse-tags
                        v-model="paxExtraRoom[room]"
                      >
                        <el-option
                          v-for="item in selects.paxListMin"
                          v-if="item <= paxAllowed[room]"
                          :label="item"
                          :value="item">
                        </el-option>
                      </el-select>
                    </base-input>
                  </ValidationProvider>
                </div>
                <div class="col-2">
                  <ValidationProvider
                    name="Adulto(s)"
                    rules="required|min:1|numeric|max_value:5|min_value:1"
                    v-slot="{ passed, failed, errors }"
                  >
                    <base-input
                      required
                      v-model="extraRoomsAges[room].adults"
                      label="Adultos"
                      placeholder="+18 años"
                      addon-left-icon="tim-icons icon-single-02"
                      type="text"
                      :error="errors[0]"
                      :class="[{ 'has-success': passed }, { 'has-danger': failed }]">
                    </base-input>
                  </ValidationProvider>
                </div>
                <div class="col-2">
                  <ValidationProvider
                    name="Teenagers"
                    rules="required|min:1|numeric|max_value:4"
                    v-slot="{ passed, failed, errors }"
                  >
                    <base-input
                      required
                      v-model="extraRoomsAges[room].teenagers"
                      label="Adolescentes"
                      placeholder="+12 a -18"
                      addon-left-icon="tim-icons icon-single-02"
                      type="text"
                      :error="errors[0]"
                      :class="[{ 'has-success': passed }, { 'has-danger': failed }]">
                    </base-input>
                  </ValidationProvider>
                </div>
                <div class="col-2">
                  <ValidationProvider
                    name="Niñ@s"
                    rules="required|min:1|numeric|max_value:4"
                    v-slot="{ passed, failed, errors }"
                  >
                    <base-input
                      required
                      v-model="extraRoomsAges[room].children"
                      label="Niñ@s"
                      placeholder="+3 a -11"
                      addon-left-icon="tim-icons icon-single-02"
                      type="text"
                      :error="errors[0]"
                      :class="[{ 'has-success': passed }, { 'has-danger': failed }]">
                    </base-input>
                  </ValidationProvider>
                </div>
                <div class="col-2">
                  <ValidationProvider
                    name="Infantes"
                    rules="required|min:1|numeric|max_value:4"
                    v-slot="{ passed, failed, errors }"
                  >
                    <base-input
                      required
                      v-model="extraRoomsAges[room].infants"
                      label="Infantes"
                      placeholder="-3 años"
                      addon-left-icon="tim-icons icon-single-02"
                      type="text"
                      :error="errors[0]"
                      :class="[{ 'has-success': passed }, { 'has-danger': failed }]">
                    </base-input>
                  </ValidationProvider>
                </div>
              </div>
            </div>

因此,为了将 v-model 绑定到每个输入,我通过观察多选以动态模式创建它们,如下所示:

watch: {
    extraRooms(value){
      // this.extraRoomsAges = []
      value.forEach(val => {
        if (this.extraRoomsAges[val] === undefined){
          this.extraRoomsAges[val] = {
            room: val,
            adults: 1,
            teenagers: 0,
            children: 0,
            infants: 0
          }
        }
      })
    },
}

所以我需要检测四个小输入的变化,以计算这些输入中的数字总和,以获得左侧较大输入中的总人数,所以我尝试使用另一个观察者,如下所示:

extraRoomsAges: {
      handler(value){
        console.log(value)
        value.forEach(val => {
          this.paxExtraRoom[val.room] = parseInt(val.adults) + parseInt(val.teenagers) + parseInt(val.children) + parseInt(val.infants)
        })
      },
      deep: true
    }

但是什么也没有发生,它不会检测到任何变化,我知道如何实现这一点吗?

标签: javascriptvue.js

解决方案


来自Vue 指南:深度反应性

Vue不允许动态添加新的根级响应属性已经创建的实例。但是,可以使用该Vue.set(object, propertyName, value)方法将反应属性添加到嵌套对象。或vm.$set(object, propertyName, value)

因此,在您的代码中,修复将是:

更改this.extraRoomsAges[val] = {...}this.$set(this.extraRoomsAges, val, { room: val, adults: 1, teenagers: 0, children: 0, infants: 0 })


推荐阅读