跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Vue.js插槽作用域
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{Note|本教程假设读者已掌握Vue.js基础组件知识和插槽的基本用法。}} = Vue.js插槽作用域 = '''插槽作用域'''(Scoped Slots)是Vue.js中允许子组件向父组件传递数据的高级插槽技术,实现了'''渲染作用域的反转'''。通过作用域插槽,父组件可以控制子组件内部数据的显示方式,同时保持逻辑的封装性。 == 核心概念 == === 基本定义 === 在普通插槽中,父组件提供的内容在父级作用域编译;而作用域插槽允许子组件将数据作为插槽的'''属性'''传递给父组件,形成类似"函数参数"的机制。 <mermaid> graph LR A[父组件] -->|传递模板| B[子组件] B -->|通过slot属性回传数据| A </mermaid> === 技术原理 === 作用域插槽本质上是一个返回VNode的函数: <math>\text{ScopedSlot} = (props: any) => VNode \text{ or } Array<VNode></math> == 基础语法 == === 子组件定义 === 在子组件中使用<code>v-bind</code>暴露数据: <syntaxhighlight lang="html"> <!-- ChildComponent.vue --> <template> <div class="child"> <slot name="header" :user="userData" :stats="performanceStats"></slot> <slot :item="listItem" v-for="item in items" :key="item.id"></slot> </div> </template> <script> export default { data() { return { userData: { name: '张三', role: '管理员' }, items: [ { id: 1, text: '项目A' }, { id: 2, text: '项目B' } ] } } } </script> </syntaxhighlight> === 父组件使用 === 通过<code>v-slot</code>接收数据(Vue 2.6+语法): <syntaxhighlight lang="html"> <!-- ParentComponent.vue --> <template> <child-component> <!-- 命名插槽示例 --> <template v-slot:header="{ user, stats }"> <h2>{{ user.name }}的控制面板</h2> <p>权限级别: {{ user.role }}</p> </template> <!-- 默认插槽示例 --> <template v-slot:default="slotProps"> <div class="item"> {{ slotProps.item.text }} </div> </template> </child-component> </template> </syntaxhighlight> == 进阶用法 == === 解构赋值 === 可以直接解构插槽props: <syntaxhighlight lang="html"> <template v-slot:header="{ user: { name, role } }"> 欢迎{{ name }} ({{ role }}) </template> </syntaxhighlight> === 动态插槽名 === 结合动态指令参数: <syntaxhighlight lang="html"> <template v-slot:[dynamicSlotName]="props"> <!-- 内容 --> </template> </syntaxhighlight> == 实际应用案例 == === 数据表格组件 === 创建可复用的表格组件,允许自定义单元格渲染: <syntaxhighlight lang="html"> <!-- DataTable.vue --> <template> <table> <thead> <slot name="header"></slot> </thead> <tbody> <tr v-for="item in data" :key="item.id"> <slot name="row" :item="item"></slot> </tr> </tbody> </table> </template> </syntaxhighlight> 使用示例: <syntaxhighlight lang="html"> <data-table :data="users"> <template #header> <th>姓名</th> <th>年龄</th> </template> <template #row="{ item }"> <td>{{ item.name }}</td> <td>{{ item.age }}</td> <td> <button @click="editUser(item)">编辑</button> </td> </template> </data-table> </syntaxhighlight> === 复合组件模式 === 实现类似''渲染代理''的模式: <syntaxhighlight lang="html"> <!-- ToggleableList.vue --> <template> <div> <button @click="toggle">切换显示</button> <ul v-if="visible"> <slot v-for="item in items" :item="item" :isEven="item.id % 2 === 0"></slot> </ul> </div> </template> </syntaxhighlight> == 性能考虑 == 1. '''避免过度嵌套''':深度作用域插槽会增加渲染函数复杂度 2. '''合理使用缓存''':对静态内容使用<code>v-once</code> 3. '''作用域隔离''':插槽内容在父组件编译,无法直接访问子组件状态 == 常见问题 == {{Warning|问题1:为什么插槽内容不更新?}} * 检查绑定的数据是否是响应式的 * 确保没有在插槽内部不必要地创建新对象 {{Warning|问题2:如何访问子组件方法?}} * 通过<code>ref</code>获取组件实例 * 或通过作用域插槽传递方法: <syntaxhighlight lang="html"> <!-- 子组件 --> <slot :internalMethod="handleSomething"></slot> <!-- 父组件 --> <template v-slot="{ internalMethod }"> <button @click="internalMethod">触发</button> </template> </syntaxhighlight> == 版本差异 == {| class="wikitable" |- ! Vue版本 !! 语法变化 |- | 2.5及之前 || <code>slot-scope</code>属性 |- | 2.6+ || <code>v-slot</code>指令(推荐) |- | 3.x || 保持2.6+语法,性能优化 |} == 总结 == 作用域插槽是Vue组件通信的强力工具,特别适用于: * 创建高度可复用的布局组件 * 实现"渲染委托"模式 * 构建面向API的组件库 通过合理使用作用域插槽,可以保持组件的封装性同时提供极大的灵活性。 [[Category:前端框架]] [[Category:Vue.js]] [[Category:Vue.js深入组件]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
该页面使用的模板:
模板:Mbox
(
编辑
)
模板:Note
(
编辑
)
模板:Warning
(
编辑
)
模块:Arguments
(
编辑
)
模块:Message box
(
编辑
)
模块:Message box/ambox.css
(
编辑
)
模块:Message box/configuration
(
编辑
)
模块:Yesno
(
编辑
)