跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Vue.js插槽
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Vue.js插槽 = '''Vue.js插槽'''(Slots)是Vue组件系统中用于内容分发的重要机制,它允许开发者定义可复用的模板结构,并在使用组件时动态插入自定义内容。插槽机制增强了组件的灵活性和可复用性,是构建复杂UI的基础工具之一。 == 基本概念 == 插槽的核心思想是'''预留位置'''。组件可以在模板中声明<code><slot></code>标签作为占位符,父组件在使用该子组件时,可以向这些占位符中插入任意内容(包括HTML、其他组件等)。 === 为什么需要插槽? === 传统组件通过props传递数据,但遇到以下场景时受限: * 需要传递复杂DOM结构而非简单数据 * 组件某部分需要高度自定义 * 内容分发位置需要精确控制 插槽解决了这些问题,实现了'''模板与内容的解耦'''。 == 基础用法 == === 默认插槽 === 最简单的插槽形式,未命名的插槽会成为默认内容的分发出口。 <syntaxhighlight lang="html"> <!-- 子组件 ChildComponent.vue --> <template> <div class="container"> <h2>组件标题</h2> <slot>这是默认内容(当父组件不提供内容时显示)</slot> </div> </template> <!-- 父组件使用 --> <ChildComponent> <p>这里的内容会替换slot标签</p> </ChildComponent> </syntaxhighlight> '''输出效果''': <div class="container"> <h2>组件标题</h2> <p>这里的内容会替换slot标签</p> </div> === 具名插槽 === 当需要多个插槽时,可以通过<code>name</code>属性区分不同插槽。 <syntaxhighlight lang="html"> <!-- 子组件 LayoutComponent.vue --> <template> <div class="layout"> <header> <slot name="header"></slot> </header> <main> <slot></slot> <!-- 默认插槽 --> </main> <footer> <slot name="footer"></slot> </footer> </div> </template> <!-- 父组件使用 --> <LayoutComponent> <template v-slot:header> <h1>页面标题</h1> </template> <p>主要内容区域</p> <!-- 自动放入默认插槽 --> <template v-slot:footer> <p>版权信息 © 2023</p> </template> </LayoutComponent> </syntaxhighlight> '''渲染结果结构''': <mermaid> graph TD A[LayoutComponent] --> B[header] A --> C[main] A --> D[footer] B --> E["<h1>页面标题</h1>"] C --> F["<p>主要内容区域</p>"] D --> G["<p>版权信息 © 2023</p>"] </mermaid> == 作用域插槽 == 当插槽内容需要访问子组件内部数据时,可以使用作用域插槽。子组件通过<code>v-bind</code>将数据传递给插槽。 <syntaxhighlight lang="html"> <!-- 子组件 DataList.vue --> <template> <ul> <li v-for="item in items" :key="item.id"> <slot :item="item" :index="index">{{ item.defaultText }}</slot> </li> </ul> </template> <script> export default { data() { return { items: [ { id: 1, text: '项目1', defaultText: '默认项目1' }, { id: 2, text: '项目2', defaultText: '默认项目2' } ] } } } </script> <!-- 父组件使用 --> <DataList> <template v-slot:default="slotProps"> <span>{{ slotProps.index + 1 }}. {{ slotProps.item.text }}</span> </template> </DataList> </syntaxhighlight> '''渲染结果''': <ul> <li><span>1. 项目1</span></li> <li><span>2. 项目2</span></li> </ul> == 动态插槽名 == Vue 2.6.0+ 支持动态指定插槽名: <syntaxhighlight lang="html"> <template v-slot:[dynamicSlotName]> <!-- 内容 --> </template> </syntaxhighlight> == 插槽的高级模式 == === 解构插槽Prop === 作用域插槽的参数可以使用ES6解构: <syntaxhighlight lang="html"> <template v-slot:default="{ item, index }"> {{ index }} - {{ item }} </template> </syntaxhighlight> === 缩写语法 === * <code>v-slot:header</code> 可缩写为 <code>#header</code> * 默认插槽可写为 <code>v-slot</code> 或 <code>#default</code> == 实际应用案例 == === 可复用的模态框组件 === <mermaid> graph LR A[ModalComponent] --> B[标题插槽] A --> C[内容插槽] A --> D[操作区插槽] </mermaid> <syntaxhighlight lang="html"> <!-- ModalComponent.vue --> <template> <div class="modal"> <div class="modal-header"> <slot name="title">默认标题</slot> </div> <div class="modal-body"> <slot></slot> </div> <div class="modal-footer"> <slot name="actions"> <button @click="$emit('close')">关闭</button> </slot> </div> </div> </template> <!-- 使用示例 --> <ModalComponent> <template #title> <h3>自定义标题</h3> </template> <p>这里是模态框的主要内容...</p> <template #actions> <button @click="submit">提交</button> <button @click="cancel">取消</button> </template> </ModalComponent> </syntaxhighlight> === 表格渲染组件 === 通过作用域插槽实现灵活的单元格渲染: <syntaxhighlight lang="html"> <DataTable :columns="columns" :data="items"> <template #column-name="{ value }"> <a :href="'/user/' + value.id">{{ value.name }}</a> </template> <template #column-status="{ value }"> <span :class="'status-' + value">{{ statusText[value] }}</span> </template> </DataTable> </syntaxhighlight> == 插槽原理 == Vue的插槽系统基于'''编译作用域'''概念: * 父级模板里的内容在父级作用域编译 * 子模板里的内容在子作用域编译 插槽内容的编译位置可以用以下公式表示: <math> \text{SlotContent} \in \text{ParentScope} \\ \text{SlotOutlet} \in \text{ChildScope} </math> == 最佳实践 == 1. '''提供合理的默认内容''':使组件在单独使用时也有良好表现 2. '''适度使用具名插槽''':超过3个插槽时考虑拆分组件 3. '''避免深层插槽嵌套''':超过3层会降低可维护性 4. '''作用域插槽命名''':使用有意义的prop名称如<code>item</code>而非<code>data</code> == 常见问题 == '''Q:插槽内容何时被编译?''' A:插槽内容在父组件编译阶段处理,但作用域由插槽位置决定。 '''Q:可以在一个插槽上同时使用v-if和v-slot吗?''' A:不可以,应该在外层template上使用v-if: <syntaxhighlight lang="html"> <template v-if="condition" v-slot:name> ... </template> </syntaxhighlight> == 总结 == Vue插槽系统提供了强大的内容分发能力: * 默认插槽 - 基础内容分发 * 具名插槽 - 多内容区域控制 * 作用域插槽 - 子向父传递数据 * 动态插槽 - 运行时决定分发位置 掌握插槽技术可以创建出高度灵活、可复用的Vue组件,是构建复杂应用的基础技能之一。 [[Category:前端框架]] [[Category:Vue.js]] [[Category:Vue.js组件基础]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)