Vue.js - 如何在 `v-for` 中为微调器设置隔离范围

Vue.js - How to have isolated scope for a spinner inside of `v-for`

HTML

<div v-for="account in accounts">
  ...
  <button v-if="!isUnlinking" class="btn btn-warning btn-sm" @click="unlinkAccount(provider.providerId)">
      <i class="fa fa-unlink"></i>
      Unlink
  </button>

  <button v-if="!!isUnlinking" class="btn btn-warning btn-sm" :disabled="!!isUnlinking">
      <i class="fa fa-spin fa-refresh"></i>
      Unlinking...
  </button>
  ...
</div>

问题

当我点击 Unlink button 时,所有 repeated/iterated div 元素中的按钮正在获取 spinner。而我只希望 单击 button 具有 微调器 图标。

在这种情况下,每个按钮都应该有 id 参数。当你是 'unlinking' 时,你必须检查 v-if 按钮的 id 是否与上下文元素相同,并且仅在这种情况下显示微调器。

在我看来问题是您使用单个变量 isUnlinking 使所有按钮可见,因此如果其中一个按钮的变量发生变化,它会应用于所有按钮。

您必须有一个 isUnlinking 数组,并且只针对该按钮进行更改,如下所示:

<div v-for="(account, index) in accounts">
  ...
  <button v-if="!isUnlinking[index]" class="btn btn-warning btn-sm" @click="unlinkAccount(provider.providerId)">
      <i class="fa fa-unlink"></i>
      Unlink
  </button>

  <button v-else class="btn btn-warning btn-sm" :disabled="isUnlinking[index]">
      <i class="fa fa-spin fa-refresh"></i>
      Unlinking...
  </button>

还要注意使用 v-else,而不是 v-if="!!isUnlinking"

...

最好的方法是在帐户对象上添加此 属性:

<div v-for="account in accounts">
  ...
  <button v-if="!account.isUnlinking" class="btn btn-warning btn-sm" @click="unlinkAccount(provider.providerId)">
      <i class="fa fa-unlink"></i>
      Unlink
  </button>

  <button v-if="!!account.isUnlinking" class="btn btn-warning btn-sm" :disabled="!!isUnlinking">
      <i class="fa fa-spin fa-refresh"></i>
      Unlinking...
  </button>
  ...
</div>

现在它已绑定到特定对象。

我解决类似问题的一种方法是在点击事件函数中将 $event.target.children[0] 作为 属性 传递,而不是从元素中删除 class 和为元素的微调器附加了一个新的 class。我希望这会有所帮助。

<div v-for="account in accounts">
  <button class="btn btn-warning btn-sm" 
    @click="unlinkAccount($event.target.children[0])">
      <i class="fa fa-unlink"></i>
      Unlink
  </button>
</div>
<script>
export default {
  methods: {
     unlinkAccount() {
        event.className = event.className.replace(/\bfa fa-unlink\b/g, "fa fa-spin fa-refresh");
     }
  }
}
</script>

这是我想针对我的问题提出的解决方案:

更新NOV-2018

我建议创建一个新的 vue-component 并对其进行迭代。帐户对象将通过 props:

传递给 child-component
<div>
  <h3> Accounts </h3>
  <AccountButton v-for="account in accounts" :account="account" />
</div>

祝你好运...


之前的建议

<div v-for="account in accounts.map(function(item){ return {item: item, isUnlinking: false}})">
  ...
  <button v-if="!account.isUnlinking" class="btn btn-warning btn-sm" @click="unlinkAccount(account)">
      <i class="fa fa-unlink"></i>
      Unlink
  </button>

  <button v-if="!!account.isUnlinking" class="btn btn-warning btn-sm" :disabled="!!account.isUnlinking">
      <i class="fa fa-spin fa-refresh"></i>
      Unlinking...
  </button>
  ...
</div>


<script>
  // somewhere inside Vue.component
  ...
  function unlinkAccount(account) {
    account.isUnlinking = true;
    // do the unlinking with account.item.provider.providerId
  }
  ...
</script>

在这里,我使用 map 函数从现有的 accounts 数组引导了一个新数组(这个映射可以移到 JS 中的 Vue 组件语法中将其保存在 HTML 中)。现在每个 account item 都有自己的 属性 isUnlinking 可以根据需要设置。我已将初始值设置为 false,因为 unlinking 只有在单击按钮后才会启动。

感谢@Bazinga、@Saurabh、@Bernard Doci 和@M U 的参与

祝你好运...

在您的 V-FOR 中,每一行都可以分配一个键。

例如

<div v-for=" (b,key) in buttons">

  <button>
  {{b}}
  <i class="fa fa-spinner fa-spin" @click="clickButton(key)" v-if="buttonsLoading[key]"> 
  </button>

</div>

在您的 VUE 数据部分:

data: {
    buttons:{
        button1:'Click me',
        button2:'NO click me,
        button3:'NOOO Click me',
    },
    buttonsLoading:[],
},
methods: {
    clickButton:function(key)
    {
          Vue.set(this.buttonsLoading , key , 1);
    }
}

如果你正在执行 axios 或 ajax 请求,你显然会知道按钮何时需要停止,所以当你获得成功响应时,添加 Vue.set(this.buttonsLoading , 'button' + key , 0) 以便它停止旋转。

例如。在我的 V-FOR 设置中,每一行都有一个按钮。 单击时,每个单独的按钮都必须单独操作并显示它自己的微调器,而不是所有微调器(这是您遇到的错误)。

为此,您必须创建一个数组,然后您可以在单击时将键设置为该数组。

如果你想要的话,给你做了一个视频,https://www.youtube.com/watch?v=Zm00rS0gX24,如果没有解释清楚,请原谅,我不是最擅长解释这些东西的人:)干杯