【问题标题】:How to make change in child components dynamically from parent in Vue.js如何在 Vue.js 中从父级动态更改子组件
【发布时间】:2020-06-17 21:54:20
【问题描述】:

我的custom-form 组件中有一个包含一些自定义组件的表单,例如custom-inputcustom-button 等。我的自定义组件(custom-form 除外)包含一个 disabled 道具。当单击提交按钮时,我想在所有自定义组件中将 disabled 属性设置为 true。

我需要动态执行此操作,但我不知道表单中使用了哪些自定义组件。我还需要提一下,我可能在一个页面上有多个表单。

我该如何处理?

这是我尝试过的。

--- Main Component ---
<template>
  <div>
    <slot />
  </div>
</template>
<script>
export default {
}
</script>
--- Component1 ---
<template>
  <div>
    <span v-if="!disabled">this is Comp1</span>
  </div>
</template>
<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>
--- Component2 ---
<template>
  <div>
    <span v-if="!disabled">this is Comp2</span>
  </div>
</template>
<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>
--- My directive ---
import Vue from 'vue'

Vue.directive('disable', {
  bind: (el, binding, vnode) => {
    methods.setChildrent(vnode.context.$children, binding.value)
  }
})

const methods = {
  setChildrent(children, value) {
    children.forEach(element => {      
      this.setChildrent(element.$children, value)
      if(element.$options.propsData)
        if ('disabled' in element.$props)
          element.$props.disabled = value
    })
  }
}

--- Page ---
<template>
  <MainComp v-disable="true">
    <Comp1></Comp1>
    <Comp2></Comp2>
  </MainComp>
</template>

<script>
import Comp1 from './Comp1.vue'
import Comp2 from './Comp2.vue'
import MainComp from './MainComp.vue'
import Directives from '../directives/index.js'
export default {
  name: 'HelloWorld',
  components: {
    Comp1,
    Comp2,
    MainComp,
  },
  directives: {
    Directives
  },
  props: {
    msg: String
  },
  methods: {
  },
  mounted() {   
  }
}
</script>

【问题讨论】:

    标签: vue.js vuejs2


    【解决方案1】:

    道具!

    //主要组件/视图

    <template>
        <custom-form />
        <custom-form />
    </template>
    
    <script>
    import CustomForm from './CustomForm'
    
    export default {
        components: { CustomForm },
        data() {
            return {
                disabled: false
            }
        },
        methods: {
            setDisabled() { 
                this.disabled = true
            }
        }
    }
    </script>
    

    // CustomForm.vue

    <template>
        <form @submit.prevent="submit">
            <custom-element :disabled="disabled" />
            <custom-element :disabled="disabled" />
        </form>
    </template>
    
    <script>
        import CustomElement from './CustomElement'
    
        export default {
            data() { 
                return {
                    disabled: true
                }
            },
            props: ['disabled'],
            components: { CustomElement },
            methods: {
                submit() {
                    this.disabled = true
                }
            }
        }
    </script>
    

    // CustomElement.vue

    <template>
        <input :disabled="disabled" />
    </template>
    
    <script>
        export default {
            props: ['disabled']
        }
    </script>
    

    【讨论】:

    • 感谢您的回答。是否有可能我们没有在 propsData 中设置:disabled 并通过方法动态更改它?正如我在问题中提到的,我们可能在一个页面上有多个表单,并且按照您的方法,所有表单都将被禁用。
    • 我正在寻找一种解决方案来为所有表单创建通用和动态行为,而无需在所有自定义元素中编写 :disabled="disabled"
    • 这是常规的方式,如果你引入了一些非常规的东西,对于任何看到你代码的人来说,维护和学习都会更加麻烦。关于拥有多个表单,您只需在自定义表单元素上公开该道具。我将更新示例。
    • 感谢您的回答。但即使在这种模式下,如果您提交第一个表单,它也会更改第二个表单的disabled 属性。另一方面,我们不想在data 部分中为每个表单定义一个特定的disabled 变量。
    • 好的,所以只需移动道具,以便禁用的范围保持在
    【解决方案2】:

    我通过以下方法解决了这个问题。我不知道是否有任何可能导致问题的情况,但我做了一些测试,没有问题。

    //组件1

    <template>
      <div>
        <span v-if="!disabled">this is Comp1</span>
      </div>
    </template>
    <script>
    export default {
      props: {
        disabled: {
          type: Boolean,
          default: false
        }
      }
    }
    </script>
    

    //组件2

    <template>
      <div>
        <span v-if="!disabled">this is Comp2</span>
      </div>
    </template>
    <script>
    export default {
      props: {
        disabled: {
          type: Boolean,
          default: false
        }
      }
    }
    </script>
    

    //主组件

    <template>
      <div>
        <slot />
      </div>
    </template>
    <script>
    export default {
      props: {
        disabled: {
          type: Boolean,
          default: false
        }
      },
      watch: {
        disabled(val) {
          this.setChildrenStatus(val)
        }
      },
      methods: {    
        setChildrenStatus(status) {      
          this.$slots.default.forEach(item => {
            if (item.componentOptions && item.componentOptions.propsData) {
              item.componentOptions.propsData['disabled'] = status
            }
          })
        }    
      }
    }
    </script>
    

    //主页

    <template>
      <MainComp :disabled="disabled">
        <Comp1></Comp1>
        <Comp2></Comp2>
        <br>
        <button @click="setDisabled">submit</button>    
      </MainComp>
    </template>
    
    <script>
    import Comp1 from './Comp1.vue'
    import Comp2 from './Comp2.vue'
    import MainComp from './MainComp.vue'
    export default {
      name: 'HelloWorld',
      components: {
        Comp1,
        Comp2,
        MainComp,
      },
      data() {
        return {
          disabled: false
        }
      },
      props: {
        msg: String
      },
      methods: {
        setDisabled() {
          this.disabled = !this.disabled
        }
      }
    }
    </script>
    
    
    

    【讨论】:

      猜你喜欢
      • 2017-10-22
      • 1970-01-01
      • 2015-11-13
      • 2016-12-23
      • 2014-10-09
      • 1970-01-01
      • 2016-12-21
      • 2019-10-10
      相关资源
      最近更新 更多