vue.js - :class not updating when clicked in vuejs v-for

标签 vue.js v-for

我想在点击 td 时向 v-for 中的项目添加 css 类

      <template>
  <div>
    <h1>Forces ()</h1>

    <section v-if="errored">
      <p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
    </section>

    <section v-if="loading">
      <p>loading...</p>
    </section>

    <table class="table table-bordered table-hover">

      <thead>
        <tr>
          <th>#</th>
          <th>ID</th>

          <th 
              @click="orderByName = !orderByName">Forces</th>
        </tr>
        <th>Delete</th>
      </thead>
      <tbody>
        <tr v-for="(force, index) in forces" @click="completeTask(force)" :class="{completed: force.done}"  v-bind:key="index">

          <td>
            <router-link :to="{ name: 'ListForce', params: { name: force.id } }">Link</router-link>
          </td>

          <th>{{ force.done }}</th>

          <th>{{ force.name }}</th>
          <th><button v-on:click="removeElement(index)">remove</button></th>

        </tr>
      </tbody>
    </table>
    <div>
    </div>
  </div>

</template>


<script>
import {APIService} from '../APIService';
const apiService = new APIService();
const _ = require('lodash');

export default {

  name: 'ListForces',

  components: {

  },

  data() {
    return {
      question: '',
      forces: [{
        done: null,
        id: null,
        name: null
      }],
      errored: false,
      loading: true,
      orderByName: false,
    };

  },

  methods: {
    getForces(){
      apiService.getForces().then((data, error) => {

          this.forces = data;
          this.forces.map(function(e){
               e.done = false;
          });
          this.loading= false;
        console.log(this.forces)
      });
    },
    completeTask(force) {
      force.done = ! force.done;
      console.log(force.done);
    },
    removeElement: function (index) {
      this.forces.splice(index, 1);
    }
  },

  computed: {
/*    forcesOrdered() {
      return this.orderByName ? _.orderBy(this.forces, 'name', 'desc') : this.forces;
    }*/
  },
  mounted() {
    this.getForces();
  },
}
</script>

<style>
    .completed {
        text-decoration: line-through;
    }
</style>

我希望在单击时有一条线穿过项目,但 dom 不更新。如果我进入 chrome 中的 vue 选项卡,我可以看到每个项目的 force.done 更改,但前提是我单击对象之外并单击返回对象。我不确定为什么状态没有像我之前使用过单击和 css 绑定(bind)时那样更新。

最佳答案

我尝试进行最小的更改以使其正常工作:

// import {APIService} from '../APIService';
// const apiService = new APIService();
// const _ = require('lodash');

const apiService = {
  getForces () {
    return Promise.resolve([
      { id: 1, name: 'Red' },
      { id: 2, name: 'Green' },
      { id: 3, name: 'Blue' }
    ])
  }
}

new Vue({
  el: '#app',
  name: 'ListForces',

  components: {

  },

  data() {
    return {
      question: '',
      forces: [{
        done: null,
        id: null,
        name: null
      }],
      errored: false,
      loading: true,
      orderByName: false,
    };

  },

  methods: {
    getForces(){
      apiService.getForces().then((data, error) => {
          for (const force of data) {
            force.done = false;
          }

          this.forces = data;
          this.loading= false;
        console.log(this.forces)
      });
    },
    completeTask(force) {
      force.done = ! force.done;
      console.log(force.done);
    },
    removeElement: function (index) {
      this.forces.splice(index, 1);
    }
  },

  mounted() {
    this.getForces();
  }
})
.completed {
  text-decoration: line-through;
}
<script src="https://unpkg.com/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e5939080a5d7cbd3cbd4d5" rel="noreferrer noopener nofollow">[email protected]</a>/dist/vue.js"></script>
<div id="app">
  <div>
    <h1>Forces ()</h1>

    <section v-if="errored">
      <p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
    </section>

    <section v-if="loading">
      <p>loading...</p>
    </section>

    <table class="table table-bordered table-hover">

      <thead>
        <tr>
          <th>#</th>
          <th>ID</th>

          <th 
              @click="orderByName = !orderByName">Forces</th>
          <th>Delete</th>
        </tr>
        
      </thead>
      <tbody>
        <tr v-for="(force, index) in forces" @click="completeTask(force)" :class="{completed: force.done}"  v-bind:key="index">

          <th>{{ force.done }}</th>

          <th>{{ force.name }}</th>
          <th><button v-on:click="removeElement(index)">remove</button></th>

        </tr>
      </tbody>
    </table>
    <div>
    </div>
  </div>
</div>

关键问题在这里:

this.forces = data;
this.forces.map(function(e){
  e.done = false;
});

这里的问题是,属性done在变为 react 性后被添加到数据中。一旦 this.forces = data 行运行, react 性观察者就会被添加。之后添加 done 算作添加新属性,这是行不通的。

这也是对 map 的误用,因此我将其切换为 for/of 循环。

for (const force of data) {
  force.done = false;
}

this.forces = data; // <- data becomes reactive here, including 'done'

在一个不相关的注释中,我调整了模板以将 Delete 标题移动到顶行内。

关于vue.js - :class not updating when clicked in vuejs v-for,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57691835/

相关文章:

vue.js - Vuejs 单选按钮检查 v-model 是否为数组

javascript - 具有工厂功能的 Vue 组件 v-for

javascript - v-for 中的 Vue 动态 v-model

vue.js - Vue - v-for 修改值

javascript - 将焦点设置在第二级引导模式中包含的输入控件上

javascript - 如何在 Axios 响应中将 JSON 数组正确推送到 Vue JS 中的现有数据数组中?

Facebook 页面插件未在 Vue Js 中加载

javascript - 获取所有嵌套内容文件并按 Nuxt 内容中的目录对它们进行分组

javascript - 无法正确从 html 调用 vue 函数(组件渲染函数中的无限更新循环)

javascript - 在循环外使用 v-for 键