Vue slot 默认内容

6,162 阅读1分钟

本人小白,如有问题,还望指出,虚心求教。

使用场景

当在自定义组件设置插槽,特别是具名插槽,如果在使用组件时不为具名插槽指定内容,具名插槽会直接不渲染。

但是如果我们要默认显示内容,就可以直接在 slot 下定义默认内容。

    <slot name="title"> --default title-- </slot>

这种使用对于插槽提供默认内容来说,十分方便。

版本问题

但是由于 vue / vue-template-compiler 版本问题,v2.6.13 版本渲染调整,如果vue 与 vue-template-compiler 版本不一致,会导致默认内容渲染不出来。

这时候,需要用 v-if v-else 语法替换原本内容

    <slot v-if="$slots.title" name="title"></slot>
    <div v-else> --default title-- </div>

源码浅析

v2.6.12

  • vue renderSlot 方法,用来渲染插槽内容 image.png

主要差异: 第二个参数类型为 VNode 直接用来渲染节点内容
nodes = this.$slots[name] || fallback,这句话表明优先使用指定的插入内容,如果未指定,则直接使用默认内容

  • vue-template-compile 引用 compile 方法编译一段 带有slot 的html image.png

返回ast语法树以及render函数,其他 _trenderSlot 函数 image.png

主要差异: 从render 函数可以看到,slot 节点直接渲染成 Vnode

v2.6.13

  • vue renderSlot 方法,用来渲染插槽内容 image.png

主要差异: 第二个参数类型为 function/VNode 用来渲染节点内容
nodes = this.$slots[name] || (typeof fallbackRender === 'function' ? fallbackRender() : fallbackRender),这句话表明优先使用指定的插入内容,如果未指定,则直接使用默认内容,判断是否为函数,如果是,则获取函数返回结果,否则,直接使用

  • vue-template-compile 引用 compile 方法编译一段 带有slot 的html image.png

返回ast语法树以及render函数,其他 _trenderSlot 函数 image.png

主要差异: 从render 函数可以看到,slot 节点渲染成一个函数function,函数function 返回 Vnode

综上所述: 如果不支持slot默认内容,则可能是vue 版本(低版本)和 vue-template-compiler 版本(高版本)不一致导致语法不兼容。解决方法,显而易见了,就是统一版本。

这种场景主要是 vue 采用CDN引入 的时候,需要考虑。