动态变化的道具

时间:2018-08-20 22:31:07

标签: javascript vue.js

在我的应用上,我有多个“上传”按钮,当用户单击该按钮时,我想显示该特定按钮的微调器/加载器。上传完成后,我要删除该微调器/加载器。

我将按钮嵌套在组件中,因此在按钮的文件上,我从父级那里收到一个道具,然后将其存储在本地,这样加载程序就不会出现在所有上传按钮上。但是当父级中的值发生变化时,子级将无法获得正确的道具价值。

App.vue:

<template>
  <upload-button
    :uploadComplete="uploadCompleteBoolean"
    @startUpload="upload">
  </upload-button>
</template>

<script>
  data(){
    return {
      uploadCompleteBoolean: true
    }
  },

  methods: {
    upload(){
      this.uploadCompleteBoolean = false
      // do stuff to upload, then when finished,
      this.uploadCompleteBoolean = true
    }

</script>

Button.vue:

<template>
  <button
    @click="onClick">
  <button>
</template>


<script>
  props: {
    uploadComplete: {
      type: Boolean
    }

  data(){
    return {
      uploadingComplete: this.uploadComplete
    }
  },

  methods: {
    onClick(){
      this.uploadingComplete = false
      this.$emit('startUpload')
    }

</script>

3 个答案:

答案 0 :(得分:1)

固定事件名称和道具名称,它应该可以工作。

  1. 正如Vue Guide: Custom EventName所说,Vue建议始终使用kebab-case作为事件名称。 因此您应该使用this.$emit('start-upload'),然后在模板中使用<upload-button @start-upload="upload"> </upload-button>

  2. 正如Vue Guide: Props所说,

  

HTML属性名称不区分大小写,因此浏览器将解释   任何大写字符作为小写。这意味着当您使用   在DOM模板中,骆驼的道具名称需要使用kebab大小写   (以连字符分隔)的等价物

因此将:uploadComplete="uploadCompleteBoolean"更改为:upload-complete="uploadCompleteBoolean"

编辑:刚刚注意到您提到了data property = uploadingComplete。

这很容易解决,为props=uploadComplete添加一只手表。

下面是一个简单的演示:

Vue.config.productionTip = false
Vue.component('upload-button', {
  template: `<div>  <button @click="onClick">Upload for Data: {{uploadingComplete}} Props: {{uploadComplete}}</button>
         </div>`,
  props: {
    uploadComplete: {
      type: Boolean
    }
  },
  data() {
    return {
      uploadingComplete: this.uploadComplete
    }
  },
  watch: { // watch prop=uploadComplete, if change, sync to data property=uploadingComplete
    uploadComplete: function (newVal) {
      this.uploadingComplete = newVal
    }
  },
  methods: {
    onClick() {
      this.uploadingComplete = false
      this.$emit('start-upload')
    }
  }
})

new Vue({
  el: '#app',
  data() {
    return {
      uploadCompleteBoolean: true
    }
  },

  methods: {
    upload() {
      this.uploadCompleteBoolean = false
      // do stuff to upload, then when finished,
      this.uploadCompleteBoolean = true
    },
    changeStatus() {
      this.uploadCompleteBoolean = !this.uploadCompleteBoolean
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <button @click="changeStatus()">Toggle Status {{uploadCompleteBoolean}}</button>
  <p>Status: {{uploadCompleteBoolean}}</p>
  <upload-button :upload-complete="uploadCompleteBoolean" @start-upload="upload">
  </upload-button>
</div>

答案 1 :(得分:1)

UploadButton组件不应将uploadingComplete作为本地状态(数据);因为您要混合使用uploadComplete属性和uploadingComplete数据,这只会使组件复杂化。

微调器的可见性应由上级组件通过道具来驱动,按钮本身不应负责响应按钮的单击而通过局部状态控制微调器的可见性。

只需执行以下操作:

Vue.component('upload-button', {
  template: '#upload-button',
  props: ['uploading'],
});

new Vue({
  el: '#app',
  data: {
    uploading1: false,
    uploading2: false,
  },
  methods: {
    upload1() {
      this.uploading1 = true;
      setTimeout(() => this.uploading1 = false, Math.random() * 1000);
    },
    upload2() {
      this.uploading2 = true;
      setTimeout(() => this.uploading2 = false, Math.random() * 1000);
    },
  },
});
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>

<div id="app">
  <upload-button :uploading="uploading1" @click="upload1">Upload 1</upload-button>
  <upload-button :uploading="uploading2" @click="upload2">Upload 2</upload-button>
</div>

<template id="upload-button">
  <button @click="$emit('click')">
    <template v-if="uploading">Uploading...</template>
    <slot v-else></slot>
  </button>
</template>

答案 2 :(得分:1)

您的问题似乎有点歧义,您可以在子组件内部的props对象中使用watch,如下所示:

watch:{
    uploadComplete:{
        handler(val){
            //val gives you the updated value 
        }, deep:true
     },
}

通过加深为true,它将监视该对象中的嵌套属性,如果属性之一发生更改,您将从val变量接收新的prop 有关更多信息:https://vuejs.org/v2/api/#vm-watch

如果不是您想要的,我会举一个真实的例子, 检查一下,希望对您有帮助:https://jsfiddle.net/K_Younes/64d8mbs1/