1、动态组件
针对以上问题我们可以使用v-if和v-show等方式来解决
在vue中我们还提供了一种解决方式,就是利用动态组件来实现
1、准备两个需要切换的组件
- UserName.vue
<template>
<div>
<span>用户名:</span>
<input type="text" name="" id="" />
<span>密码:</span>
<input type="text" name="" id="" />
</div>
</template>
<script>
export default {};
</script>
<style>
</style>
- UserInfo.vue
<template>
<div>
<div>
<span>人生格言:</span>
<input type="text" />
</div>
<div>
<span>个人简介</span>
</div>
</div>
</template>
<script>
export default {};
</script>
<style>
</style>
2、引入到UseTab.vue注册
import UserName from "@/components/Demo01/UserName";
import UserInfo from "@/components/Demo01/UserInfo";
export default {
// 注册组件
components: {
UserName,
UserInfo,
},
};
3、准备变量来承载要显示的"组件名"
data() {
return {
//设置挂载点
comName: "UserName",
};
},
4、设置挂载点<component>
, 使用is属性来设置要显示哪个组件
<component :is="comName"></component>
5、点击按钮 – 修改comName变量里的"组件名"
<button @click="comName='UserName'">账号密码填写</button>
<button @click="comName='UserInfo'">个人信息填写</button>
6、完整代码
<template>
<div>
<button @click="comName='UserName'">账号密码填写</button>
<button @click="comName='UserInfo'">个人信息填写</button>
<p>下面显示注册的组件</p>
<div class="contain">
<component :is="comName"></component>
</div>
</div>
</template>
<script>
// 导入组件
import UserName from "@/components/Demo01/UserName";
import UserInfo from "@/components/Demo01/UserInfo";
export default {
data() {
return {
//设置挂载点
comName: "UserName",
};
},
// 注册组件
components: {
UserName,
UserInfo,
},
};
</script>
<style lang="less" scoped>
.contain {
width: 500px;
height: 200px;
border: 1px solid red;
}
</style>
【效果图】:
7、App.vue
<template>
<div>
<h1>动态组件的使用</h1>
<UseTab></UseTab>
</div>
</template>
<script>
// 导入组件
import UseTab from "@/components/Demo01/UseTab";
export default {
components: {
UseTab,
},
};
</script>
<style>
</style>
2、组件缓存
1、问题演示
【代码修改】:
- UserName.vue
export default {
created() {
console.log("username组件---创建了");
},
destroyed() {
console.log("username组件---销毁了");
},
};
</script>
- UserInfo.vue
export default {
created() {
console.log("userInfo组件---创建了");
},
destroyed() {
console.log("userInfo组件---销毁了");
},
};
</script>
【结果图】:
2、问题解决
使用keep-alive内置的vue组件, 让动态组件缓存而不是销毁
【代码修改】:
<keep-alive>
<component :is="comName"></component>
</keep-alive>
【效果图】:
3、组件插槽
vue提供组件插槽能力, 允许开发者在封装组件时,把不确定的部分定义为插槽
1、基本使用
- 组件内用
<slot></slot>
占位 - 使用组件时夹着的地方, 传入标签替换slot
2、折叠面板案例重新演示
- 准备折叠面板组件
在内容区域使用slot标签进行占位
<template>
<div>
<!-- 按钮标题 -->
<div class="title">
<h4>芙蓉楼送辛渐</h4>
<span class="btn" @click="isShow = !isShow">
{{ isShow ? "收起" : "展开" }}
</span>
</div>
<!-- 下拉内容 -->
<div class="container" v-show="isShow">
// 使用组件插槽占位
<slot></slot>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isShow: false,
};
},
};
</script>
<style scoped>
h3 {
text-align: center;
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #ccc;
padding: 0 1em;
}
.title h4 {
line-height: 2;
margin: 0;
}
.container {
border: 1px solid #ccc;
padding: 0 1em;
}
.btn {
/* 鼠标改成手的形状 */
cursor: pointer;
}
img {
width: 50%;
}
</style>
- 准备使用面板的组件
导入面板,并且替换面板内部的内容
<template>
<div id="container">
<div id="app">
<h3>案例:折叠面板</h3>
//使用面板。并替换插槽内部的内容
<Panel>
<img src="../../assets/mm.gif" alt="" />
<span>我是文字哦</span>
</Panel>
<Panel name="">
<p>寒雨连江夜入吴,</p>
<p>平明送客楚山孤。</p>
<p>洛阳亲友如相问,</p>
<p>一片冰心在玉壶。</p>
</Panel>
</div>
</div>
</template>
<script>
import Panel from "@/components/Demo03/Panel";
export default {
components: {
Panel,
},
};
</script>
<style lang="less" scoped>
#app {
width: 400px;
margin: 20px auto;
background-color: #fff;
border: 4px solid blueviolet;
border-radius: 1em;
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);
padding: 1em 2em 2em;
}
</style>
- App.vue
<template>
<div>
<UserPanel></UserPanel>
</div>
</template>
<script>
import UserPanel from "@/components/Demo03/UserPanel";
export default {
components: {
UserPanel,
},
};
</script>
<style>
</style>
【效果图演示】:
3、插槽默认内容设置
<slot>
夹着内容默认显示内容, 如果不给插槽slot传东西, 则使用<slot>
夹着的内容在原地显示
【语法】:
<slot>默认内容</slot>
4、具名插槽
1、具名插槽基本使用
【语法】:
- slot使用name属性区分名字
- template配合v-slot:名字来分发对应标签
2、折叠面板案例修改
途中的#title是一种简写的方式,相当于v-click用@代替
5、作用域插槽
1、使用步骤
- 子组件, 在slot上绑定属性和子组件内的值
- 使用组件, 传入自定义标签, 用template和v-slot=“自定义变量名”
- scope变量名自动绑定slot上所有属性和值
2、折叠面板改造
- 面板组件
- 使用面板组件
3、作用域插槽案例
需求: 封装一个表格组件, 在表格组件内循环产生单元格
- MyTable.vue
<template>
<div>
<table border="1">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>头像</th>
</tr>
</thead>
<thead>
<tr v-for="(item, index) in list" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
<td>
<slot :img="item">{{ item.headImgUrl }}</slot>
</td>
</tr>
</thead>
</table>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{
name: "小传同学",
age: 18,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
},
{
name: "小黑同学",
age: 25,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
},
{
name: "智慧同学",
age: 21,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
},
],
};
},
};
</script>
- UseTable.vue
<template>
<div>
<MyTable>
<template v-slot="imgNew">
<img :src="imgNew.img.headImgUrl" alt="" />
</template>
</MyTable>
</div>
</template>
<script>
import MyTable from "@/components/Table/MyTable";
export default {
components: {
MyTable,
},
};
</script>
<style>
img {
width: 100px;
height: 100px;
border: 1px solid #333;
border-radius: 50px;
margin: 5px;
}
</style>
- App.vue
<template>
<div>
<UseTable></UseTable>
</div>
</template>
<script>
import UseTable from "@/components/Table/UseTable";
export default {
components: {
UseTable,
},
};
</script>
<style>
</style>