首页 > 解决方案 > Vuejs | 创建使用其中一个道具的中间组件并将所有剩余的东西传播到

问题描述

可能是重复的,但由于我是 Vue 的新手,所以我很难提出问题。

在我们的代码库中,我们有一个按钮的重复模式,伴随着一条消息,这取决于按钮是否被禁用。这是我的意思的简化(下面的完整上下文)示例:

    <button 
      :disabled="!canSayHello"
      style="background-color:red"
    >
      Hi!
    </button>
    <p v-if="canSayHello"> Ready to say hi! </p>
    
    <br>
    
    <button 
      :disabled="!canSayGoodbye"
      name="the-bye-bye-button"
    >
      Bye!
    </button>
    <p v-if="canSayGoodbye"> You can say goodbye now </p>

我想创建一个中间组件clarified-button,以便可以执行以下操作:

    <clarified-button
      :disabled="!canSayHello"
      clarification="Ready to say hi!"
      style="background-color:red"
    >
      Hi!
    </clarified-button>
    
    <br>
    
    <clarified-button
      :disabled="!canSayGoodbye"
      clarification="You can say goodbye now"
      name="the-bye-bye-button"
    >
      Bye!
    </clarified-button>

的内部button元素clarified-button 不应该接收clarification道具,应该接收给它的所有剩余内容(属性、侦听器等?)并且应该使用接收到的道具disabled。我猜它会涉及到:

<button
  /*
   *  everything except the clarification prop gets propagated
   */
>
  <slot></slot>
</button>
<p v-if="!disabled"> {{ clarification }} </p>

如果对您有帮助,这是基本案例的 MWE:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
new Vue({
  el: '#app',
  template: `
  <div>
  
    <button 
        :disabled="!canSayHello"
      style="background-color:red"
    >
      Hi!
    </button>
    <p v-if="canSayHello"> Ready to say hi! </p>
    
    <br>
    
    <button 
        :disabled="!canSayGoodbye"
      name="the-bye-bye-button"
    >
      Bye!
    </button>
    <p v-if="canSayGoodbye"> You can say goodbye now </p>
    
  </div>
  `,
  data: {
    canSayHello: false,
    canSayGoodbye: true,
  },
})

实际问题

我们正在使用bootstrap-vue,我需要在禁用按钮上显示工具提示。但是,当 ab-button被禁用时,它b-tooltip不会出现。文档提供了一种解决方法(https://bootstrap-vue.org/docs/components/tooltip/#disabled-elements),但它会产生两个单独的组件,如简化示例所示。我试图了解如何创建可重用和增强的组件。

标签: htmlvue.jsvuejs2

解决方案


似乎以下可以解决问题:

Vue.component('clarified-button', {
  template: `
    <div>
      <button v-bind="$attrs" v-on="$listeners" :disabled="disabled">
        <slot></slot>
      </button>
      <p v-if="!disabled">
        {{ clarification }}
      </p>
    </div>
  `,
  props: ['clarification', 'disabled']
});

new Vue({
  el: '#app',
  template: `
  <div>
    <clarified-button
      :disabled="!canSayHello"
      style="background-color:red"
      clarification="Ready to say hi!"
    >
      Hi!
    </clarified-button>
    
    <br>
    
    <clarified-button
      :disabled="!canSayGoodbye"
      name="the-bye-bye-button"
      clarification="You can say goodbye now"
    >
      Bye!
    </clarified-button>
  </div>
  `,
  data: {
    canSayHello: false,
    canSayGoodbye: true,
  },
});

请注意,如果您使用 vue2,则样式和类不包含在 $attrs 中,因此完整的解决方案需要额外的工作。


推荐阅读