案例 组件信息的通信

插槽 v-slot
- 这个时候我们就可以来定义插槽slot: 插槽的使用过程其实是抽取共性、预留不同;
- 我们会将共同的元素、内容依然在组件内进行封装;
- 同时会将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素;
- 如何使用slot呢?
- Vue中将 <slot> 元素作为承载分发内容的出口;
- 在封装组件中,使用特殊的元素<slot>就可以为封装组件开启一个插槽;
- 该插槽插入什么内容取决于父组件如何使用;
插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。简单理解就是子组件中留下个“坑”,父组件可以使用指定内容来补“坑”.

案例一

主页面
<template #bbb>
name=BBB请输入密码:<input type="password" name="" id="" />
</template>
<template>
<div class="App">
<headerTab>
<!-- v-solt 插槽 名称 -->
<template v-slot:aaa>
<a href="name=AAA返回按钮<">name=AAA返回按钮</a>
</template>
<template #bbb>
name=BBB请输入密码:<input type="password" name="" id="" />
</template>
<template #ccc>
name=CCC:<input type="Number">
</template>
<template #ddd>name=DDD <input type="checkbox" name="" id="" />男 </template>
<template #eee> name=EEE<input type="checkbox" name="" id="" />女</template>
<template #[msg]><button>name=fff你好呀</button> </template>
</headerTab>
<headerTab>
<template #[msg]>
<button>返回按钮</button>
</template>
<template v-slot:aaa>
<a href="#">返回按钮</a>
</template>
<template #bbb>
请输入密码:<input type="password" name="" id="" />
</template>
<template #ccc>
点击按钮:<button>{{ msg }}</button>
</template>
<template #ddd> <input type="checkbox" name="" id="" />男 </template>
<template #eee> <input type="checkbox" name="" id="" />女</template>
</headerTab>
<button @click="msg = 'left'">left</button>
<button @click="msg = 'center'">center</button>
<button @click="msg = 'right'">right</button>
<button @click="msg = 'left'">left</button>
<button @click="msg = 'aaa'">aaa</button>
<button @click="msg = 'bbb'">bbb</button>
<button @click="msg = 'ccc'">ccc</button>
<button @click="msg = 'ddd'">ddd</button>
<p>返回</p>
<hr />
<headerTab :propList="propList">
<template v-slot="slotProps">
<div>{{ slotProps.item + " " + slotProps.index }}</div>
</template>
</headerTab>
<hr />
<!-- <headerTab :propList="propList" v-slot="slotProps"> -->
<!-- <div>{{slotProps.item+'-'+slotProps.index}}</div> -->
<!-- </headerTab> -->
</div>
</template>
<script>
import headerTab from "./components/header-tab.vue";
export default {
name: "App",
components: {
headerTab,
},
data() {
return {
msg: "我是登录按钮",
propList: ["王者荣耀", "JavaScript", "Jquery", "Web", "EEEE"],
};
},
methods: {},
};
</script>
<style scoped>
div{
border-top: 2px solid red;
background-color: rgb(124, 188, 225);
}
</style>
子组件
<div class="content">
<div class="item left">
<slot name="aaa"> 请输入姓名:<input type="text" /> </slot>
</div>
<div class="item"><slot name="bbb">请输入邮箱地址:<input type="emil" /></slot></div>
<div class="item"><slot name="ccc">我是a链接:<a href="#">我是a标签</a></slot></div>
<div class="item center">
<!-- 命令 -->
<slot name="ddd">标题</slot>
</div>
<div class="item right">
<slot name="eee">登录</slot>
</div>
<template>
<div class="content">
<div class="item left">
<slot name=" item lefts"> 请输入姓名:<input type="text" /> </slot>
</div>
<div class="item">请输入邮箱地址:<input type="emil" /></div>
<div class="item">我是a链接:<a href="#">我是a标签</a></div>
<div class="item center">
<slot name="center">标题</slot>
</div>
<div class="item right">
<slot name="right">登录</slot>
</div>
</div>
<div class="content">
<div class="item left">
<slot name="aaa"> 请输入姓名:<input type="text" /> </slot>
</div>
<div class="item"><slot name="bbb">请输入邮箱地址:<input type="emil" /></slot></div>
<div class="item"><slot name="ccc">我是a链接:<a href="#">我是a标签</a></slot></div>
<div class="item center">
<!-- 命令 -->
<slot name="ddd">标题</slot>
</div>
<div class="item right">
<slot name="eee">登录</slot>
</div>
</div>
<div>
<div class="item" v-for="item,index in propList" :key="item">
<slot :item="item" :index="index">登录信息</slot>
<slot name="two">我是数据信息</slot>
</div>
</div>
</template>
<script>
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: "left",
props: ["propList"],
data() {
return {
msg: "子组件的msg",
};
},
methods: {},
};
</script>
<style scoped>
.content {
display: flex;
height: 50px;
line-height: 50px;
text-align: center;
display: flex;
}
.item {
margin-top: 3px;
border-left: 2px solid red;
flex: 1;
background-color: rgb(166, 236, 167);
color: rgb(0, 0, 0);
}
.left {
background: rgb(171, 220, 223);
}
.center {
background: rgb(50, 174, 28);
}
.right {
background: rgb(10, 155, 213);
}
</style>
案例二 兄弟的组件直接转送值


主页面
<template>
<div class="app">
<h3 style="color:red">Provide和Inject基本使用</h3>
<home></home>
<hr>
<content></content>
</div>
</template>
<script>
import content from "./components/content.vue";
import home from "./components/home.vue";
export default {
name: "app",
data() {
return {
message: "Hello world vue cli",
};
},
components: {
// eslint-disable-next-line vue/no-unused-components
content,
// eslint-disable-next-line vue/no-unused-components
home,
},
methods: {
btnclick() {
console.log("为难忘");
},
},
};
</script>
<style scoped>
</style>
子组件1
<template>
<div class="content">
<home></home>
</div>
</template>
<script>
import home from "../components/home.vue";
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: "content",
data() {
return {
message: "Hello world vue cli",
};
},
// 定义对象
provide: {
name: "李四",
age: 20,
height: 123,
weight: 78,
email: "2678903458@qq.com",
qq: "2386754567",
weixing: "12389999933",
},
// 函数的写法
methods: {
btnclick() {
console.log("为难忘");
},
},
components: {
// eslint-disable-next-line vue/no-unused-components
home,
},
};
</script>
<style scoped>
</style>
// 定义对象
provide: {
name: "李四",
age: 20,
height: 123,
weight: 78,
email: "2678903458@qq.com",
qq: "2386754567",
weixing: "12389999933",
},
子组件2
// 取值
inject: ["name", "age", "height", "weight", "email", "qq", "weixing"],
<template>
<h6>
在home.vue组件中和content组件中利用 provide定义对象 利用 inject取出对象
</h6>
<div class="home">
<content></content>
<table>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>身高</th>
<th>体重</th>
<th>邮箱</th>
<th>qq</th>
<th>微信</th>
</tr>
<tr>
<td>
<span>{{ name }}</span>
</td>
<td>
<span>{{ age }}</span>
</td>
<td>
<span>{{ height }}</span>
</td>
<td>
<span>{{ weight }}</span>
</td>
<td>
<span>{{ email }}</span>
</td>
<td>
<span>{{ qq }}</span>
</td>
<td>
<span>{{ weixing }}</span>
</td>
</tr>
</table>
</div>
</template>
<script>
import content from '../components/content.vue'
// home 与content组件为兄弟元素
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: "home",
data() {
return {
message: "Hello world vue cli",
};
},
components: {
// eslint-disable-next-line vue/no-unused-components
content
},
// 取值
inject: ["name", "age", "height", "weight", "email", "qq", "weixing"],
methods: {
btnclick() {
console.log("为难忘");
},
},
};
</script>
<style scoped>
.home {
background-color: rgb(214, 248, 177);
display: flex;
}
.home span {
font-size: 20px;
background-color: rgb(236, 253, 239);
color: red;
flex: 1;
}
table {
width: 100%;
background-color: rgb(176, 230, 232);
color: rgb(255, 0, 0);
font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
}
td {
width: 18%;
border-radius: 10px;
}
td {
text-align: center;
line-height: 60px;
height: 60px;
border: 3px solid green;
}
</style>
组件通信答案
<!-- eslint-disable vue/require-v-for-key -->
<template>
<div class="app">
<div class="big_father">
<span
v-for="(item, index) in arrays"
:key="index.id + ''"
class=".big_father"
:class="{ active: isshow === index }"
@click="btnclick(index)"
>{{ item }} {{ index }}</span
>
</div>
<div>
<span
v-for="(item, index) in infor"
:key="index.id + ''"
class=".big_father"
:class="{ active: isshow === index }"
@click="btnclick1(ko)">{{ item }} {{ index }}</span
>
</div>
<yf v-show="isshow === 0"></yf>
<kz v-show="isshow === 1"></kz>
<xz v-show="isshow === 2"></xz>
<sy v-show="isshow === 3"></sy>
<wt v-show="isshow === 4"></wt>
</div>
</template>
<script>
// 导入文件信息
import yf from "./components/yf.vue";
import xz from "./components/xz.vue";
import kz from "./components/kz.vue";
import sy from "./components/sy.vue";
import wt from './components/wt.vue';
export default {
components: {
// eslint-disable-next-line vue/no-unused-components
yf,
// eslint-disable-next-line vue/no-unused-components
xz,
// eslint-disable-next-line vue/no-unused-components
kz,
// eslint-disable-next-line vue/no-unused-components
sy,
wt
},
name: "app",
data() {
return {
message: "Hello world vue cli",
isshow: 0,
arrays: ["衣服", "鞋子", "裤子", "上衣", "外套"],
infor: ["衣服页面", "鞋子页面", "裤子页面", "上衣页面", "外套页面"],
index:0,
ko:true
};
},
methods: {
btnclick(flag) {
this.isshow = flag;
},
btnclick1(ko){
this.ko= !ko
}
},
};
</script>
<style scoped>
.active {
color: red;
background-color: azure;
border: 2px solid lightseagreen;
border-bottom: 8px solid red;
border-radius: 12px;
}
.big_father {
display: flex;
}
.big_father div {
text-align: center;
height: 60px;
line-height: 60px;
flex: 1;
color: white;
background-color: rgb(28, 125, 147);
}
.big_father div span {
text-align: center;
height: 60px;
line-height: 60px;
width: 100px;
flex: 1;
color: white;
background-color: rgb(116, 214, 236);
}
button {
height: 60px;
width: 100px;
line-height: 60px;
margin-left: 100px;
}
span {
text-align: center;
line-height: 60px;
margin-left: 10px;
display: inline-block;
width: 17%;
height: 60px;
font-size: 20px;
border-radius: 20px;
background: rgb(121, 224, 235);
border-right: 2px solid red;
}
</style>