Dropzone 实例适用于第一个元素但不适用于克隆元素(Vue)

Dropzone instance works on first element but not cloned elements (Vue)

我在下面有一个片段,它基本上是我目前的整个代码块,它基本上创建了一个 div,当你点击“添加另一个区域”时,它会克隆那个 div。这允许用户输入多行信息,每行都有自己的结果和图像。

问题是,由于我的卡设置,我成功地克隆了所有具有自己独特身份的东西。但是,dropzone 没有复制。第一个文件 dropzone 表单可以完美运行,但是当我克隆 div 并在页面上有 2 个或更多 dropzone 实例时,它们不起作用(它们不显示上传图像文本或任何内容)

如何才能将相同的逻辑成功应用到此处的 dropzone 实例?

new Vue({
          components: {},
          el: "#commonNameDiv",
          data() {
            return {
              searchString: [''],
              results: [],
              savedAttributes: [],
              cards: [],
              showList: false,
              zoneNumber:[],
              imageZoneNames: []            }
          },
          methods: {
            autoComplete(ev, card) {
              this.results = [];
              console.log(this.searchString);
              if (ev.target.value.length > 2) {
                axios.get('/product/parts/components/search', {
                  params: {
                    searchString: ev.target.value
                  }
                }).then(response => {
                  card.results = response.data;
                  this.showList = true;
                  console.log(this.results);
                  console.log(this.searchString);
                });
              }
            },
            saveAttribute(result, card) {
              card.value = result.attribute_value;
              card.results = [];
              card.zone = this.zoneNumber;
              this.showList = false;
            },
            addCard: function() {
                this.cards.push({
                  index: "",
                  value: "",
                  zoneNumber: "",
                  results: [],
                  componentImage:""
                });

                console.log(this.cards);
            },
            hideDropdown() {
              this.showList = false;
            },

          },
          created() {

                this.addCard();

                let instance = this;

                Dropzone.options = {
                    maxFilesize: 12,
                    renameFile: function (file) {
                        var dt = new Date();
                        var time = dt.getTime();
                        return time + file.name;
                    },
                    acceptedFiles: ".jpeg,.jpg,.png,.gif",
                    addRemoveLinks: true,
                    timeout: 50000,
                    removedfile: function (file) {
                        console.log(file.upload.filename);
                        var name = file.upload.filename;

                        var fileRef;
                        return (fileRef = file.previewElement) != null ?
                            fileRef.parentNode.removeChild(file.previewElement) : void 0;

                    },
                    init: function() {
                        this.on("addedfile", 
                        function(file) { 
                            instance.imageZoneNames.push({name: file.upload.filename, desc: 'Line Drawing'});
                            console.log(file);
                            console.log(instance.imageZoneNames);
                        });
                    }
                };
                }
        })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/dropzone.js"></script>


<div id="commonNameDiv">
<div class="uk-grid" v-for="(card, i) in cards" :key="i">
                    <div class="uk-width-1-10"  >
                        <input v-model=" card.zoneNumber" size="4" type="text" name="mapNumber">
                    </div>
                    <div class="uk-width-6-10">
                        <input
                          style="width:100%"
                          placeholder="what are you looking for?"
                          v-model="card.value"
                          v-on:keyup="autoComplete($event, card)"
                        >
                        <div v-if="showList"  class="panel-footer componentList" v-if="card.results.length">
                          <ul>
                            <li  v-for="(result, i) in card.results" :key="i">
                              <a v-on:click="saveAttribute(result, card)">@{{ result.attribute_value }}</a>
                            </li>
                          </ul>
                        </div>
                    </div>
                    <div class="uk-width-3-10">
                        <form method="post" action="{{url('product/parts/upload/store')}}" enctype="multipart/form-data"
                              class="dropzone">
                        </form>
                    </div>
                </div>

  <div style="height: 35px;">

  </div>

<div>
                    <a v-on:click="addCard">Add another zone</a>
                </div>
</div>

实际上正在创建,但Dropzone并未重建。 我认为您必须创建一个新的 Dropzone 实例。

如果您尝试插入:

created() {

    this.addCard();
    var myDropzone = new Dropzone('.dropzone')
    let instance = this;

    Dropzone.options.myDropzone = {

甚至将选项添加到 addCard 方法或设置一个 setupDropzones 方法并将其添加到 addCard 方法。

当您实例化 Dropzone class 时,它会自动查找要在 dropzones 中转换的元素(默认情况下,具有 .dropzone class 的元素)。

您似乎想要动态添加作为拖放区的元素。然后你需要自己触发dropzone转换。

我建议您禁用 autoDiscover 选项,并手动指定要转换为拖放区的每个元素:

addCard() {
    this.cards.push({
    ...
    });
    let cardIndex = this.cards.length - 1;

    // Waiting for the element #dropzone-X to exist in DOM
    Vue.nextTick(function () {
        new Dropzone("#dropzone-"+cardIndex, {
           ...
        });
    });
},
created() {
    ...
    Dropzone.autoDiscover = false
    // no new Dropzone()
    ...

    // Starting setup
    this.addCard();
},
<form ... class="dropzone" v-bind:id="'dropzone-'+i">

工作jsbin

有几种方法可以select转换元素($refs, ids, classes),这里我建议使用ids。

doc on programmatically creating dropzones