简体   繁体   English

VueJS v-bind 属性在 AJAX 之后没有立即更新

[英]VueJS v-bind property not updated immediately after AJAX

I have a table where each row corresponds to an event.我有一个表,其中每一行对应一个事件。 Each event has a set of timeslots rendered as span elements and each timeslot is assigned the na class (with v-bind) only when its stopsales property is true每个事件都有一组呈现为跨度元素的时隙,并且每个时隙仅在其stopsales属性为 true 时被分配na class(使用 v-bind)

The timeslots are fetched asynchronously from an ajax request ( loadData ).从 ajax 请求 ( loadData ) 异步获取时隙。

I call loadData to render my timeslots initially.我最初调用loadData来渲染我的时间段。 There are also 2 buttons I use to call the function below to change the stopsales property of some of them:我还使用 2 个按钮来调用下面的 function 来更改其中一些的 stopsales 属性:

<div v-for="event in events">
  <label>
    <input type="checkbox" @change="handleEvents(event); " :id="event" 
           :value="event" v-model="selectedEvents">
      {{event.name}}
  </label>
</div>

<button class="btn btn-success" v-on:click="toggle(true);">Activate</button>
<button class="btn btn-danger" v-on:click="toggle(false);">Stop</button>

<td v-for="event in selectedEvents">
  <span v-for="(ev, index, key)  in event.timeslot">
    <span class="label label-default" v-bind:class="{ na: ev.stopsales }"></span>
    <input type="checkbox" :timeslot="ev.timeslotId" 
           v-on:click="addToToggleCheck($event,ev.timeslotId)">
  </span>
</td>


<script>
  const app = new Vue({
    el: '#app',
    data: {
      events: [
        { 
          id: 1, 
          name: "Event 1",                  
        },
        { 
          id: 2, 
          name: "Event 2",                  
        }
      ],
      selectedEvents: [],
      toggleCheck: []
    },
    methods: {
      loadData(event) {
        axios.post(url, {
          event: event.id
        })
        .then(function (response) {
          var response_item = response.data.data[0];
          event.timeslot = response_item.timeslot;
        });
      },
      handleEvents(event) {
        var currentObj = this;
        this.selectedEvents.forEach(function (selectedEvent) {
          if (selectedEvent.id === event.id) {
            currentObj.loadData(event);
          }
        });
      },
      addToToggleCheck(event, timeslotId) {
        if (event.target.checked) {
          this.toggleCheck[timeslotId] = true;
        } else {
           this.toggleCheck[timeslotId] = false;
        }
      },
      toggle(activate){
        var selectedToToggle = [];
        var _this = this;
        for (var key in this.toggleCheck) {
          if (this.toggleCheck[key]) {
            selectedToToggle.push(key);
          }
        }
        axios.post(toggleUrl, {
          evIds: selectedToToggle,
          activate: activate
        })
        .then(function (response) {
          _this.selectedEvents.forEach(function (selectedEvent) {
          _this.loadData(selectedEvent);
        });
      }
    }
  }
</script>

Now here comes the weird part.现在奇怪的部分来了。 If selectedEvents only contains 1 event , when I call the toggle function, the na class is immediately applied as normal to the span elements.如果selectedEvents包含 1 个事件,当我调用切换function 时, na class 会立即正常应用于跨度元素。

However, if selectedEvents contains 2 events , when I call the toggle function, the na class is immediately applied only to the span elements whose parent is the last event chosen.但是,如果selectedEvents包含 2 个事件,当我调用切换function 时, na class 会立即仅应用于其父级是最后选择的事件的跨度元素。 The na class is not yet assigned to the span elements that are children of the first event. na class 尚未分配给作为第一个事件的子元素的 span 元素。 However if I do anything else in my table that does not even involve those 2 functions, like for example opening a modal, the na class is applied to those elements too.但是,如果我在我的表中做任何其他甚至不涉及这两个功能的事情,例如打开一个模式,那么na class 也适用于这些元素。

Is this some VueJS timing issue where the DOM is only updated after a JS event is triggered?这是一些 VueJS 计时问题,其中 DOM 仅在触发 JS 事件后更新? Is there a queue of changes waiting to be deployed on the next event trigger?是否有等待在下一个事件触发器上部署的更改队列?

Your addToToggleCheck seems problematic.您的addToToggleCheck似乎有问题。 Setting array value using indexer is not reactive (Vue cannot detect the change - applies to Vue 2.x).使用索引器设置数组值不是被动的(Vue 无法检测到更改 - 适用于 Vue 2.x)。

Replace this.toggleCheck[timeslotId] = true/false;替换this.toggleCheck[timeslotId] = true/false; with Vue.set(this.toggleCheck, timeslotId, true/false);使用Vue.set(this.toggleCheck, timeslotId, true/false);

Read about Change Detection Caveats for Arrays阅读有关Arrays 的更改检测注意事项

And if your code really looks exactly as in your question, similar problem is in the loadData method on event.timeslot = response_item.timeslot;如果你的代码看起来和你的问题完全一样,类似的问题是在event.timeslot = response_item.timeslot;上的loadData方法中。 line where you are adding new property to an event object向事件添加新属性的行 object

Read about Change Detection Caveats for Objects阅读有关对象的更改检测警告

Either use Vue.set(event, 'timeslot', response_item.timeslot) or introduce the property in data:要么使用Vue.set(event, 'timeslot', response_item.timeslot)要么在数据中引入属性:

data() {
  return {
      events: [
        { 
          id: 1, 
          name: "Event 1",
          timeslot: {}
        },
        { 
          id: 2, 
          name: "Event 2",                  
          timeslot: {}
        }
      ],
      selectedEvents: [],
      toggleCheck: []
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM