【问题标题】:"Non-function value encountered for default slot." in Vue 3 Composition API component“默认插槽遇到非函数值。”在 Vue 3 组合 API 组件中
【发布时间】:2021-12-20 19:25:00
【问题描述】:

MCVE

https://github.com/hyperbotauthor/minvue3cliapp

MCVE 直播

https://codesandbox.io/s/white-browser-fl7ji

我有一个 Vue 3 cli-service 应用程序,它使用带有插槽的组合 API 组件。

HelloWorld 组件在div 中呈现它接收到的插槽:

// src/components/Helloworld.js
import { defineComponent, h } from "vue";

export default defineComponent({
  setup(props, { slots }) {
    return () => h("div", {}, slots);
  }
});

Composite 组件在其setup 函数中使用HelloWorld 并填充其槽:

// src/components/Composite.js
import { defineComponent, h } from "vue";

import HelloWorld from "./HelloWorld";

export default defineComponent({
  setup(props, { slots }) {
    return () =>
      h(HelloWorld, {}, [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);
  }
});

该应用使用两种方式来呈现相同的两个 div:

<template>
  <!--<img alt="Vue logo" src="./assets/logo.png">-->
  Works with plain slots
  <HelloWorld>
    <div>Div 1</div>
    <div>Div 2</div>
  </HelloWorld>
  Triggers warning when slots are used from other component
  <Composite> </Composite>
</template>

<script>
import HelloWorld from "./components/HelloWorld";
import Composite from "./components/Composite";

export default {
  name: "App",
  components: {
    HelloWorld,
    Composite,
  },
};
</script>

<style>
</style>

Composite 组件触发此警告:

Non-function value encountered for default slot. Prefer function slots for better performance. 

当我仅从模板中使用HelloWorld 时,不会触发相同的警告。

我不明白如果我使用来自模板或其他组件的插槽有什么区别。

这个警告的意义何在?

有什么办法可以消除这个警告?

【问题讨论】:

    标签: vue.js vuejs3 vue-composition-api slots


    【解决方案1】:

    警告是关于setup()Composite.js 的渲染函数中创建的VNodes 数组。

    // src/components/Composite.js
    export default defineComponent({
      setup(props, { slots }) {
        return () =>
          h(HelloWorld, {}, [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      }
    });
    

    这是低效的,因为子槽被渲染之前HelloWorld 组件甚至可以使用它。子槽本质上是在父级中渲染,然后传递给子级。将子槽生成包装在一个函数中,将工作推迟到渲染子槽为止。

    我不明白如果我使用来自模板或其他组件的插槽有什么区别。

    @vue/compiler-sfc 将 SFC 中的 &lt;template&gt; 编译为渲染函数,其中槽作为函数传递,从而避免了您观察到的警告。

    解决方案

    不要在父级中渲染子槽(即,直接将VNodes 的数组作为slots 参数传递),而是将其包装在一个函数中:

    // src/components/Composite.js
    export default defineComponent({
      setup(props, { slots }) {
        return () =>          ?
          h(HelloWorld, {}, () => [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);
      }
    });
    

    请注意,内部的h() 调用不需要此函数包装器,因为它们都与默认槽一起呈现由孩子

    demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-06
      • 2021-01-14
      • 2021-02-01
      • 2021-12-23
      • 2021-06-06
      • 2019-01-30
      • 2021-06-21
      • 2021-01-14
      相关资源
      最近更新 更多