vue.js:如何处理同一元素上的click and dblClick事件



我有一个带有单独事件的VUE组件,可单击/dblclick。单击(de)选择行,dblClick打开编辑表单。

<ul class="data_row"
  v-for="(row,index) in gridData"
  @dblclick="showEditForm(row,$event)"
  @click="rowSelect(row,$event)"
>

这样做,我会通过双击发射3个事件。两次点击事件,最后是一个DBLICK。由于单击事件首先触发,是否有办法(延迟点击事件以获取固定数量的MS),以停止单击事件的传播,双击?

小提琴

如注释中所建议的,您可以通过在一定时间段内设置计时器来模拟DBLCLICK事件(例如X)。

  • 如果我们在那段时间跨度没有再次单击,请选择single_click_function()。
  • 如果我们确实得到一个,请致电double_click_function()。
  • 收到第二次点击后将清除计时器。
  • 一旦X毫秒毫无疑问,它也将被清除。

请参阅下面的代码和工作小提琴。

new Vue({
    el: '#app',
    data: {
        result: [],
        delay: 700,
        clicks: 0,
        timer: null
    },    
     mounted: function() {
        console.log('mounted');
     },      
     methods: {
        oneClick(event) {
          this.clicks++;
          if (this.clicks === 1) {
            this.timer = setTimeout( () => {
              this.result.push(event.type);
              this.clicks = 0
            }, this.delay);
          } else {
             clearTimeout(this.timer);  
             this.result.push('dblclick');
             this.clicks = 0;
          }         
        }      
     }
});
<div id="example-1">
 <button v-on:dblclick="counter += 1, funcao()">Add 1</button>
   <p>The button above has been clicked {{ counter }} times.</p>
</div>
var example1 = new Vue({
 el: '#example-1',
 data: {
   counter: 0
 },
 methods: {
   funcao: function(){
     alert("Sou uma funcao");
   }
 }
})

查看此工作小提琴https://codepen.io/robertourias/pen/lxvnzx

我有一个更简单的解决方案(我正在使用vue-class,但相同的原理适用):

private timeoutId = null;
onClick() {
        if(!this.timeoutId)
        {
            this.timeoutId = setTimeout(() => {
                // simple click
            }, 50);//tolerance in ms
        }else{
            clearTimeout(this.timeoutId);
            // double click
        }
    }

它不需要计算点击次数。

单击和单击之间必须短时间。

为了获得点击和双击,只需要一个计数器即可携带点击数(例如0.2s),并且当用户慢慢单击或执行几个将会捕获用户的意图是双击或默认情况的情况。

我留下了我如何实现这些功能的代码。

new Vue({
   el: '#app',
   data: {numClicks:0, msg:''},
   methods: {
      // detect click event
      detectClick: function() {
        this.numClicks++;
        if (this.numClicks === 1) {          // the first click in .2s
            var self = this;
            setTimeout(function() {
                switch(self.numClicks) {     // check the event type
                      case 1:
                        self.msg = 'One click';
                        break;
                      default:
                        self.msg = 'Double click';
                }
                self.numClicks = 0;               // reset the first click
            }, 200);                              // wait 0.2s
        } // if
      }  // detectClick function
   }
});
span { color: red }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.0/vue.js"></script>
<div id='app'>
  <button @click='detectClick'>
    Test Click Event, num clicks
    <span>{{ numClicks }}</span>
   </button>
  <h2>Last Event: <span>{{ msg }}</span></h2>
</div>

我将此方法用于同一问题。我使用的承诺可以通过触发200ms的超时或第二次点击被检测到的承诺。它在我最近的Web应用程序中运行良好。

<div id="app">
  <div 
    @click="clicked().then((text) => {clickType = text})">
      {{clickType}}
  </div>
</div>
<script>
new Vue({
  el: "#app",
  data: {
    click: undefined,
    clickType: 'Click or Doubleclick ME'
  },
  methods: {
    clicked () {
      return new Promise ((resolve, reject) => {
        if (this.click) {
          clearTimeout(this.click)
          resolve('Detected DoubleClick')
        }
        this.click = setTimeout(() => {
         this.click = undefined
         resolve('Detected SingleClick')
        }, 200)
      })
    }
  }
})
</script>

工作小提琴:https://jsfiddle.net/mapletonemartin/9m62lrwf/

vue component

// html 
 <div class="grid-content">
    <el-button 
   @click.native="singleClick" 
   @dblclick.native="doubleClick" 
   class="inline-cell">
    click&dbclickOnSameElement</el-button>
 </div>
// script
<script>
let time = null;  // define time be null 
export default {
  name: 'testComponent',
  data() {
    return {
       test:''
    };
  },
  methods: {
   singleClick() {
     // first clear  time
      clearTimeout(time);
      time = setTimeout(() => {
        console.log('single click ing')
      }, 300); 
    },
  
   doubleClick() {
      clearTimeout(time);  
      console.log('double click ing');
    }
  }
}
</script>
selectedFolder = ''; // string of currently selected item
folderSelected = false; // preview selected item
selectFolder(folder) {
    if (this.selectedFolder == folder) {
        // double click
      this.folderSelected = false;
      this.$store.dispatch('get_data_for_this_folder', folder);
    } else {
      // single click
      this.selectedFolder = folder;
      this.folderSelected = true;
    }
},

@click.stop 单击单击,@dblclick.stop 处理双击

<v-btn :ripple="false"
            class="ma-0"
            @click.stop="$emit('editCompleteGrvEvent', props.item)"
            @dblclick.stop="$emit('sendCompleteGrvEvent',props.item)">
    <v-icon>send</v-icon>
    </v-btn>

,除非您需要在Single Select上进行昂贵的操作,否则您可以将Rowselect重新处理为切换。与设置和取消计时器相比,设置一个简单的数组将更快,可靠和更简单。单击事件是否两次启动并不重要,但是您可以在编辑功能中轻松处理。

<template>
  <ul>
    <li :key="index" v-for="(item, index) in items">
      <a
        :class="{ 'active-class': selected.indexOf(item) !== -1 }"
        @click="toggleSelect(item)"
        @dblclick="editItem(item)"
      >
        {{ item.title }}
      </a>
      <!-- Or use a checkbox with v-model
      <label @dblclick="editItem(item)">
        <input type="checkbox" :value="item.id" v-model.lazy="selected" />
        {{ item.title }}
      </label>
      -->
    </li>
  </ul>
</template>
<script>
export default {
  data: function () {
    return {
      items: [
        {
          id: 1,
          title: "Item 1",
        },
        {
          id: 2,
          title: "Item 2",
        },
        {
          id: 3,
          title: "Item 3",
        },
      ],
      selected: [],
    };
  },
  methods: {
    editItem(item) {
      /*
       * Optionally put the item in selected
       * A few examples, pick one that works for you:
       */
      // this.toggleSelect(item); // If the item was selected before dblclick, it will still be selected. If it was unselected, it will still be unselected.
      // this.selected = []; // Unselect everything.
      // Make sure this item is selected:
      // let index = this.selected.indexOf(item.id);
      // if (index === -1) {
      //   this.selected.push(item.id);
      // }
      // Make sure this item is unselected:
      // let index = this.selected.indexOf(item.id);
      // if (index !== -1) {
      //   this.selected.splice(index, 1);
      // }
      this.doTheThingThatOpensTheEditorHere(item);
    },
    toggleSelect(item) {
      let index = this.selected.indexOf(item.id);
      index === -1
        ? this.selected.push(item.id)
        : this.selected.splice(index, 1);
    },
    // For fun, get an array of items that are selected:
    getSelected() {
      return this.items.filter((item) => this.selected.indexOf(item.id) !== -1);
    },
  },
};
</script>

最新更新