编译作用域
<child-component>
{{message}}
</child-component>
<!--在这里,{{massage}}的数据应该是父组件的数据,而不是child-componet的数据-->
在vue组件中作用域简单的说就是:
父组件模板的内容在父组件的作用域内编译,子组件模板的内容在子组件的作用域内编译
一个常见的错误是我们会试图在父组件内将一个指令绑定到子组件的属性/方法
<child-component v-show="someChildProperty"></child-component>
如果someChildProperty是子组件的属性,那么这种做法是无效的,在vue中父模板是不应该知道子组件状态的,如果想要通过子组件的someChildProperty来控制子组件的show/hide,那么应该在子组件内对其进行设置
单个插槽
在我们使用组件时,父组件在子组件标签内写入的内容都会被丢弃,例如
<child-component>
<p>父组件的内容</p> <!--不会显示-->
</child-component>
如果我们想要在子组件渲染时能够渲染出父组件添加的内容,需要为子组件组件中设置slot插槽
当子组件内只有一个没有属性的插槽时,父组件在调用子组件时在子组件内添加的内容将全部插入到插槽所在的DOM节点的位置,并替换掉插槽标签本身
最初在插槽标签内的任何元素都将会被视为默认内容,默认内容在子组件的作用域内编译,只有在宿主元素为空,且没有插入内容的时候才显示
<body>
<div id="box">
<h4>This's parent</h4>
<child>
<h4>推荐好友列表</h4>
<ul>
<li>tom</li>
</ul>
</child>
</div>
<template id="childTem">
<div>
<h4>This's child</h4>
<slot>
<p>您还没有推荐好友~</p>
</slot>
</div>
</template>
<script>
new Vue({
components:{
'child':{
template:"#childTem"
}
}
}).$mount("#box")
</script>
</body>
具名插槽
slot元素可以用一个特殊的属性name来配置如何分布内容,多个插槽可以有不同的名字,设置有name属性的插槽会匹配到父组件中具有相同值的具有slot属性的元素
仍然可以有匿名的插槽,它会作为默认插槽存在,在插槽找不到匹配的slot值或不具有name的插槽会被插入到匿名的插槽中
<body>
<div id="box">
<h2>具名插槽</h2>
<child>
<h4 slot="header">{{parentMsg}}</h4>
<p>Test</p>
<div>
<p>1.父组件数据</p>
<p>2.展示slot使用方法</p>
</div>
<h6 slot="footer">parentFooter</h6>
</child>
</div>
<template id="childTem">
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
<script>
new Vue({
data: {
parentMsg: 'parentHeader'
},
components: {
'child': {
template: '#childTem'
}
}
}).$mount('#box')
</script>
</body>
作用域插槽
+2.1.0新增
作用域插槽是一种特殊类型的插槽,可以用来将子组件的数据展示到slot插槽中
在子组件中,只需要将数据传递到插槽,就像我们将props传递给组件一样,格式为
<slot :text="变量值"></slot>
<!--text是我们自定义的变量名,:表示是动态的,变量值为我们要从子组件中传递的数据-->
在父级中,具有特殊属性的的scope的template元素必须存在,表示这是作用域插槽的模板,scope的值对应一个临时变量名,此变量接收从子组件中传递的props对象,格式为:
<child>
<template slot-scope="props">
<!--props是我们自定义的名称-->
<span>{{props}}</span>
<!--props会接收所有的slot上传递的变量值,并将其合成为一个对象,如上面的例子,打印props会得到
{text:变量值}
-->
</template>
</child>
在2.5.0之后的版本官方用slot-scope替换了scope
<body>
<div id="box">
<child>
<template slot-scope="props" slot="test">
<li>{{props.item.name}}</li>
<li>{{props.item.age}}</li>
</template>
</child>
</div>
<template id="childTem">
<ul>
<slot
name="test"
v-for="item in items"
:item="item"
></slot>
</ul>
</template>
<script>
new Vue({
components: {
"child": {
template: "#childTem",
data() {
return {
items: [
{
name: 'xm',
age: 18
}
]
}
}
}
}
}).$mount("#box")
</script>
</body>
这种用法在我们使用Element时非常常见,例如在使用表格组件时需要根据后台返回的1、2、3展示对应状态已完成、未完成、已驳回
<el-table-column
label="状态"
minWidth="150">
<template slot-scope="scope">
<span v-if="scope.row.state==1">已完成</span>
<span v-else-if="scope.row.state==2">未完成</span>
<span v-else @click="turn" class="turn">已驳回</span>
</template>
</el-table-column>
在使用slot-scope时,支持es 6 的对象解构语法,例如上面的例子,我们可以改写为
<el-table-column
label="状态"
minWidth="150">
<template slot-scope="{row}">
<span v-if="row.state==1">已完成</span>
<span v-else-if="row.state==2">未完成</span>
<span v-else @click="turn" class="turn">已驳回</span>
</template>
</el-table-column>