Open JianShaw opened 5 years ago
通常我们声明使用一个vue按钮组件.
const TestButton = { template: `<button>组件A</button>` }
使用这个button组件
<test-button>提交</test-button>
渲染出的button上的text依然是 组件A。
vue中实现了slot(插槽)来做内容分发。有了slot,我们能写出更灵活强大的插件。
vue
slot
const TestButton = { template: `<button><slot>组件A</slot></button>` }
现在,渲染出的就是文字内容为提交的按钮了。
在我使用element的el-dialog,有如下代码
element
el-dialog
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose"> <span>这是一段信息</span> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="dialogVisible = false">确 定</el-button> </span> </el-dialog>
slot='footer'便是名为footer的插槽。查看源码,dialog实际设置了3个插槽,分别为title,default,footer。使用组件时,通过显示的指定对应的name便可以设置相关内容。
slot='footer'
footer
dialog
设置具名插槽的语法.
<div class="define-slot-name"> <header> <slot name="header"> </slot> </header> </div>
注意,slot没有设置name的时候,默认为default。
以dialog的示例代码为例
<el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button> <el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose"> <span>这是一段信息</span> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="dialogVisible = false">确 定</el-button> </span> </el-dialog> <script> export default { data() { return { dialogVisible: false }; }, methods: { handleClose(done) { this.$confirm('确认关闭?') .then(_ => { done(); }) .catch(_ => {}); } } }; </script>
// 对于slot内的`this`指向的显然是父组件的。 <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="dialogVisible = false">确 定</el-button> </span>
业务是变化的,有时候我们是需要插槽访问到子组件才有的数据的。如下的这个todolist组件
<parent> <todo-list v-bind:data="todos"> <template v-slot:todo="{ todo }"> <span v-if="todo.isComplete">✓</span> {{ todo.text }} </template> </todo-list> </parent> <script> export default { data(){ return { todos: [] } } } </script>
todolist组件允许传入一个list列表,在slot里能访问到每个单独的list,根据具体的业务判断显示不同的内容。
vue允许我们在定义slot时,绑定一个属性上去,称之为 插槽prop 。在父级作用域中,我们可以给v-slot 带一个值来定义我们提供的插槽 prop 的名字。
v-slot
我们来看一下todolist是如何实现的
todolist
<ul> <li v-for="todo in todos" v-bind:key="todo.id"> <!-- slot定义在 遍历内,我们为每个todo都准备一个插槽。 通过`v-bind:todo=todo`,prop就是 插槽prop。 在使用todolist的时候,就可以访问到子组件的todo了。使用方法如上段代码。 --> <slot name="todo" v-bind:todo ="todo"'> {{todo.text}} </slot> </li> </ul>
文档中将这种插槽称之为作用域插槽。
前提是只有默认插槽,在强调一遍,是只有默认插槽,组件的标签代替<template>
<template>
<component-name v-slot="scope"> {{ scope.user.name }} </component-name>
可以使用es6的结构来处理scope
<component-name v-slot="{user}"> // {user: person} => 重命名, {user= {name: "haha"}} 设置默认值,如果user为undefined {{ user.name }} </component-name>
同上边例子作对比,用结构直接取出user。
v-slot:name也可以被缩写为#name。
v-slot:name
#name
<base-layout> <template #header> <h1>Here might be a page title</h1> </template> <p>A paragraph for the main content.</p> <p>And another one.</p> <template #footer> <p>Here's some contact info</p> </template> </base-layout> <!-- 代码有错。这样会触发一个警告 --> <current-user #="{ user }"> {{ user.firstName }} </current-user> <!-- 如果你希望使用缩写的话,你必须始终以明确插槽名取而代之: 也就是default的默认slot,要明确写出default的插槽名才可以。 --> <current-user #default="{ user }"> {{ user.firstName }} </current-user>
什么是插槽
通常我们声明使用一个vue按钮组件.
使用这个button组件
渲染出的button上的text依然是 组件A。
vue
中实现了slot
(插槽)来做内容分发。有了slot
,我们能写出更灵活强大的插件。现在,渲染出的就是文字内容为提交的按钮了。
具名插槽
在我使用
element
的el-dialog
,有如下代码slot='footer'
便是名为footer
的插槽。查看源码,dialog
实际设置了3个插槽,分别为title,default,footer。使用组件时,通过显示的指定对应的name便可以设置相关内容。设置具名插槽的语法.
注意,slot没有设置name的时候,默认为default。
插槽的作用域
以
dialog
的示例代码为例业务是变化的,有时候我们是需要插槽访问到子组件才有的数据的。如下的这个todolist组件
todolist组件允许传入一个list列表,在slot里能访问到每个单独的list,根据具体的业务判断显示不同的内容。
vue允许我们在定义slot时,绑定一个属性上去,称之为 插槽prop 。在父级作用域中,我们可以给
v-slot
带一个值来定义我们提供的插槽 prop 的名字。我们来看一下
todolist
是如何实现的文档中将这种插槽称之为作用域插槽。
插槽中一些简写的方法
独占默认插槽的简写
前提是只有默认插槽,在强调一遍,是只有默认插槽,组件的标签代替
<template>
结构插槽prop
可以使用es6的结构来处理scope
同上边例子作对比,用结构直接取出user。
具名插槽的缩写
v-slot:name
也可以被缩写为#name
。