# 插槽

Vue 实现了一套内容分发的 API,将 <slot></slot> 元素作为承载分发内容的出口。 插槽(Slot)是 Vue 提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。 插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制

插槽就是 Vue 实现的一套内容分发的 API,将元素作为承载分发内容的出口。

# 插槽slot

插槽内可以是任意内容。

<div id="app">
	<child-component></child-component>
</div>
<script>
	Vue.component("child-component", {
		template: `
            <div>
            Hello,World!
            <slot></slot>
            </div>
        `,
	});
	let vm = new Vue({
		el: "#app",
		data: {},
	});
</script>

# 具名插槽

具名插槽,用于标记往哪个具名插槽中插入子组件内容。简单理解就是 给每一个 slot 一个name属性,父组件中 使用子组件标签时用的v-slot:name要跟子组件的name匹配上,才会渲染出来,就是 默认插槽 !!

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta http-equiv="X-UA-Compatible" content="ie=edge" />
		<title>Document</title>
		<script src="lib/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<com>
				<template v-slot:header>
					<h1>标题</h1>
				</template>
				<template v-slot:main>
					<h2>内容</h2>
				</template>
				<template v-slot:footer>
					<h3>底部内容</h3>
				</template>
			</com>
		</div>
		<script>
			var vm = new Vue({
				el: "#app",
				data() {
					return {
						info: 1,
					};
				},
				components: {
					com: {
						template: `
                    <div class="container">
                        <header>
                            <slot name="header"></slot>
                        </header>
                        <main>
                            <slot name="main"></slot>
                        </main>
                        <footer>
                            <slot name="footer"></slot>
                        </footer>
                    </div>
                    `,
					},
				},
			});
		</script>
	</body>
</html>

# 编译作用域

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

<div id="app">
	{{ red }}
	<com1></com1>
</div>
<script>
	var vm = new Vue({
		el: "#app",
		data() {
			return {
				isActive: true,
				red: "red",
			};
		},
		components: {
			com1: {
				data() {
					return {
						info: "子组件内容",
					};
				},
				template: "<h2>我是子组件{{ info }} {{ red }}</h2>", // Property or method "red" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
			},
		},
	});
</script>

# 后备内容 当在组件里面没有写内容时在 slot 里面默认渲染的内容

<div id="app">
	{{ red }}
	<com1></com1>
</div>
<script>
	var vm = new Vue({
		el: "#app",
		data() {
			return {
				isActive: true,
				red: "red",
			};
		},
		components: {
			com1: {
				data() {
					return {
						info: "子组件内容",
					};
				},
				template: "<h2>我是子组件{{ info }}<slot>我是插槽的默认内容</slot></h2>",
			},
		},
	});
</script>

# 作用域插槽

用作访问我们组件里面的属性

template 内可以通过临时变量 props 来访问来自子组件插槽的数据 msg

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta http-equiv="X-UA-Compatible" content="ie=edge" />
		<title>Document</title>
		<script src="lib/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<com :list="list">
				<template v-slot:default="slotProps">
					<li @click="slotProps.item.age++">{{slotProps.item.name}}{{slotProps.item.age}}</li>
				</template>
			</com>
		</div>
		<script>
			var vm = new Vue({
				el: "#app",
				data() {
					return {
						list: [
							{
								name: "张三",
								age: 40,
							},
							{
								name: "李四",
								age: 40,
							},
						],
					};
				},
				components: {
					com: {
						props: ["list"],
						data() {
							return {};
						},
						template: `
                        <ul><slot v-for="item in list" :item = "item"></slot></ul>
                    `,
					},
				},
			});
		</script>
	</body>
</html>
上次更新: 11/26/2019, 10:43:50 AM