Vue文字高亮事件

时间:2019-01-31 11:41:38

标签: vue.js vuejs2 vuetify.js

我有一个data table包含可点击的行。一切正常,我遇到了一个问题。如果我要突出显示行上的文本,则会触发click event。我发现唯一可以帮助的是.exact修饰符。 如果文本突出显示,希望它会忽略单击处理程序。但是click event仍然被触发。

我的问题:是否可以在不触发点击事件的情况下突出显示项目上的文本。

预期结果:突出显示文本时使用@click.exact不会触发点击事件

实际结果:突出显示文本时触发点击事件,事件使用@click.exact

边注:它可以突出显示文本,但是一旦您松开鼠标按钮,它就会触发单击事件。

<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>

编辑其他尝试@click.prevent也不起作用

到目前为止最好的解决方法:https://codepen.io/anon/pen/YBNLLy

1 个答案:

答案 0 :(得分:1)

好的,在@click.stop上尝试TD,这将阻止事件传播到父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(及更低版本),请查看this post,了解一种备用文本选择获取方法。