冲突的 @Dragenter @Dragleave / v-show 事件不断地触发

3

Bug

pointer-events: none; 已经被实现,在调试中,布尔值在“拖动”和“draggingOL”两者之间迅速切换。

HTML结构

     <ol id="product-images" @dragenter="draggingOL=true" @dragleave="draggingOL=false">

        <li v-for="(file, key) in files" style="pointer-events: none;"></li>

      </ol>


      <div v-show="files.length < 1 || draggingOL == true">
         <div ref="fileform" :class="['next-upload-dropzone', dragging ? 'css1' : '', draggingOL ? 'css1 css2' : '']" @dragenter="dragging=true" @dragleave="dragging=false">

         </div>
      </div>

基本上,当您将图像拖入DIV标记后,OL标记将出现。

OL标记没有可拖动属性,因此我将Dragenter和leave添加到了OL中。

当我将第二个dragenter添加到OL标记时,当您将图像拖入该区域时,dragging和draggingOL的布尔值将在0.5秒间隔内迅速在true和false之间切换。CSS也是如此,非常快速地显示和隐藏。

我尝试了几种方法,包括仅使用一个dragenter ONLY,但问题仍然存在。也许问题出在v-show上,我不确定。

<div>图片 以上是DIV标记的图片 OL图片 以上是OL标记的图片

Javascript

var dropFileApp = new Vue({
    el: '#dropfile',
    data: {
        dragAndDropCapable: false,
        dragging : false,
        draggingOL : false,
        files: [],
        uploadPercentage: 0
    },
    // define methods under the `methods` object
    mounted(){
  /*
    Determine if drag and drop functionality is capable in the browser
  */
  this.dragAndDropCapable = this.determineDragAndDropCapable();

  /*
    If drag and drop capable, then we continue to bind events to our elements.
  */
  if( this.dragAndDropCapable ){
    /*
      Listen to all of the drag events and bind an event listener to each
      for the fileform.
    */
    ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach( function( evt ) {
      /*
        For each event add an event listener that prevents the default action
        (opening the file in the browser) and stop the propagation of the event (so
        no other elements open the file in the browser)
      */
      this.$refs.fileform.addEventListener(evt, function(e){
        e.preventDefault();
        e.stopPropagation();
      }.bind(this), false);
    }.bind(this));

    /*
      Add an event listener for drop to the form
    */

    this.$refs.fileform.addEventListener('drop', function(e){
      /*
        Capture the files from the drop event and add them to our local files
        array.
      */
      for( let i = 0; i < e.dataTransfer.files.length; i++ ){
        this.files.push( e.dataTransfer.files[i] );
        this.getImagePreviews();
      }
      console.log((this.files.length))
      /*
        Instantly upload files
      */
      this.submitFiles();
    }.bind(this));
  }
},

methods: {
  /*
    Determines if the drag and drop functionality is in the
    window
  */
  determineDragAndDropCapable(){
    /*
      Create a test element to see if certain events
      are present that let us do drag and drop.
    */
    var div = document.createElement('div');

    /*
      Check to see if the `draggable` event is in the element
      or the `ondragstart` and `ondrop` events are in the element. If
      they are, then we have what we need for dragging and dropping files.

      We also check to see if the window has `FormData` and `FileReader` objects
      present so we can do our AJAX uploading
    */
    return ( ( 'draggable' in div )
            || ( 'ondragstart' in div && 'ondrop' in div ) )
            && 'FormData' in window
            && 'FileReader' in window;
  },

  /*
    Gets the image preview for the file.
  */
  getImagePreviews(){
    /*
      Iterate over all of the files and generate an image preview for each one.
    */
    for( let i = 0; i < this.files.length; i++ ){
      /*
        Ensure the file is an image file
      */
      if ( /\.(jpe?g|png|gif)$/i.test( this.files[i].name ) ) {
        /*
          Create a new FileReader object
        */
        let reader = new FileReader();

        /*
          Add an event listener for when the file has been loaded
          to update the src on the file preview.
        */
        reader.addEventListener("load", function(){
          this.$refs['preview'+parseInt( i )][0].src = reader.result;
        }.bind(this), false);

        /*
          Read the data for the file in through the reader. When it has
          been loaded, we listen to the event propagated and set the image
          src to what was loaded from the reader.
        */
        reader.readAsDataURL( this.files[i] );
      }else{
        /*
          We do the next tick so the reference is bound and we can access it.
        */
        this.$nextTick(function(){
          this.$refs['preview'+parseInt( i )][0].src = '/images/file.png';
        });
      }
    }
  },

  /*
    Submits the files to the server
  */
  submitFiles(){
    /*
      Initialize the form data
    */
    let formData = new FormData();

    /*
      Iteate over any file sent over appending the files
      to the form data.
    */
    for( var i = 0; i < this.files.length; i++ ){
      let file = this.files[i];

      formData.append('files[' + i + ']', file);
    }

    /*
      Make the request to the POST /file-drag-drop URL
    */
    axios.post( '/file-drag-drop',
      formData,
      {
        headers: {
            'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: function( progressEvent ) {
        //Showing Loading   
        }.bind(this)
      }
    ).then(function(){
      console.log('SUCCESS!!');
    })
    .catch(function(){
      console.log('FAILURE!!');
    });
  },

  /*
    Removes a select file the user has uploaded
  */
  removeFile( key ){
    this.files.splice( key, 1 );
  }
}
})

我将继续测试、调试和更新这个线程。


看起来你的 v-show 正在切换可见性。当可见性改变时,drag-leave 也会发生变化。你能否提供一个 jsfiddle 或者可运行的代码来隔离这个问题?这样可能更容易提供解决方案。 - Daniel
@Daniel无法让CSS起作用,我认为我的CSS现在太乱了,嗯好的,谢谢你关于v-show的建议。 - CodeGuru
4个回答

3

我曾经遇到类似的问题,后来解决了。你需要防止Vue事件的事件冒泡: 防止Vue中的事件冒泡

<div v-on:dragleave.self="dragLeave($event)">
    ...
</div>

1

我通过在我的覆盖层上添加一个透明的叠加层来解决了这个问题:

<div style="position: relative"
   @dragenter.prevent.stop="dropzone = true"
   @dragover.prevent.stop="dropzone = true"
  >
    <!-- Bunch of other stuff here -->

    <div v-if="dropzone" class="dropzone" >
      <i class="material-icons">cloud_upload</i>
      <div class="dropzone_text">Drop files here</div>

      <!-- transparent, catches drop & dragleave events -->

      <div style="width: 100%; height: 100%; position: absolute"
        @drop.prevent.stop="dropzone = false"
        @dragleave.prevent.stop="dropzone = false"
      ></div>
</div>


不错的建议。 - CodeGuru

1
我在我的代码中解决了相同的问题,做法如下:
  1. 删除"v-on:dragleave"
  2. 当文件上传(或仅选择)时运行'this.draggingOL=false'
  3. 添加'v-on:mouseleave="draggingOL=false"'
这对我起作用了!希望能帮到别人 :)

0

解决方案是不使用@dragleave

我改变了拖动OL的布尔值为false,手动触发图片的post请求,而不是使用@dragleave。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接