发生冲突的@Dragenter @Dragleave / v-show活动持续迅速

时间:2019-01-03 00:07:46

标签: javascript vue.js vuejs2 drag-and-drop draggable

Bug

指针事件:无;已经实现了,在调试中,对于“拖动”和“ dragonOL”,布尔值始终在true和false之间快速切换。

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并留给OL

当我将第二个Dragenter添加到OL标签时,将图像拖到该区域时,dragging和draggingOL的布尔值将以0.5s的间隔在true和false之间快速切换。对于CSS同样如此,显示和取消显示的速度非常快。

我尝试了几种方法,仅包括一个Dragenter,同样的问题。我不确定这可能与v-show有关。

Picture of <div> 上面是DIV标签的图像 Picture of 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 );
  }
}
})

我将继续测试,调试和更新此线程。

4 个答案:

答案 0 :(得分:2)

我有类似的问题。已解决,您需要防止Vue事件冒泡: Prevent event bubbling in Vue

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

答案 1 :(得分: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>

答案 2 :(得分:0)

解决方案是不使用@dragleave

我在手动触发图像的发布请求时(而不是使用@dragleave)将draggingOL的布尔值更改为false。

答案 3 :(得分:0)

我在代码中修复了下一个相同的问题:

  1. 删除了“ v-on:dragleave
  2. 上传(或刚刚选择)文件后运行' this.draggingOL = false '
  3. 添加了“ v-on:mouseleave =“ draggingOL = false” '

对我有用! 希望它可以帮助某人:)