vue2.0 之 slot 内容分发
前提:父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。被分发的内容会在父作用域内编译。
一、单个插槽
// 子组件模板 child-component <div> <h2>我是子组件的标题</h2> <slot> 只有在没有要分发的内容时才会显示。 </slot> </div> // 父组件模板: // 父组件模板中的子组件child-component中的内容渲染到slot插槽中, // 若插槽中原有默认内容,会替换掉;
// 若子组件child-component只有一个没有属性的插槽,则父组件中的所有传入内容将被渲染在此插槽处;
// 若一个插槽都没有,则父组件模版中的子组件child-component中的内容会被丢弃
<div>
<h1>我是父组件的标题</h1>
<child-component>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</child-component>
</div>
// 渲染结果:
<div>
<h1>我是父组件的标题</h1>
<div>
<h2>我是子组件的标题</h2>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</div>
</div>
二、具名插槽
<slot>
元素用属性 name
来进一步配置如何分发内容。具名插槽将匹配内容片段中有对应 slot
特性的元素。
仍然可以有一个匿名插槽,作为默认插槽,作为找不到匹配的内容片段的备用插槽。若无默认插槽,这些找不到匹配的内容片段将被抛弃
// 子组件模板:child-component
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot> //默认插槽
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
// 父组件模板:
<div>
<h2>父组件模版标题</h2>
<child-component>
<h1 slot="header">这里可能是一个页面标题</h1>
// 为匹配到的内容,插入到默认插槽中
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<p slot="footer">这里有一些联系信息</p>
</child-component>
</div>
// 渲染结果为:
<div>
<h2>父组件模版标题</h2>
<div class="container">
<header>
<h1>这里可能是一个页面标题</h1>
</header>
<main>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
</main>
<footer>
<p>这里有一些联系信息</p>
</footer>
</div>
</div>
三、作用域插槽
v2.1.0
作用域插槽是一种特殊类型的插槽,能被传递数据。在子组件中,只需将数据传递到插槽,就可以像 props 一样传递数据。
// 子组件模板 child-component <div class="child"> <slot text="msg from child"></slot> </div>
在父级中,具有属性 slot-scope
的 <template>
元素必须存在,表示它是作用域插槽的模板。slot-scope
的值将被用作一个临时变量名,此变量接收从子组件传递过来的 prop 对象:
// 父组件模板 <div class="parent"> <child-component> <template slot-scope="props"> <span>msg from parent</span> <span>{{ props.text }}</span> </template> </child-component> </div> // 渲染成: <div class="parent"> <div class="child"> <span>msg from parent</span> <span>msg from child</span> </div> </div>
在组件开发中,Element-UI广泛使用
demo:
// 父组件模版
......其他模版代码
<list :data="listData" class="img-list"> <template scope="scope"> <div class="info"> <p>数据:{{scope}}</p> <p>索引:{{scope.$index}}</p> <p>姓名:{{scope.row.name}}</p> <p>性别:{{scope.row.sex}}</p> </div> </template> </list>
........其他模版代码
// 子组件模版 list <ul> <li v-for="(item,i) in data"> <slot :row="item" :$index="i"></slot> </li> </ul>
js:
......
props: {
data: {
default: [],
type: Array
}
}
.....
父模版渲染后:
<ul> <li v-for="(item,i) in data"> <div class="info"> <p>数据:{{item}}</p> <p>索引:{{item.i}}</p> <p>姓名:{{item.name}}</p> <p>性别:{{item.sex}}</p> </div> </li> </ul>
父组件把数据listData传递给子组件 data , 子组件通过作用域插槽把值传递给父组件scope
注意:<slot :row="item" :$index="i"></slot> 这里的属性在上面list组件调用的时候就会打印出一个对象{ "row": { "name": "张三", "sex": "男" }, "$index": 0 }
v2.5.0+
slot-scope
能被用在任意元素或组件中而不再局限于 <template>
// 子组件模版 my-list <ul> <slot name="item-child" v-for="item in items" :text="item.text"> <!-- 这里写入备用内容 --> </slot> </ul>
// 父组件模版
<my-list :items="items"> <li slot="item-child" slot-scope="props" class="my-fancy-item"> {{ props.text }} </li> </my-list>