Отображение усеченного текста только при наведении курсора на Vue - PullRequest
0 голосов
/ 01 октября 2018

Я попробовал это так:

<template>
  ...
  <b-card-group deck v-for="row in formattedClubs">
    <b-card v-for="club in row"
            img-src="http://placehold.it/130?text=No-image"
            img-alt="Img"
            img-top>
      <h4 class="card-title"
          @mouseover="showAll = true"
          @mouseout="showAll = false">
        {{getWord(club.description)}}
      </h4>
      <p class="card-text">
          {{club.price}}
      </p>
      <p class="card-text">
          {{club.country}}
      </p>
      <div slot="footer">
          <b-btn variant="primary" block>Add</b-btn>
      </div>
    </b-card>
  </b-card-group>
  ...
</template>

<script>
export default {
  data () {
    return {
      showAll: false,
      clubs: [
        {id:1, description:'chelsea is the best club in the world and chelsea has a great player', price:1000, country:'england'},
        {id:2, description:'liverpool has salah', price:900, country:'england'},
        {id:3, description:'mu fans', price:800, country:'england'},
        {id:4, description:'city has a great coach. Thas is guardiola', price:700, country:'england'},
        {id:5, description:'arsenal player', price:600, country:'england'},
        {id:6, description:'tottenham in london', price:500, country:'england'},
        {id:7, description:'juventus stadium', price:400, country:'italy'},
        {id:8, description:'madrid sell ronaldo', price:300, country:'spain'},
        {id:9, description:'barcelona in the spain', price:200, country:'spain'},
        {id:10, description:'psg buys neymar at a fantastic price', price:100, country:'france'}
      ]
    }
  },
  computed: {
    formattedClubs () {
      return this.clubs.reduce((c, n, i) => {
        if (i % 4 === 0) c.push([]);
        c[c.length - 1].push(n);
        return c;
      }, []);
    }
  },
  methods: {
    getWord (desc) {
      if (this.showAll) return desc

      let value = desc;
      let length = 30;
      if (value.length <= length) {
        return value;
      } else {
        return value.substring(0, length) + '...';
      }
    }
  }
}
</script>

Это почти работает.Но когда я наведите курсор на описание в блоке 1, описание на всех других полях также будет зависать.Он должен только висеть, показывая усеченный текст в поле 1.

Как я могу решить эту проблему?

Ответы [ 3 ]

0 голосов
/ 01 октября 2018

Вы можете создать массив логических значений, в котором каждому значению соответствует команда.

let formattedClubs= [{name: "team1", description: "desc team1"}, {name: "team2", description: "desc team2"}];
let showDescription = Array.from(formattedClubs, show => false);

У вас есть начальный массив команды.Вы можете создать массив того же размера со значениями, инициализированными в false.

В вашем шаблоне

<b-card-group deck deck v-for="(row, index) in formattedClubs">

Теперь вы можете сопоставить команду в массиве formattedClubs[index] со значением в showDescription[index]

@mouseover="showDescription[index] = true" @mouseout="showDescription[index] = false"

То же в ваших событиях.

0 голосов
/ 01 октября 2018

Проблема в том, что у вас есть только одно свойство для управления усечением всех элементов.

Во-первых, вы должны убедиться, что у каждого клуба есть свой логический тип для управления усечением текста.Давайте используем уже существующее вычисленное свойство, чтобы добавить новое реактивное свойство для каждого клуба:

formattedClubs () {
  return this.clubs.reduce((c, n, i) => {
    if (i % 4 === 0) c.push([]);
    c[c.length - 1].push(n);
    this.$set(n, 'truncate', true); // Here we add the new reactive property.
    return c;
  }, []);
}

Во-вторых, давайте использовать <template> для обработки визуальных вещей, сохраняя правильное разделение интересов, используя нового человека.club.truncate свойство с блоком v-if / v-else:

<h4 class="card-title"
    @mouseenter="club.truncate = false"
    @mouseleave="club.truncate = true">
  <template v-if="club.truncate">{{trucateText(club.description)}}</template>
  <template v-else>{{club.description}}</template>
</h4>

И теперь, метод trucateText должен заботиться только о возвращении усеченного текста, так как он вызывается только если мыусечение описания одного клуба:

methods: {
  trucateText (value) {
    const length = 30;
    return value.length <= length ?
      value : value.substring(0, length) + "...";
  }
}

Взгляните на полностью рабочий код здесь , если какие-либо сомнения сохраняются.

0 голосов
/ 01 октября 2018

Попробуйте использовать ключевой атрибут для каждого элемента.Если вы установите указатель мыши для showAll, он непременно отобразит все описания, так как вернет true для всех.Вот почему вы должны выполнять рендеринг динамического списка здесь, который поддерживает Vue, аналогично этому:

<div v-for="club in row" :key="club.id">

Кроме того, я рекомендую вам взглянуть на официальную документацию о рендеринге динамического списка:

https://vuejs.org/v2/guide/list.html

...