【问题标题】:Applying DropZone bootstrap example under React JS在 React JS 下应用 DropZone 引导示例
【发布时间】:2017-06-19 16:22:12
【问题描述】:

我正在尝试在 ReactJS 下应用 Dropzone bootstrap example,如下面的代码所示。

但由于某种原因,开始上传/取消上传和进度条的行为不一致。

示例 1:即使我取消了所有要上传的文件,进度条也会显示无休止的进度。 示例 2:开始上传单个文件不会做任何事情。

有人可以告诉我我在这里做错了什么/遗漏了什么,我怎样才能像示例一样完成这项工作?

注意:如果可能,基于第一次回复,使用 Refs

import React from 'react';
import { connect } from 'react-redux';

@connect((state) => state)
export default class DZUploader extends React.Component {

  componentDidMount() {

  let previewNode = document.querySelector("#template");
  previewNode.id = "";

  let previewTemplate = previewNode.parentNode.innerHTML;
  previewNode.parentNode.removeChild(previewNode);

  let myDropzone = new Dropzone(document.body, {
    url: "/target-url", // Set the url
    paramName: "file", // The name that will be used to transfer the file
    maxFilesize: 2, // MB
    thumbnailWidth: 80,
    thumbnailHeight: 80,
    parallelUploads: 20,
    previewTemplate: previewTemplate,
    autoQueue: false,
    previewsContainer: "#previews",
    clickable: ".fileinput-button",
  });

  myDropzone.on('addedfile', function(file){
    console.log(file);
    file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
  });

  myDropzone.on('totaluploadprogress', function(progress){
    console.log(progress);
    document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
  });

  myDropzone.on('sending', function(file){
    // Show the total progress bar when upload starts
    document.querySelector("#total-progress").style.opacity = "1";
    // And disable the start button
    file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
  });

  myDropzone.on('queuecomplete', function(progress){
    document.querySelector("#total-progress").style.opacity = "0";
  });

  document.querySelector("#actions .start").onclick = function() {
    myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
  };
  document.querySelector("#actions .cancel").onclick = function() {
    myDropzone.removeAllFiles(true);
  };


  }

  render() {
    return (
      <div>

          <div id="actions" className="row">

              <div className="col-lg-7">
                <span className="btn btn-success fileinput-button dz-clickable">
                    <i className="glyphicon glyphicon-plus"></i>
                    <span>Add files...</span>
                </span>
                <button type="submit" className="btn btn-primary start">
                    <i className="glyphicon glyphicon-upload"></i>
                    <span>Start upload</span>
                </button>
                <button type="reset" className="btn btn-warning cancel">
                    <i className="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel upload</span>
                </button>
              </div>
              <div className="col-lg-5">
                <span className="fileupload-process">
                  <div id="total-progress" className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                    <div className="progress-bar progress-bar-success" data-dz-uploadprogress=""></div>
                  </div>
                </span>
              </div>

          </div>

          <div className="table table-striped" className="files" id="previews">
            <div id="template" className="file-row">
              <div>
                  <span className="preview"><img data-dz-thumbnail /></span>
              </div>
              <div>
                  <p className="name" data-dz-name></p>
                  <strong className="error text-danger" data-dz-errormessage></strong>
              </div>
              <div>
                  <p className="size" data-dz-size></p>
                  <div className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                    <div className="progress-bar progress-bar-success" data-dz-uploadprogress></div>
                  </div>
              </div>
              <div>
                <button className="btn btn-primary start">
                    <i className="glyphicon glyphicon-upload"></i>
                    <span>Start</span>
                </button>
                <button data-dz-remove className="btn btn-warning cancel">
                    <i className="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel</span>
                </button>
                <button data-dz-remove className="btn btn-danger delete">
                  <i className="glyphicon glyphicon-trash"></i>
                  <span>Delete</span>
                </button>
              </div>
            </div>
          </div>

      </div>
    );
  }
}

【问题讨论】:

    标签: reactjs dropzone.js


    【解决方案1】:

    三件事:

    1. 使用componentDidMount生命周期方法并不意味着$(JQuery)和dropzone都已经加载到DOM中了

    2. 使用 React Refs 代替选择器,这样你的组件就保持一致

    3. 您应该使用导入键导入 dropzone 对象并避免 jquery 依赖 (import dropzone from 'dropzone')。

    结论:

    避免在不需要时使用 Jquery,至少在这种情况下是这样。

    作为我建议的结论,您的组件应如下所示:

    import React from 'react';
    import { connect } from 'react-redux';
    import Dropzone from 'dropzone';
    
    @connect((state) => state)
    export default class DZUploader extends React.Component {
    
      constructor(props) {
        super(props);
    
        this.focus = this.focus.bind(this);
        this.onAddedfile = this.onAddedfile.bind(this);
        this.onTotaluploadprogress = this.onTotaluploadprogress.bind(this);
        this.onSending = this.onSending.bind(this);
        this.onQueuecomplete = this.onQueuecomplete.bind(this);
        this.onActionStartClick = this.onActionStartClick.bind(this);
        this.onActionCancelClick = this.onActionCancelClick.bind(this);
      }
    
      componentDidMount() {
        const previewNode = this.divTemplate;
        previewNode.id = "";
    
        const previewTemplate = previewNode.parentNode.innerHTML;
        previewNode.parentNode.removeChild(previewNode);
    
        const myDropzone = new Dropzone(document.body, {
          url: "/target-url", // Set the url
          paramName: "file", // The name that will be used to transfer the file
          maxFilesize: 2, // MB
          thumbnailWidth: 80,
          thumbnailHeight: 80,
          parallelUploads: 20,
          previewTemplate: previewTemplate,
          autoQueue: false,
          previewsContainer: "#previews",
          clickable: ".fileinput-button",
        });
    
        myDropzone.on('addedfile', onAddedfile);
        myDropzone.on('totaluploadprogress', onTotaluploadprogress);
        myDropzone.on('sending', onSending);
        myDropzone.on('queuecomplete', onQueuecomplete);
    
        this.actionStart.onclick = onActionStartClick;
        this.actionStart.onclick = onActionCancelClick;
      }
    
      onAddedfile(file) {
        console.log(file);
        file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
      }
    
      onTotaluploadprogress(progress) {
        console.log(progress);
        this.progressBar.style.width = progress + "%";
      }
    
      onSending(file) {
        // Show the total progress bar when upload starts
        this.totalProgress.style.opacity = "1";
        // And disable the start button
        file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
      }
    
      onQueuecomplete(progress) {
        this.totalProgress.style.opacity = "0";
      }
    
      onActionStartClick() {
        myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
      }
    
      onActionCancelClick() {
        myDropzone.removeAllFiles(true);
      }
      render() {
        return (
          <div>
    
              <div id="actions" className="row">
    
                  <div className="col-lg-7">
                    <span className="btn btn-success fileinput-button dz-clickable">
                        <i className="glyphicon glyphicon-plus"></i>
                        <span>Add files...</span>
                    </span>
                    <button type="submit" className="btn btn-primary start" ref={(button) => { this.actionStart = button; }}>
                        <i className="glyphicon glyphicon-upload"></i>
                        <span>Start upload</span>
                    </button>
                    <button type="reset" className="btn btn-warning cancel" ref={(button) => { this.actionCancel = button; }}>
                        <i className="glyphicon glyphicon-ban-circle"></i>
                        <span>Cancel upload</span>
                    </button>
                  </div>
                  <div className="col-lg-5">
                    <span className="fileupload-process">
                      <div id="total-progress" ref={(div) => { this.totalProgress = div; }} className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                        <div className="progress-bar progress-bar-success" ref={(div) => { this.progressBar = div; }} data-dz-uploadprogress=""></div>
                      </div>
                    </span>
                  </div>
    
              </div>
    
              <div className="table table-striped" className="files" id="previews">
                <div id="template" ref={(div) => { this.divTemplate = div; }} className="file-row">
                  <div>
                      <span className="preview"><img data-dz-thumbnail /></span>
                  </div>
                  <div>
                      <p className="name" data-dz-name></p>
                      <strong className="error text-danger" data-dz-errormessage></strong>
                  </div>
                  <div>
                      <p className="size" data-dz-size></p>
                      <div className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                        <div className="progress-bar progress-bar-success" data-dz-uploadprogress></div>
                      </div>
                  </div>
                  <div>
                    <button className="btn btn-primary start">
                        <i className="glyphicon glyphicon-upload"></i>
                        <span>Start</span>
                    </button>
                    <button data-dz-remove className="btn btn-warning cancel">
                        <i className="glyphicon glyphicon-ban-circle"></i>
                        <span>Cancel</span>
                    </button>
                    <button data-dz-remove className="btn btn-danger delete">
                      <i className="glyphicon glyphicon-trash"></i>
                      <span>Delete</span>
                    </button>
                  </div>
                </div>
              </div>
    
          </div>
        );
      }
    }
    

    【讨论】:

    • 感谢您的帮助,从 #3 开始,我已经将 dropzone 作为依赖项包含在项目 bower.json 中,因此它已经包含在内。从#2开始,您是否介意提供一个在我的代码中应用 Refs 的示例,例如在尝试获取模板 div 时?我查看了文档参考,但无法使其正常工作。谢谢
    • @MChan 见上面的例子,它包含refs 的实现。很简单。
    【解决方案2】:

    下面是 React + Dropzone + Relay 使用的演示。

    在您的组件中使用 Dropzone。

    <Dropzone style={{disply: 'none'}} disableClick={true}  ref="dropzone" onDrop={this.onDrop}/>
    

    实现onDrop函数,这里我正在做一个Relay突变,如果你没有使用relay,那么这里应该发出post请求来上传你的文件。

    onDrop: function(files) {
      /*
      * TODO fire mutliple mutations triggars warnings
      */
      files.forEach((file)=> {
        Relay.Store.commitUpdate(
          new AddImageMutation({
            file,
            images: this.props.User,
          })
        );
      });
    }
    

    以上代码可以在relay-gallery找到

    现场演示http://fanjin.computer/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-15
      • 2020-09-13
      • 2018-12-24
      • 2019-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多