【问题标题】:VueJS 2.4 basic wrapper componentVueJS 2.4 基本包装组件
【发布时间】:2017-12-12 00:33:24
【问题描述】:

也许这是一个简单的问题,但我找不到创建基本包装组件的正确方法。例如我有一个这样的选择:

<select v-model="foo" name="bar" v-validate="'required'" v-bind:class="{ invalid: errors.has('bar') }">
    <option value="">Default</option>
    <option value="1">Value 1</option>
    <option value="2">Value 2</option>
</select>

我需要在这个周围添加一些糖,divcustom-select 类。所以我创建了一个custom-select 组件来包装原生选择:

Vue.component('custom-select', {
    template: `
        <div class="custom-select">
            <select v-on="$listeners" v-bind="$props">
                <slot></slot>
            </select>
        </div>
    `,
});

我的问题是我的组件没有继承 v-modelclass 之类的属性。想知道有没有全局的方式,不用重写组件中所有的props,让他继承一切?

【问题讨论】:

  • 您可能想让您的自定义组件将选择作为插槽。在任何情况下,v-model 都不是道具,也没有直接的方法可以将其代理到层次结构中。

标签: vue.js vuejs2


【解决方案1】:

v-model 只是:value@input 的语法糖。它对本机输入元素的工作方式与对组件的工作方式不同;这并不像将v-on="$listeners" v-bind="$props" 添加到组件的模板那么简单。它不会起作用。

如果您想让v-model 工作,您需要处理组件内的输入事件并发出更改后的值:

<custom-select v-model="selected">
Vue.component('custom-select', {
  template: `
    <div class="custom-select">
      <select v-bind="$attrs" v-on="computedListeners">
        <slot></slot>
      </select>
    </div>
  `,
  computed: {
    computedListeners() {
      return Object.assign({}, this.$listeners, {
        input: e => this.$emit('input', e.target.value),
      });
    },
  },
});

以上是使v-model 正常工作的一种技巧,否则你可以这样做:

<custom-select :value="selected" @input="selected = $event.target.value">
Vue.component('custom-select', {
  template: `
    <div class="custom-select">
      <select v-bind="$attrs" v-on="$listeners">
        <slot></slot>
      </select>
    </div>
  `,
});

请注意,classstyle 不能代理到内部 &lt;select&gt;,因为它们不是道具,它们由 Vue 专门处理,并将应用于组件模板的根元素。

编辑:实际上你可以代理 classstyle 但它需要手动编写渲染函数:

Vue.component('custom-select', {
  functional: true,
  render(h, ctx) {
    const on = Object.assign({}, ctx.listeners);
    if (ctx.listeners.input) {
      // Required for v-model to work
      on.input = e => ctx.listeners.input(e.target.value);
    }

    const data = Object.assign({}, ctx.data, { on });
    return h('div', { class: 'custom-select' }, [h('select', data, ctx.children)]);
  },
});

【讨论】:

  • 在您的示例中,您如何处理 v-bind:disabled=... ?组件需要禁用道具?我的问题的重点是不必编写所有此类绑定。
  • 感谢详细解答
猜你喜欢
  • 2017-11-25
  • 2018-07-26
  • 1970-01-01
  • 2020-01-16
  • 2020-10-29
  • 1970-01-01
  • 2018-07-05
  • 2018-03-29
  • 1970-01-01
相关资源
最近更新 更多