我有一个BaseFormControl
组件接受id
道具。它将id
prop值设置为for
元素上的<label>
属性值和给定输入上的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>
这种方法的问题是<slot>
没有将任何属性传递给插槽内容,因此: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
属性),但在其他情况下它没有。特别有趣的是,所有输入组件(我在输入槽中放入的是另一个基本组件,而不是通用的<input>
标签)实际上已经this.$attrs
正确地填充了id
,但是有时它出现在实际的HTML中,有时它不会出现。
有人可以解释我的行为,告诉我我做错了什么以及如何解决这个问题?
我创建了一个pen来说明这些概念。唯一的问题是在笔中一切正常。在我的应用中,只有1个选项在页面上,只有1个设置正确id
- 另一个在没有id
的情况下呈现(尽管id
设置在其中this.$attrs
})。
答案 0 :(得分:1)
这种方法的问题在于没有将任何属性传递给插槽内容,
您正在做的是将id
作为广告位数据传递到广告位。这意味着您正在创建scoped slot。
您可以使用BaseFormControl
属性在slot-scope
中访问此数据。
<BaseFormControl :id="'myInput'">
<p slot="label">Input label</p>
<input slot="input" slot-scope="props" :id="props.id" type="text" placeholder="type anythin">
</BaseFormControl>
如果您将id
作为道具传递,可以直接使用它来设置输入的ID,如下所示
<BaseFormControl :id="'myInput'">
<p slot="label">Input label</p>
<input id="myInput" type="text" placeholder="type anythin">
</BaseFormControl>
答案 1 :(得分:0)
寻找解决方案我决定最简单的方法是为组件添加“for”属性并将其转发到标签。
我还手动为插槽内容设置了“id”属性。这几乎与我们在 HTML 中使用 <label>
的方式相同。
<!-- 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>
看起来所有其他方法都需要许多不明确的属性用于组件本身及其使用中的作用域/命名插槽。