v-for 使操作应用于所有 div [英] v-for causing actions to be applied to all divs

查看:48
本文介绍了v-for 使操作应用于所有 div的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

之前我问过一个关于在 Vue 中删除自定义 truncate 过滤器的问题.请在此处查看问题:

在鼠标悬停时删除 Vue 自定义过滤器

但是,我忽略了我正在使用 v-for 循环,当我将鼠标悬停在一个 div 上时,我注意到循环中的所有 div 都对它们应用了相同的操作.我不确定如何只定位悬停在上面的 div.这是我的模板:

 

<button class="tile" v-for="(word, index) in shuffled" @click="clickWord(word, index)" :title="word.english"><div class="pinyin">{{ word.pinyin }}</div><div class="eng" @mouseover="showAll = true" @mouseout="showAll = false"><div v-if="showAll">{{ word.english }}</div><div v-else>{{ word.english |截断 }}</div>

以及返回的数据:

 数据(){返回 {当前索引:0,圆形清除:假,clickedWord: '',matchFirstTry: 真,全部显示:假,}},

如果您了解 Vue,我将不胜感激.谢谢!

解决方案

在您的示例中, showAll 用于 v-for 生成的每个按钮来确定是否显示word.english 值的完整文本.这意味着每当任何 .eng 类 div 的 mouseover 事件触发时,相同的 showAll 属性都会为每个按钮设置为 true.

<小时>

我会将 showAll 布尔值替换为最初设置为 nullshowWordIndex 属性:

data() {显示词索引:空,},

然后在模板中,将 showWordIndex 设置为 mouseover 处理程序上单词的 index(并设置为 nullmouseleave 处理程序中):

这是一个有用的小提琴.

<小时>

更好的是制作一个新组件来封装在 v-for 中呈现的所有内容的功能和模板,将每个 word 对象的属性传递给子组件作为道具.

这样,您仍然可以像在示例中一样使用 showAll 属性,但您将在子组件的范围内定义它.所以现在 showAll 属性只会影响它相关的组件的实例.

下面是一个例子:

Vue.component('tile', {模板:'#tile',道具:['拼音','英文'],数据() {返回 { showAll: false };},过滤器:{截断:函数(值){让长度= 50;if (value.length <= length) {返回值;} 别的 {return value.substring(0, length) + '...';}}},})新的 Vue({el: '#app',数据() {返回 {字: [{pinyin: 1, english: "很长的字符串会被截断函数截断"},{pinyin: 2, english: "很长的字符串会被截断函数截断"},{pinyin: 3, english: "很长的字符串会被截断函数截断"},{pinyin: 4, english: "很长的字符串会被截断函数截断"},],}}})

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.1/vue.min.js"></script><div id="应用程序"><tile v-for="word, i in words" v-bind="word" :key="word"></tile>

<script id="tile" type="x-template"><button :title="english"><div class="pinyin">{{拼音}}</div><div class="eng" @mouseover="showAll = true" @mouseout="showAll = false"><div v-if="showAll">{{ 中文 }}</div><div v-else>{{ 英语 |截断 }}</div>

</script>

Previously I asked a question about removing a custom truncate filter in Vue. Please see the question here:

Removing a Vue custom filter on mouseover

However, I neglected to mention that I am using a v-for loop and when I hover over one div, I am noticing that all the divs in the loop are having the same action applied to them. I'm not sure how to target only the div that is being hovered over. Here is my template:

 <div id="tiles">
    <button class="tile" v-for="(word, index) in shuffled" @click="clickWord(word, index)" :title="word.english">
      <div class="pinyin">{{ word.pinyin }}</div>
      <div class="eng" @mouseover="showAll = true" @mouseout="showAll = false">
        <div v-if="showAll">{{ word.english }}</div>
        <div v-else>{{ word.english | truncate }}</div>
      </div>
    </button>
  </div>

And the data being returned:

  data(){
    return {
      currentIndex: 0,
      roundClear: false,
      clickedWord: '',
      matchFirstTry: true,
      showAll: false,
    }
  },

If you know Vue, I would be grateful for advice. Thanks!

解决方案

In your example, showAll is being used for each of the buttons generated by the v-for to determine whether or not to show the complete text of the word.english value. This means that whenever the mouseover event of any the .eng class divs fires, the same showAll property is being set to true for every button.


I would replace the showAll Boolean value with a showWordIndex property initially set to null:

data() {
  showWordIndex: null,
},

And then in the template, set showWordIndex to the index of the word on the mouseover handler (and to null in the mouseleave handler):

<button v-for="(word, index) in shuffled" :key="index">
  <div class="pinyin">{{ word.pinyin }}</div>
  <div 
    class="eng" 
    @mouseover="showWordIndex = index" 
    @mouseout="showWordIndex = null" 
  >
    <div v-if="showWordIndex === index">{{ word.english }}</div>
    <div v-else>{{ word.english | truncate }}</div>
  </div>
</button>

Here's a working fiddle.


Even better would be to make a new component to encapsulate the functionality and template of everything being rendered in the v-for, passing the properties of each word object to the child component as props.

This way, you would still use the showAll property like you are in your example, but you would define it in the child component's scope. So now the showAll property will only affect the instance of the component it's related to.

Below is an example of that:

Vue.component('tile', {
  template: '#tile',
  props: ['pinyin', 'english'],
  data() {
    return { showAll: false };
  },
  filters: {
    truncate: function(value) {
      let length = 50;
      if (value.length <= length) {
        return value;
      } else {
        return value.substring(0, length) + '...';
      }
    }
  },
})

new Vue({
  el: '#app',
  data() {
    return {
      words: [
        {pinyin: 1, english: "really long string that will be cut off by the truncate function"},
        {pinyin: 2, english: "really long string that will be cut off by the truncate function"},
        {pinyin: 3, english: "really long string that will be cut off by the truncate function"},
        {pinyin: 4, english: "really long string that will be cut off by the truncate function"},
      ],
    }
  }
})

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.1/vue.min.js"></script>
<div id="app">
  <tile v-for="word, i in words" v-bind="word" :key="word"></tile>
</div>

<script id="tile" type="x-template">
  <button :title="english">
    <div class="pinyin">{{ pinyin }}</div>
    <div class="eng" @mouseover="showAll = true" @mouseout="showAll = false">
      <div v-if="showAll">{{ english }}</div>
      <div v-else>{{ english | truncate }}</div>
    </div>
  </button>
</script>

这篇关于v-for 使操作应用于所有 div的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆