Событие выделения текста Vue - PullRequest
0 голосов
/ 31 января 2019

У меня есть таблица данных , содержащая кликабельные строки.Все работает хорошо, я столкнулся с одной проблемой.Если я хочу выделить текст в строке, срабатывает click event.Единственное, что я смог найти, это модификатор .exact .Надеясь, он будет игнорировать обработчик кликов, если текст выделен.Но click event по-прежнему срабатывает.

Мой вопрос : есть ли способ выделить текст на элементе, не вызывая событие щелчка.

Ожидаемый результат : использование @click.exact не будет вызывать событие щелчка при выделении текста

Фактический результат : событие щелчка вызывается при выделении текста, событие с использованием @click.exact

Side Note : ему удается выделить текст, но как только вы отпустите кнопку мыши, оно вызовет событие щелчка.

<v-data-table
    v-show="model.id && !editMode"
    :headers="bagHeaders"
    :items="bags"
    class="elevation-1"
    item-key="id"
    :loading="bagsStatus.loading"
    :pagination.sync="pagination"
    >
        <template slot="items" slot-scope="props">
            <tr @click.exact="onBagClick(props.item.id)">
                <td class="text-xs-left" v-for="header in bagHeaders" :key="header.id">{{ formatColumn(header, props.item) }}</td>
            </tr>
        </template>
</v-data-table>

Edit : Другие попытки : @click.prevent также не работает

Лучшая работа на данный момент: https://codepen.io/anon/pen/YBNLLy

1 Ответ

0 голосов
/ 31 января 2019

ОК, попробуйте @click.stop на TD s, который останавливает распространение события на родительский TR.

Поскольку вы хотите сохранить нормальное поведение щелчка строк при определенных условиях, вы можете добавитьметод проверки, выполняется ли выделение текста во время щелчка и продолжается остановка распространения события, в противном случае вызывается метод onBagClick() родительского TR:

new Vue({
  el: '#app',

  methods: {
    onBagClick(id) {
      alert('Bag Click');
    },

    checkMouseAction(e) {
      const isTextHighlighting = window.getSelection().toString().trim() !== '';

      if (!isTextHighlighting) {
        e.target.parentElement.click();

        // Or call the this.onBagClick() instead
      }
    }
  }
})
table {
  border-collapse: collapse;
}

table td {
  border: 1px solid;
  padding: 10px;
}

table td:first-child {
  background-color: lavender;
}

table td:last-child {
  background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <table>
    <tr @click="onBagClick">
      <td @click.stop="checkMouseAction">Selectable text. Left-click and drag these lines with your mouse.</td>
      <td>Hardly selectable text. An alert dialog will get in the way by popping up.</td>
    </tr>
  </table>
</div>

Изменения

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

Рабочая демонстрация

new Vue({
  el: '#app',
  data() {
    return {
      headers: [
        {
          text: 'Dessert (100g serving)',
          align: 'left',
          sortable: false,
          value: 'name'
        }, 
        {
          text: 'Calories',
          value: 'calories'
        }, 
        {
          text: 'Fat (g)',
          value: 'fat'
        }, 
        {
          text: 'Carbs (g)',
          value: 'carbs'
        }, 
        {
          text: 'Protein (g)',
          value: 'protein'
        }, 
        {
          text: 'Iron (%)',
          value: 'iron'
        }
      ],
      desserts: [
        {
          name: 'Frozen Yogurt',
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          iron: '1%'
        }, 
        {
          name: 'Ice cream sandwich',
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3,
          iron: '1%'
        }, 
        {
          name: 'Eclair',
          calories: 262,
          fat: 16.0,
          carbs: 23,
          protein: 6.0,
          iron: '7%'
        }, 
        {
          name: 'Cupcake',
          calories: 305,
          fat: 3.7,
          carbs: 67,
          protein: 4.3,
          iron: '8%'
        }, 
        {
          name: 'Gingerbread',
          calories: 356,
          fat: 16.0,
          carbs: 49,
          protein: 3.9,
          iron: '16%'
        }, 
        {
          name: 'Jelly bean',
          calories: 375,
          fat: 0.0,
          carbs: 94,
          protein: 0.0,
          iron: '0%'
        }, 
        {
          name: 'Lollipop',
          calories: 392,
          fat: 0.2,
          carbs: 98,
          protein: 0,
          iron: '2%'
        }, 
        {
          name: 'Honeycomb',
          calories: 408,
          fat: 3.2,
          carbs: 87,
          protein: 6.5,
          iron: '45%'
        }, 
        {
          name: 'Donut',
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          iron: '22%'
        }, 
        {
          name: 'KitKat',
          calories: 518,
          fat: 26.0,
          carbs: 65,
          protein: 7,
          iron: '6%'
        }
      ]
    }
  },
  methods: {
    onBagClick(id) {
      const isTextHighlighting = window.getSelection().toString().trim() !== '';

      if (!isTextHighlighting) {
        alert("Bag Click");
      }
    }
  }
})
@import url('https://fonts.googleapis.com/css?family=Roboto|Material+Icons');
<link href="https://cdn.jsdelivr.net/npm/vuetify@1.4.4/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@1.4.4/dist/vuetify.min.js"></script>

<div id="app">
  <v-app id="inspire">
    <v-data-table :headers="headers" :items="desserts" class="elevation-1">
      <template slot="items" slot-scope="props">
        <tr @click="onBagClick(props.item.id)"> 
          <td class="text-xs-left" 
            v-for="header in props.item" 
            :key="header.id">{{header}}</td>
        </tr>
      </template>
    </v-data-table>
  </v-app>
</div>

Я использую window.getSelection() для чтения выбранных текстов.Если вы заботитесь о поддержке IE 8 (и ниже), взгляните на в этом посте , чтобы найти альтернативный подход к сбору текста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...