【问题标题】:Renderless Vue Component in TypeScriptTypeScript 中的无渲染 Vue 组件
【发布时间】:2020-01-19 23:18:23
【问题描述】:

我正在尝试将 JavaScript 中的无渲染组件转换为 TypeScript。我在 Vue.extend-ed 组件中声明 render 函数时遇到错误:

(method) ComponentOptions<Vue, unknown, unknown, unknown, never[], Record<never, any>>.render?(createElement: CreateElement, hack: RenderContext<Record<never, any>>): VNode
  No overload matches this call.
  The last overload gave the following error.
  Argument of type '{ render(): void; }' is not assignable to parameter of type 'ComponentOptions<Vue, DefaultData<Vue>, DefaultMethods<Vue>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<string, any>>'.
    Types of property 'render' are incompatible.
      Type '() => void' is not assignable to type '(createElement: CreateElement, hack: RenderContext<Record<string, any>>) => VNode'.
        Type 'void' is not assignable to type 'VNode'.ts(2769)
        vue.d.ts(90, 3): The last overload is declared here.

这是我在 TypeScript 中尝试做的一个示例:

import Vue from 'vue'

export default Vue.extend({
  render() { // error happens when I add this. I tried typing the render with :VNode
             // and returning this.$scopedSlots.default({}), but error still occurs
  }
})

我该如何解决这个问题?

【问题讨论】:

标签: typescript vue.js vuejs2 vue-component renderless-component


【解决方案1】:

render() 有这个签名:

render?(createElement: CreateElement, hack: RenderContext<Props>): VNode;

render() 声明注意事项:

  • hack 不需要在你的代码中声明
  • 无渲染函数中不需要参数声明
  • 返回类型是VNode(即单个根节点),但Vue实际上接受VNode[]作为返回(这是this.$scopedSlots.default()返回的)

方案一:指定返回类型为VNode,并返回包裹this.$scopedSlots.default()的单个节点:

import Vue, { VNode, CreateElement } from 'vue'

export default Vue.extend({
  render(h: CreateElement): VNode {
    return h('div', this.$scopedSlots.default!({}))
  }
})

解决方案 2:this.$scopedSlots.default() 上使用 any 类型断言来解决类型错误:

import Vue from 'vue'

export default Vue.extend({
  render() {
    // The container node is expected to provide a single root,
    // so it's okay to return `VNode[]` as any.
    return this.$scopedSlots.default!({}) as any
  }
})

【讨论】:

  • 解决方案 2 对我有用,因为该组件是无渲染的。谢谢@tony19。这在文档中不可用,因此感谢您分享您的知识。
  • 我在使用第二种解决方案时出错,但使用普通插槽可以正常工作:render() { return this.$slots.default! as any }
  • 是的,只要我不使用 mixin(不幸地定义为 any),上述解决方案就可以工作。添加 mixin 会导致每个组件属性出现 ts 错误。现在我正在使用 `render(h) { return h('template') } 并且似乎工作得很好。
猜你喜欢
  • 2019-04-19
  • 1970-01-01
  • 2019-02-19
  • 2020-10-12
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
  • 2020-03-25
  • 2017-11-09
相关资源
最近更新 更多