【问题标题】:How to set attribute on a component inside a slot in Vue?如何在Vue中的插槽内设置组件的属性?
【发布时间】:2018-06-14 10:59:13
【问题描述】:

问题

我有一个接受 id 属性的 BaseFormControl 组件。它将id 属性值设置为<label> 元素上的for 属性值和给定输入上的id 属性值。由于我希望 BaseFormControl 成为可与各种输入类型一起使用的通用组件,因此我将输入作为插槽传递。下面的组件代码:

<script>
export default {
   props: {
     id: {
       type: String,
       required: true
     }
   }
};
</script>

<template>
  <div>
    <label :for="id">
      <slot name="label" />
    </label>
    <slot
      name="input"
      :id="id"
    />
  </div>
</template>

这种方法的问题是&lt;slot&gt; 没有将任何属性传递给插槽内容,因此:id 根本没有传递给实际输入。

所以我尝试以编程方式设置它:

export default {
   props: {
     id: {
       type: String,
       required: true
     }
   }

   created() {
     let inputSlot = this.$slots.input;
     if (inputSlot) {
       inputSlot[0].data.attrs.id = this.id;
     }
   }
};

在某些情况下它可以完美运行(作为插槽传递的输入在其 HTML 中正确设置了 id 属性),但在其他情况下则不然。特别有趣的是,所有的输入组件(我放在输入槽中的是另一个基本组件,而不是通用的&lt;input&gt; 标签)实际上是用id 正确填充的this.$attrs,但有时它会出现在实际的HTML 中有时不会。

谁能解释一下我的这种行为,告诉我我做错了什么以及如何解决这个问题?

我创建了一个pen 来说明这些概念。唯一的问题是在笔中一切正常。在我的应用中,在页面上的 2 个选择中,只有 1 个正确设置了 id - 另一个在没有 id 的情况下呈现(尽管 id 设置在它的 this.$attrs 中)。

【问题讨论】:

    标签: vue.js vue-component


    【解决方案1】:

    这种方法的问题是没有将任何属性传递给插槽内容,

    您正在做的是将id 作为插槽数据传递给插槽。这意味着您正在创建一个scoped slot

    您可以使用slot-scope 属性在BaseFormControl 中访问这些数据。

    <BaseFormControl :id="'myInput'">
      <p slot="label">Input label</p>
      <input slot="input" slot-scope="props" :id="props.id" type="text" placeholder="type anythin">
    </BaseFormControl>
    

    PS:

    如果您将 id 作为道具传递,您可以直接使用它来设置输入的 id,如下所示

    <BaseFormControl :id="'myInput'">
      <p slot="label">Input label</p>
      <input id="myInput" type="text" placeholder="type anythin">
    </BaseFormControl>
    

    【讨论】:

    • 我同意它会起作用,但这种方法需要我在每次使用 BaseFormControl 时在 &lt;input&gt; 上声明 idslot-scope="props" :id="props.id"。我想将所有关系/要求封装在BaseFormComponent 中以避免这种重复。
    【解决方案2】:

    搜索解决方案我决定最简单的方法是为组件添加“for”属性并将其转发到标签。

    我还手动为插槽内容设置了“id”属性。这与我们在 HTML 中使用 &lt;label&gt; 的方式几乎相同。

    <!-- component.vue -->
    <template>
        <div class="form-group row my-2">
            <label class="col-4 col-form-label" :for="$props.for">{{ label }}</label>
            <div class="col-8" >
                <slot></slot>
            </div>
        </div>
    </template>
    <script>
    
    export default {
        name: "SettingsRow",
        props: {
            label: {required: true, type: String},
            for: {required: true, type: String}
        }
    }
    </script>
    

    这就是我使用这个组件的方式。

    <settings-row label="Choose chromosome" for="someId">
        <select v-model="ch" id="someId">
            <option>X</option>
            <option>Y</option>
        </select>
    </settings-row>
    

    看起来所有其他方法都需要许多不清楚的属性,用于组件本身及其使用中的作用域/命名槽。

    【讨论】:

      猜你喜欢
      • 2021-01-15
      • 1970-01-01
      • 2021-02-06
      • 2021-12-06
      • 2018-11-06
      • 2021-02-27
      • 2020-05-22
      • 2018-03-13
      • 1970-01-01
      相关资源
      最近更新 更多