参考
具名插槽
vue 2.6+废弃
在Test.vue中使用BaseLayout 组件,在向具名插槽提供内容的时候,我们可以在一个父组件的 元素上使用 slot 特性
<template>
<div class="test">
<base-layout>
<template slot="header">
<h1>header</h1>
</template>
<p>main1</p>
<p>main2</p>
<template slot="footer">
<h1>footer</h1>
</template>
</base-layout>
</div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
name: "",
components: { BaseLayout },
data() {
return {};
},
methods: {},
mounted() {}
};
</script>
<style lang="less" scoped></style>
或者直接用在一个普通的元素上:Test.vue内容
<template>
<div class="test">
<base-layout>
<h1 slot="header">header</h1>
<p>main1</p>
<p>main2</p>
<template slot="footer">
<h1>footer</h1>
</template>
</base-layout>
</div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
name: "",
components: { BaseLayout },
data() {
return {};
},
methods: {},
mounted() {}
};
</script>
<style lang="less" scoped></style>
BaseLayout .vue组件
<template>
<!-- 组件 -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
<script>
export default {
name: "",
components: {},
data() {
return {};
},
methods: {},
mounted() {}
};
</script>
<style lang="less" scoped></style>

访问Test.vue页面内容如下

我们可以使用 v-slot 指令改写上面的Test.vue
<template>
<div class="test">
<base-layout>
<!-- <h1 v-slot:header>header</h1> -->
<p>main1</p>
<p>main2</p>
<template v-slot:footer>
<h1>footer</h1>
</template>
</base-layout>
</div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
name: "",
components: { BaseLayout },
data() {
return {};
},
methods: {},
mounted() {}
};
</script>
<style lang="less" scoped></style>
注意:<h1 v-slot:header>header</h1>这种写法是错误的,v-solt只能用在template上面
插槽的名字现在通过 v-slot:slotName 这种形式来使用
Tips: 没有名字的 <slot> 隐含有一个 "default" 名称
例如,上面的默认插槽,如果你想显示调用的话,可以这样:
<template>
<div class="test">
<base-layout>
<template v-slot:header>
<h1>header</h1>
</template>
<template v-slot:default>
<p>main1</p>
<p>main2</p>
</template>
<template v-slot:footer>
<h1>footer</h1>
</template>
</base-layout>
</div>
</template>
<script>
import BaseLayout from "./BaseLayout";
export default {
name: "",
components: { BaseLayout },
data() {
return {};
},
methods: {},
mounted() {}
};
</script>
<style lang="less" scoped></style>
总结:父组件中具名插槽slot="header"内容会进入子组件对应的名字中<slot name="header"></slot>
作用域插槽
父组件中访问子组件的插槽绑定的值
父组件 Test.vue中
<template>
<div id="app">
<!-- 子组件 -->
<user v-slot:default="slotProps">
<!-- 插槽内容 -->
{{ slotProps.user.firstName }}
</user>
</div>
</template>
<script>
import User from "./User.vue";
export default {
name: "app",
components: {
User
}
};
</script>
<style></style>
子组件User.vue中
<template>
<div>
<!-- 作用域插槽:插槽prop -->
<slot :user="user">
<!-- 后备内容 -->
{{ user.lastName }}
</slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
firstName: "张",
lastName: "三"
}
};
}
};
</script>
<style></style>
结果:

在这个栗子中,我们选择 slotProp作为我们的slot props名字,但你可以使用你喜欢的任何名字。
- 父组件 Test.vue还可以这么写,将
v-slot:default="slotProps"改为v-slot="slotProps"上面
<template>
<div id="app">
<!-- 子组件 -->
<user v-slot="slotProps">
<!-- 插槽内容 -->
{{ slotProps.user.firstName }}
</user>
</div>
</template>
<script>
import User from "./User.vue";
export default {
name: "app",
components: {
User
}
};
</script>
<style></style>
- 父组件 Test.vue还可以这么写,将
v-solt写在template上面
<template>
<div id="app">
<!-- 子组件 -->
<user>
<template v-slot:default="slotProps">
<!-- 插槽内容 -->
{{ slotProps.user.firstName }}
</template>
</user>
</div>
</template>
<script>
import User from "./User.vue";
export default {
name: "app",
components: {
User
}
};
</script>
<style></style>
- 父组件 Test.vue还可以这么写,
v-slot:default="slotProps"改为v-slot="slotProps"
<template>
<div id="app">
<!-- 子组件 -->
<user>
<template v-slot="slotProps">
<!-- 插槽内容 -->
{{ slotProps.user.firstName }}
</template>
</user>
</div>
</template>
<script>
import User from "./User.vue";
export default {
name: "app",
components: {
User
}
};
</script>
<style></style>
单个默认插槽的缩写形式
总结上面的作用域插槽。在上述情况下,当且仅当提供了默认插槽内容时,我们可以使用 v-slot 直接作用在组件上:
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
我们可以简化上面的的默认插槽写法:
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
请注意了,默认插槽的缩写语法不能与具名插槽混用:
<!-- 控制台将报警告:-->
<!-- To avoid scope ambiguity, the default slot should also use <template> syntax when there are other named slots. -->
<!-- 意思就是说,为了避免作用域模糊 -->
<!-- 当有其他具名插槽时,默认插槽也应当使用 '<template>' 模板语法 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
<template v-slot:other="otherSlotProps">
slotProps is NOT available here
</template>
</current-user>
于是,上面的代码,我们改写成:
<current-user>
<!-- 两种写法均可 -->
<!--<template v-slot="slotProps">
{{ slotProps.user.firstName }}
</template>-->
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user>
插槽内容的解构赋值
作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:
function (slotProps) {
// 插槽内容
}
这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop
父组件Test.vue
<template>
<div id="app">
<!-- 子组件 -->
<user v-slot="{ user }">
<!-- 插槽内容 -->
{{ user }}
<br />
{{ user.firstName }}
</user>
</div>
</template>
<script>
import User from "./User.vue";
export default {
name: "app",
components: {
User
}
};
</script>
<style></style>
这时候访问Test.vue显示的内容为

子组件 User.vue
<template>
<div>
<!-- 作用域插槽:插槽prop -->
<slot :user="user">
<!-- 后备内容 -->
{{ user.lastName }}
</slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
firstName: "张",
lastName: "三"
}
};
}
};
</script>
<style></style>
**父组件Test.vue<user v-slot="{ user }">里面的user必须和子组件User.vue中<slot :user="user">的:user**保持一致,例如
Test.vue
<template>
<div id="app">
<!-- 子组件 -->
<user v-slot="{ person }">
<!-- 插槽内容 -->
{{ person }}
<br />
{{ person.firstName }}
</user>
</div>
</template>
<script>
import User from "./User.vue";
export default {
name: "app",
components: {
User
}
};
</script>
<style></style>
User.vue
<template>
<div>
<!-- 作用域插槽:插槽prop -->
<slot :person="user">
<!-- 后备内容 -->
{{ user.lastName }}
</slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
firstName: "张",
lastName: "三"
}
};
}
};
</script>
<style></style>
结果

- 这样可以使模板更简洁,尤其是在该插槽提供了多个 prop 的时候。它同样开启了 prop 重命名等其它可能,例如将 person重命名为 people:
Test.vue
<template>
<div id="app">
<!-- 子组件 -->
<user v-slot="{ person: people }">
<!-- 插槽内容 -->
{{ people }}
<br />
{{ people.firstName }}
</user>
</div>
</template>
<script>
import User from "./User.vue";
export default {
name: "app",
components: {
User
}
};
</script>
<style></style>
User.vue
<template>
<div>
<!-- 作用域插槽:插槽prop -->
<slot :person="user">
<!-- 后备内容 -->
{{ user.lastName }}
</slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
firstName: "张",
lastName: "三"
}
};
}
};
</script>
<style></style>
结果
- 你甚至可以定义后备内容,用于插槽 prop 是 undefined 的情形:
命名插槽简写
这个简单一些,就不去写实例了
2.6.0+ 新增
与 v-on和 v-bind类似,v-slot 也有一个简写,即使用 #代替 v-slot。例如, v-slot:header 简写成 #header:
<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>
也就是说,如果你想使用简写语法,则务必指定插值的名字:
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>

本文深入探讨Vue.js中的插槽概念,包括具名插槽、作用域插槽、默认插槽的使用方法及其实例,讲解如何在父组件中向子组件传递内容和数据,并展示插槽内容解构赋值及简写语法。
834

被折叠的 条评论
为什么被折叠?



