【问题标题】:How to expose wrapped <input> in Vue?如何在 Vue 中暴露包装的 <input>?
【发布时间】:2017-04-09 16:37:27
【问题描述】:

我正在尝试在 Vue 中创建一个可重用的样式输入字段。要使其样式化(例如,内部带有图标),我需要将其包装在另一个 html 元素中。

让我们调用下面的例子StyledInput

<div class="hasIcon">
    <input />
    <i class="someIcon"></i>
<div>

如果我想使用StyledInput,它可能看起来像这样:

<styled-input @keyup.enter="doSomething">
</styled-input>

但这不起作用,因为事件侦听器被附加到 &lt;div&gt; 而不是 &lt;input&gt;

解决方法可能是从输入字段发出所有键事件:

<div class="hasIcon">
    <input @keyup="$emit('keyup', $event) />
    <i class="someIcon"></i>
<div>

但这不会很好地扩展,因为每次开发人员使用未映射的道具或事件时都必须重写它。

有没有办法只让内部元素暴露给任何使用它的人?

【问题讨论】:

    标签: vue-component vue.js


    【解决方案1】:

    我不确定是否有 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 不一定旨在无限重用,它们应该提供特定的功能并封装复杂的逻辑,因此您可能会更好地实现最可能的用例,如果组件不适合,您可以扩展它或为该特定事件编写一个新组件。

    【讨论】:

    • 我想强制组件只公开它记录/映射的内容是有意义的,即使它强制开发人员编写一致的组件 API。你们都提供了解决方案并写了一个很好的答案。谢谢!
    【解决方案2】:

    您可以使用slots 来实现此目的。如果您的 &lt;styled-input&gt; 模板如下所示:

    <div class="hasIcon">
        <slot><input></slot>
        <i class="someIcon"></i>
    <div>
    

    那么你可以这样使用它:

    <styled-input>
        <input @keyup.enter="doTheThing">
    </styled-input>
    

    或者,在你不关心输入事件的情况下,像这样:

    <styled-input></styled-input>
    

    并且将使用默认的插槽内容(一个裸露的&lt;input&gt;)。您可以使用 CSS 为组件内的 &lt;input&gt; 设置样式,但您不能向其添加自定义属性或类,因此这种方法可能符合您的要求,也可能不符合您的要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      • 1970-01-01
      • 2018-06-19
      • 1970-01-01
      相关资源
      最近更新 更多