Vue多选奇怪的行​​为

时间:2017-11-29 16:16:54

标签: select vue.js vuejs2

我有这个模板

         <select multiple v-model="selectedRows">
           <!-- availableFields -->
           <option v-for="row in availableFields" v-bind:value="row">
             {{ (row.data.title) }}
           </option>
          </select>

其中selectedRows为空数组 availableFields是由对象填充的数组 每个行对象都有属性数据。例如

availableFields[i] = {
data: {title: "blablabla", type: "INDEX"}
}

等。

当我有类似data.title的对象时, 鼠标单击一个实体会突出显示所有其他实体,它们具有相同的标题属性。 在图片上,如果我点击带有data.title =“newrow”的对象,则同样会突出显示具有相同data.title的第二个对象。 enter image description here

是否可以解决此问题(我想使用多个选择)

2 个答案:

答案 0 :(得分:2)

这是一个有趣的问题。我能够重现你所看到的行为。

我希望问题是因为在HTML中,value是一个字符串,当对象转换为字符串时,它们最终成为相同的字符串,这就是为什么它们全部突出显示的原因。 Vue将实际的row对象添加为属性_value,这就是为什么只有一个值添加到selectedFields

&#13;
&#13;
console.clear()

new Vue({
  el: "#app",
  data:{
    selectedFields:[],
    availableFields:[
      {data: {title:"newrow", type:"INDEX"}},
      {data: {title:"newrow", type:"INDEX"}},
      {data: {title:"newrow", type:"INDEX"}},
      {data: {title:"newrow", type:"INDEX"}},
    ]
  }
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div id="app">
  <select multiple v-model="selectedFields">
    <option v-for="row in availableFields" :value="row">{{row.data.title}}</option>
  </select>
  <hr>
  {{selectedFields}}
</div>
&#13;
&#13;
&#13;

如果您选择上述某个项目,则会在选择中选择所有项目(虽然只有一项添加到selectedFields。我不会预料到这一点行为,因为它们都是单独的对象,尽管具有完全相同的属性。

一种解决方法是为每个对象添加id属性。

&#13;
&#13;
console.clear()

new Vue({
  el: "#app",
  data:{
    selectedFields:[],
    availableFields:[
      {id: 1, data: {title:"newrow", type:"INDEX"}},
      {id: 2, data: {title:"newrow", type:"INDEX"}},
      {id: 3, data: {title:"newrow", type:"INDEX"}},
      {id: 4, data: {title:"newrow", type:"INDEX"}},
    ]
  }
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div id="app">
  <select multiple v-model="selectedFields">
    <option v-for="row in availableFields" :value="row">{{row.data.title}}</option>
  </select>
  <hr>
  {{selectedFields}}
</div>
&#13;
&#13;
&#13;

在这种情况下,只突出显示单个选定对象。

总之,要解决这个问题,只要有一些独特的属性导致不同的value字符串,是否通过@ RoyJ使用计算机或修改数据的出色建议,select应该按预期工作。

答案 1 :(得分:2)

我也能够重现这个问题。如果两个条目具有相同的字段,那么它们之间的区别是什么?如果你选择一个,可以说它们都应该被选中。但是,Vue实际上并没有将PTRL != PTRS一致地添加到selectedRows,所以不管怎样你都会看到它。

在下面的示例中,我已将type更改为一行,您会注意到它独立于其他行进行选择。

您可以设置computed为每个条目指定唯一键。如果您使用afWithKey代替availableFields,则每个选项仅影响所选行。

&#13;
&#13;
new Vue({
  el: '#app',
  data: {
    availableFields: [{
      data: {
        title: "row",
        type: "INDEX"
      }
    }, {
      data: {
        title: "other",
        type: "INDEX"
      }
    }, {
      data: {
        title: "row",
        type: "INDEX2"
      }
    }, {
      data: {
        title: "row",
        type: "INDEX"
      }
    }],
    selectedRows: []
  },
  computed: {
    afWithKey() {
      return this.availableFields.map((e, i) => Object.assign({key: i}, e));
    }
  }
});
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <select multiple v-model="selectedRows">
     <option v-for="row in availableFields" v-bind:value="row">
       {{ row.data.title }}
     </option>
   </select>
   <pre>{{JSON.stringify(selectedRows)}}</pre>
</div>
&#13;
&#13;
&#13;

另一种方法是使用index作为选项的值,并使用computedselectedIndexes的数组转换为selectedRows数组:

&#13;
&#13;
new Vue({
  el: '#app',
  data: {
    availableFields: [{
      data: {
        title: "row",
        type: "INDEX"
      }
    }, {
      data: {
        title: "other",
        type: "INDEX"
      }
    }, {
      data: {
        title: "row",
        type: "INDEX2"
      }
    }, {
      data: {
        title: "row",
        type: "INDEX"
      }
    }],
    selectedIndexes: []
  },
  computed: {
    selectedRows() {
      return this.selectedIndexes.map((i) => this.availableFields[i]);
    }
  }
});
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <select multiple v-model="selectedIndexes">
     <option v-for="row, index in availableFields" v-bind:value="index">
       {{ row.data.title }}
     </option>
   </select>
   <pre>{{JSON.stringify(selectedRows)}}</pre>
</div>
&#13;
&#13;
&#13;