使用 Dropzone.js 和 Vue.js

Use Dropzone.js with Vue.js

我正在尝试在通过 Vue.js 生成的 Rails 表单中使用 Dropzone.js。我已将 dropzone.js 文件放在 app/assets/javascripts/.

然后我创建了一个单文件 components/dropzone.vue 组件:

<template>
  <div id="image-drop"></div>
</template>

<script>
  export default {
    data() {
      return {
        greeting: 'blah'
      }
    },
    created: function() {
      var myDropzone = new Dropzone("div#image-drop", { url: "/file/post"});
    }
  }
</script>

<style></style>

我从我的主 vue 文件调用这个组件:

import Vue from 'vue/dist/vue.esm';
import dropzone from 'components/dropzone';

document.addEventListener('DOMContentLoaded', () => {
  const listingForm = new Vue({
    el: '#listing-multistep',
    data: {
      activeStep: 0
    },
    components: { dropzone }
  })
})

在我的Rails_form.html.erb部分我有

<fieldset class="listing-step" v-if="activeStep === 0">
  ...
</fieldset>

<fieldset class="listing-step" v-if="activeStep === 1">
  ...
</fieldset>

<fieldset class="listing-step" v-if="activeStep === 2">
  ...
</fieldset>

<fieldset class="listing-step" v-if="activeStep === 3">
  <h2>Images</h2>
  <div class="form-group">
    <dropzone></dropzone>
  </div>
</fieldset>

...

<button type="reset" @click="activeStep--" :disabled="activeStep === 0"/>
  Previous
</button>

<button type="reset" @click="activeStep++" :disabled="activeStep === stepList.length - 1"/>
  Next
</button>

但 Dropzone 未在 <div id="image-drop"> 上初始化。 知道我可能做错了什么吗?

提前致谢

初读这个问题时,我以为你已经创建了一个包装器组件,因为它使用了<dropzone></dropzone>。但从下面链接的 fiddle 来看,情况似乎并非如此。在 Vue 中使用外部库时,通常您希望将外部库功能包装在 Vue 组件中。这是一个非常的基本示例。

Vue.component("dropzone",{
  template: `<div></div>`,
  mounted(){
    new Dropzone(this.$el, {
        url: "/file/post"
    })
  }
})

Here is a pen 演示组件。

Dropzone 发射 many events,您可能希望自定义此基本组件以监听并发射到 Vue,以便它了解发生的事情。

原答案

创建组件时,div#image-drop还不存在。

使用mounted.

参见lifecycle diagram

如下所述,由于您隐藏了部分模板,您可能需要切换到 v-show 而不是 v-if。不同之处在于 v-show 将隐藏元素呈现给 DOM,但隐藏它们,而 v-if 直到需要它们时才呈现它们。

如果您想坚持使用 v-if,则需要将 watch 添加到 activeStep

watch:{
  activeStep(newVal){
    if (3 == newVal)
      this.$nextTick(() => new Dropzone("div#image-drop", { url: "/file/post"}))
  }
}