【问题标题】:Remap component listeners to child components将组件侦听器重新映射到子组件
【发布时间】:2021-10-31 06:13:08
【问题描述】:

在 Vue2/JavaScript 中,我有这个计算属性,用于根据前缀将组件侦听器重新映射到子组件:

inputPortListeners() {
  return reduce(
    this.$listeners,
    (listeners, listener, name) => {
      if (!name.startsWith('input-')) return listeners;
      listeners[name.slice('input-'.length)] = (e) => listener.call(this, e, this.node.id, e.target.dataset.index);
      return listeners;
    },
    {}
  );
},

现在我正在迁移到 Vue3/TypeScript,我在迁移这个计算属性时也遇到了麻烦。我到目前为止是这样的:

type Listeners = Record<string, (e: unknown)=>void>;
const inputPortListeners = computed(() => {
  return Object.keys(attrs).reduce<Listeners>((listeners, name: string) => {
    if (!name.startsWith('onInput')) return listeners;
    listeners[name.replace('onInput', '')] = (e: unknown) => attrs[name].call(this, e, this.node.id, e.target.dataset.index);
    return listeners;
  }, {});
});

有问题的行是这一行:

(e: unknown) => attrs[name].call(this, e, props.node.id, e.target.dataset.index);

因为attrs 没有强类型并且e 是未知的所以无法获取e.target.dataset.index

我有什么办法来解决这个问题?

【问题讨论】:

    标签: typescript vue.js typescript-typings vuejs3


    【解决方案1】:

    attrs(来自setup()'s context argument)是Data,也就是defined as

    Record<string, unknown>
    

    所以,attrs[name]unknown,在您的情况下需要类型断言才能用作函数:

    (attrs[name] as Function).call(...)
    

    类似地,eunknown,但不一定是这样。这里的e真的是Event,所以你可以从(e: unknown)切换到(e: Event)

    type Listeners = Record<string, (e: Event)=>void>;
    //...
    listeners[name.replace('Input', '')] = (e: Event) => {...};
    

    Event 有一个target 属性,即defined as

    EventTarget | null
    

    但是,EventTarget 没有dataset,而comes from HTMLElement。您可以对HTMLElement 使用类型断言,因为target 可能是&lt;input&gt;(基于input 事件名称):

    (e.target as HTMLElement)?.dataset.index
    

    生成的代码应该是:

    type Listeners = Record<string, (e: Event)=>void>;
    const inputPortListeners = computed(() => {
      return Object.keys(attrs).reduce<Listeners>((listeners, name: string) => {
        if (!name.startsWith('onInput')) return listeners;
        listeners[name.replace('Input', '')] = (e: Event) => (attrs[name] as Function).call(this, e, null, (e.target as HTMLElement)?.dataset.index);
        return listeners;
      }, {});
    });
    

    【讨论】:

      猜你喜欢
      • 2018-03-04
      • 2019-08-14
      • 1970-01-01
      • 2013-03-09
      • 1970-01-01
      • 2019-08-16
      • 1970-01-01
      • 2022-12-07
      • 1970-01-01
      相关资源
      最近更新 更多