簡體   English   中英

vue.js:如何處理同一元素上的 click 和 dblclick 事件

[英]vue.js: how to handle click and dblclick events on same element

我有一個帶有單獨事件的 vue 組件,用於單擊/dblclick。 單擊(取消)選擇行,dblclick 打開編輯表單。

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

這樣做,我會在雙擊時觸發 3 個事件。 兩個點擊事件和最后一個 dblclick。 由於點擊事件首先觸發,有沒有辦法(沒有將點擊事件延遲固定數量的毫秒)來停止雙擊點擊事件的傳播?

在這里擺弄

正如評論中所建議的,您可以通過設置一段時間(例如 x)的計時器來模擬 dblclick 事件。

  • 如果我們在這段時間內沒有再次點擊,請使用 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>

我使用這種方法解決同樣的問題。 我使用了一個通過觸發 200 毫秒超時或檢測到第二次點擊來解決的承諾。 它在我最近的網絡應用程序中運行良好。

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

組件

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

除非您需要對單個選擇執行昂貴的操作,否則您可以將 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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM