我试图在Vue中创建可重用的样式输入字段。为了使它风格化(例如,里面有一个图标)我需要将它包装在另一个html元素中。
让我们调用StyledInput
<div class="hasIcon">
<input />
<i class="someIcon"></i>
<div>
如果我想使用StyledInput
,可能会这样:
<styled-input @keyup.enter="doSomething">
</styled-input>
但是这不起作用,因为事件监听器被附加到<div>
而不是<input>
。
解决方法可能是从输入字段发出所有键事件:
<div class="hasIcon">
<input @keyup="$emit('keyup', $event) />
<i class="someIcon"></i>
<div>
但是这不会很好地扩展,因为每次开发人员使用未映射的道具或事件时都必须重写。
有没有办法只让内部元素暴露给任何使用它的人?
答案 0 :(得分:4)
我不确定是否有Vue
方法可以实现这一点,因为据我所知,没有办法动态绑定vue事件,但是可以使用vanilla javascript来实现这一点。将所有事件作为道具传递,然后使用addEventListener()
映射它们以添加自定义事件:
Vue.component('my-input', {
template: "#my-input",
props: ['events'],
mounted() {
// get the input element
let input = document.getElementById('styled-input');
// map events
this.events.forEach((event) => {
let key = Object.keys(event);
input.addEventListener(key, event[key]);
});
}
})
然后你就可以把所有事件作为道具传递出去:
<my-input :events="events"></my-input>
查看型号:
var app = new Vue({
el: "#app",
data: {
events: [{
focus: () => {
console.log('focus')
}
}, {
keyup: (e) => {
console.log(e.which)
}
}]
}
})
继承人JSFiddle:https://jsfiddle.net/h1dnk40v/
当然,这意味着任何开发人员都必须执行映射密钥代码等操作,因此您将失去Vue提供的一些便利。
我要提到的一件事是Vue components
不一定是无限可重用的,它们应该提供特定的功能并封装复杂的逻辑,所以你可能会更好地实现最可能的用途如果组件不适合,您可以扩展它或为该特定事件写一个新组件。
答案 1 :(得分:0)
您可以使用slots来实现此目的。如果您的<styled-input>
模板如下所示:
<div class="hasIcon">
<slot><input></slot>
<i class="someIcon"></i>
<div>
然后你可以像这样使用它:
<styled-input>
<input @keyup.enter="doTheThing">
</styled-input>
或者,如果您不关心输入事件,请执行以下操作:
<styled-input></styled-input>
将使用默认广告位内容(裸<input>
)。您可以使用CSS来设置组件内<input>
的样式,但不能向其添加自定义属性或类,因此这种方法可能符合您的要求,也可能不符合您的要求。