深入理解vue中的插槽(slot)

1. 插槽的本质

组件能够接收任意类型的 JavaScript 值作为 props,但组件要如何接收模板内容呢?插槽可以理解为模板提供内容,<slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。

那么插槽到底是怎么实现替换,怎么运行的。

先看一个案例: 子组件通过setup中slots接收,使用createElementVNode进行渲染。

父组件:

vue 复制代码
<SlotDemo>
    <template v-slot:default="{ title }">
        {{ title }}
    </template>
</SlotDemo>

子组件:

vue 复制代码
import { createElementVNode } from 'vue';

export default {
    setup(props, {slots}) {
        const _default = slots.default()
        console.log('打印***_default', _default)
        return () => {
            return createElementVNode('div', {}, [_default])
        }
    }
}
</script>

子组件定义了默认插槽,父组件传入默认插槽的内容,子组件使用setup语法进行接收,可以看到slots本质是一个对象,对象的键就是插槽的名称,对象的值是一个函数,作用域插槽需要传递数据,就是这个函数的参数。

可以打印下slots:

运行这个函数,得到虚拟节点:

子组件可以通过createElementVnode进行渲染

这样就可以看出插槽的

2. 插槽的使用

2.1 默认插槽

子组件 使用默认或者写

js 复制代码
<slot name="default"></slot>
// 或者
<slot title="默认插槽"></slot>

父组件 三种写法

js 复制代码
// 直接写
默认插槽
// 或者
<template v-slot:default>
    默认插槽(v-slot:default)
</template>
// 或者
<template #default>
    默认插槽(v-slot:default)
</template>

2.2 具名插槽

默认插槽不满足使用需求,那么具名插槽可以解决,为每一个插槽添加名称,就可以进行区分。

子组件:

js 复制代码
<slot name="header"></slot>

父组件:

js 复制代码
<template #header>
    具名插槽
</template>
// 或者
<template v-slot:header>
    具名插槽
</template>

2.3 作用域插槽

如果子组件的内容需要通过插槽传递到外部父组件的插槽中,那么作用域插槽就可以解决问题。我们可以为插槽添加属性,注意name字段是不可以添加的,因为已经被定义为插槽的名称,多个属性会收集成一个对象,传递给父组件的模版中,父组件通过v-slot:xxx=obj接受,这里可以解构

子组件:

js 复制代码
<slot name="content" v-bind="{ a: 1, b: 2 }" />
// 或者
<slot name="content" :a="1" :b="2" />

父组件:

js 复制代码
 <template #content="obj">
    作用域插槽{{ obj.a }}
</template>
// 或者
<template v-slot:content="{ a, b }">
    作用域插槽{{ a }}
</template>

注意:插槽传递的内容,其他插槽是不可以使用的

2.4 动态插槽

我们常见的ui组件库element表格,操作栏可以我们自己定义插槽。使用的就是动态插槽。

如果插槽的名称需要外部自定义,那么动态插槽可以满足要求,动态插槽是用外部传入的名称,定义子组件插槽的名称。通过子组件定义:name="dynamicName" 父组件v-slot:[dynamicName]书写。

子组件:

js 复制代码
<slot :name="dynamicName" :a="1" :b="2"></slot>

父组件:

js 复制代码
<template v-slot:[dynamicName]="{ a, b }">
    动态插槽{{ a }}-{{ b }}
</template>

3. 总结

最后总结一下:插槽的实现就是对于子组件来说就是一个对象,键是插槽的名称,值是一个函数,用于渲染父组件传递的内容。

插槽的使用有几种:

  • 默认插槽:如果子组件没有具名插槽,那么父组件提供的内容将被插入到子组件的默认插槽中。
  • 具名插槽 :如果需要多个插槽及对应不同的内容,可以为插槽添加名称,并通过<template v-slot:xxx><slot name="xxx">进行传递。
  • 作用域插槽:允许子组件通过插槽向父组件传递数据。通过在插槽内部定义属性,并通过父组件提供的对象将数据传递给父组件来实现。
  • 动态插槽 :允许父组件动态地指定插槽的名称。子组件可以使用动态的名称来定义插槽,并在父组件中通过v-slot:[dynamicName]来指定插槽。

如有错误,请指正O^O!

相关推荐
耶啵奶膘14 分钟前
uniapp-是否删除
linux·前端·uni-app
王哈哈^_^2 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie2 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic3 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿3 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具4 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
qq_390161774 小时前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test5 小时前
js下载excel示例demo
前端·javascript·excel
Yaml45 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事5 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro