一、定义一个vue分页组件,实现客户端分页功能

1.1、子组件A(页数按钮)

<!-- 本组件用于遍历分页的页数按钮 -->
<template lang="">
<div class="btn-box">
<!-- 页数,下标+1 -->
{{pzie + 1}}
</div>
</template>
<script lang="ts">
import { ref } from 'vue'
export default {
// 接收参数 "size"
props: ['size'],
setup (p:any) {
// 响应式参数
const pzie = ref(p.size)
// 暴露出去页面上
return { pzie }
}
}
</script>
<style >
.btn-box{
width: 30px;
height: 30px;
line-height: 30px;
border-radius: 2.5px;
background-color: #ddd;
}
</style>

1.1、父组件

<!-- 本组件用于实现分页的功能 -->
<template lang="">
<div>
<!-- 表格里面的数据 -->
<table border="1" width="60%">
<tr>
<th>商品编号</th>
<th>商品名称</th>
<th>商品价格</th>
</tr>
<!-- 遍历数据到表格上 -->
<tr v-for="item in data" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
</tr>
</table>
<div class="btn2-box">
<button @click = btnsx(0)>上一页</button>
<!-- 显示页数的按钮 -->
<!-- 功能:添加类、:size="i":(传下标到子组件里显示页数) -->
<Btn class="Btn-st" v-for="(item, i) in list.btncount" :class="{'addclass': list.addclass==i}" :key="i" :size="i" @click="clicknext(i)"></Btn>
<button @click = btnsx(1)>下一页</button>
<div class="skip">
跳转到:<input type="text" v-model="nums"> 页
<button @click="skip()">Go</button>
</div>
</div> </div>
</template>
<script lang="ts">
// 导入子组件文件
import Btn from "../components/1.1 分页按钮.vue";
import { reactive, ref, toRefs } from 'vue'
export default {
// 注册子组件
components: {
Btn
},
setup() {
// 参数1:模拟数据库里的数据
// 参数2:在页面上显示的数据
// 参数3:显示在分页上的总条数、当前页、每页显示的数量、总页数
const s: any = reactive({ sql: [], data: [], list: {} }); // 绑定跳转页面的文本框数据
let nums:any = ref(1); // 循环100条数据
for (let i = 0; i < 100; i++) {
// 把100条数据存储到sql数组里面
s.sql.push({
id: i + 1, // 编号,从1开始
name: `桃子${i + 1}`, // 名称后面+1
price: `${(i + 100) * 2}` // 价格
})
}
// 添加属性到参数3里面
s.list.toal = s.sql.length // 总数据长度
s.list.danqianye = 1 // 当前页 默认为 1
s.list.pagezie = 10 // 每一页显示数量
s.list.btncount = s.list.toal / s.list.pagezie // 总页数 = 总数据长度 / 每一页显示数据数量
s.list.addclass = 0; // 这个变量用于给显示页数的按钮(有颜色)添加类 // 参数1 等于数据源(sql)起点下标 例如0 就等于从 s.sql[0] 开始拿数据
// 参数2 等于数据源(sql)终点下标 例如10 就等于从 s.sql[9] 结束
function createfenye(ii: any, i2: any) {
// 每次进来都要清空之前所缓存的数据,要不然就实现不了下一页的效果
s.data = []
// 每一页的数据从参数1开始,到参数2结束
for (let i = ii; i < i2; i++) {
// 然后重新赋值给s.data数组
s.data.push(s.sql[i])
} }
// 初始化的时候就从0条数据开始到10条数据结束获取数据
createfenye(0, 10) // 该方法用于实现点击页数按钮功能,传入该页数按钮中的下标
function clicknext(i: any) {
// 当前页赋值为i,跟着下标的变化而变化当前页的值
s.list.danqianye = i
// 显示页数按钮(有颜色)的值也需要变化
s.list.addclass = i // 例如 i 的下标等于 0 的时候 i+1,就代表它在第一页
// 1 × 10 等于10, 10 - 10 = 0 说明它是从0 开始 赋值数据到 s.data 里边
// i 的下标等于 0 终点就等于 i + 1 = 1, 1 x 10 = 10, 说明它是从10 结束 赋值
createfenye(((i + 1) * 10 - 10), ((i + 1) * 10))
} // 该方法用于实现点击上一页与下一页功能,传入1(下一页)或0(上一页)判断用户点击的是哪个按钮
function btnsx(i: any) {
if (i == 0) { // i为0,即点击了上一页
// 获取到上一页的数据
createfenye(((s.list.danqianye - 1) * 10 - 10), ((s.list.danqianye - 1) * 10))
// 然后当前页也需要-1
s.list.danqianye--
// 显示页数按钮(有颜色)也需要后退一个
s.list.addclass--
} else {
// 与上面相反
createfenye(((s.list.danqianye + 1) * 10 - 10), ((s.list.danqianye + 1) * 10))
s.list.danqianye++
s.list.addclass++
}
} // 该方法用于跳转页面的
function skip(){
// 当前页赋值为i,跟着下标的变化而变化当前页的值
s.list.danqianye = nums.value
// 显示页数按钮(有颜色)的值也需要变化
s.list.addclass = nums.value console.log(s.list.danqianye);
console.log(s.list.addclass); createfenye(((s.list.danqianye) * 10 - 10), ((s.list.danqianye) * 10))
s.list.addclass--
} // 暴露到页面上
return {
...toRefs(s),
clicknext,
btnsx,
nums,
skip
}
}
}
</script>
<style >
table {
margin: auto;
height: 350px;
border-collapse: collapse;
} th {
background-color: pink;
color: #fff;
} .btn2-box {
display: flex;
width: 60%;
margin: auto;
margin-top: 30px; } .Btn-st {
margin: 5px;
cursor: pointer;
} .addclass {
background-color: pink;
color: #fff;
} .skip {
width: 240px;
height: 30px;
/* border: 1px solid red; */
margin-left: 30px;
margin-top: 5px;
}
.skip input{
width: 70px;
height: 20px;
text-align: center;
outline: none;
}
.skip button{
height: 26px;
margin-left: 10px;
} </style>

1.3、运行结果

二、使用vue3实现图书列表与详细展示功能

2.1、子组件A(可能想搜的)

<!-- 本组件为图书列表中的“ 可能想搜索的图书 ” 部分 -->
<template lang="">
<!-- 把从父组件传过来的数据通过遍历循环出来 -->
<div class="hot-min" v-for="(item,i) in list.hot">{{item}}</div>
</template>
<script lang="ts">
import { reactive, ref, toRefs } from 'vue';
export default {
// 接收参数
props: ['data'],
setup(p:any) {
// 定义一个变量把数据存储起来
const s:any = reactive({list:[] });
s.list.hot= p.data
// 暴露出去页面上
return { ...toRefs(s) }
}
}
</script>
<style>
.hot-min {
width: 80px;
height: 40px;
background-color: #fff;
margin: 10px;
line-height: 40px;
}
</style>

2.2、子组件B(图书列表)

<!-- 本组件用于显示所有的图书列表 -->
<template lang="">
<div class="main" v-for="(item,i) in list.hot" @click="clicklist(item)">
<div class="main_left">
<img :src="item.tp" alt="" >
</div>
<div class="main_right" >
<p style="font-size: 18px;">{{item.name}}</p>
<p style="color: #aaa;font-size: 14px;">{{item.zz}}</p>
<p style="color: red;font-size: 16px;">¥ {{item.price}}</p>
</div>
</div>
</template> <script lang="ts">
// 导入路由文件
import { useRouter } from 'vue-router'
import { reactive, toRefs } from 'vue';
export default {
setup() {
const s: any = reactive({ list: [], list2: [] });
s.list.hot = [
{ name: "web 前端开发", zz: "南方IT学院", price: "62.4", tp: "https://ts1.cn.mm.bing.net/th/id/R-C.5c5ec1769389901eac83e9cf75a5bd33?rik=GXnLovzVPOcEUg&riu=http%3a%2f%2fwww.tup.tsinghua.edu.cn%2fupload%2fbigbookimg3%2f080900-01.jpg&ehk=4efizNnDT%2fRsmCZVq5H2UkONQ%2bBT2oOu6%2br%2bP511Lv0%3d&risl=&pid=ImgRaw&r=0" },
{ name: "JavaScript语言精粹", zz: "清华大学出版社", price: "88.9", tp: "https://pic2.zhimg.com/v2-a4265bf1750016b9a83abdc60a8471c7_b.jpg" },
{ name: "HTML5权威指南", zz: "北京大学出版社", price: "108.0", tp: "https://codesheep.oss-cn-hangzhou.aliyuncs.com/blog/20200916233828.png" },
{ name: "ES6标准入门", zz: "清华大学出版社", price: "35.8", tp: "https://pic2.zhimg.com/v2-17c68027e62866178d5159374318ad7d_b.jpg" },
{ name: "图解css3", zz: "南方it学院", price: "11.2", tp: "https://pic2.zhimg.com/v2-64c56a356fa4777037ffd15233417585_b.jpg" },
{ name: "node.js", zz: "人民大学出版社", price: "77.9", tp: "https://ts1.cn.mm.bing.net/th/id/R-C.a6bfd782f3aa77ca473a208514a65e18?rik=r07N6f2SwTOl1w&riu=http%3a%2f%2fwww.fairysoftware.com%2fad_images%2fqian_duan_kai_fa_06.jpg&ehk=6nr%2fdlTyGl4EtlcAJu3KDeRyRLAH9VvZC8Ae58EB1y0%3d&risl=&pid=ImgRaw&r=0" },
] // 路由跳转
const $router = useRouter();
// 该方法实现点击每一个图书时,跳转到该图书的详情页上,通过query传递点击的图书信息参数过去
function clicklist(item:any) {
// path是路由路径
$router.push({ path:'info', query:item })
console.log(item);
} // 暴露出去页面上
return { ...toRefs(s),clicklist }
}
}
</script>
<style>
/* 身体 */
.main {
width: 90%;
height: 100px;
margin: auto;
/* border: 1px solid magenta; */
margin-top: 20px;
display: flex; } .main_left {
width: 35%;
height: 100%;
} .main_left img {
width: 100%;
height: 100%;
object-fit: contain;
} .main_right {
width: 65%;
height: 100%;
padding-bottom: 10px;
border-bottom: 1px solid #aaa; } .main_right p {
text-align: left;
line-height: 20px;
margin: 10px;
}
</style>

2.3、子组件C(图书详情页)

<!-- 本组件用于展示某一本图书信息的详情页 -->
<template lang="">
<div class="headinfo">
<svg t="1667807456323" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2517" width="25" height="32"><path d="M677.391515 873.916768c-7.86101 0-15.618586-2.999596-21.617778-8.895354L324.473535 533.721212c-11.998384-11.894949-11.998384-31.340606 0-43.235555L655.670303 159.288889c5.999192-5.999192 13.756768-8.895354 21.617778-8.895354 7.757576 0 15.618586 2.999596 21.617778 8.895354 11.894949 11.894949 11.894949 31.237172 0 43.235555L389.223434 512.103434 698.905859 821.785859c11.894949 11.998384 11.894949 31.340606 0 43.235555-5.895758 5.895758-13.756768 8.895354-21.514344 8.895354z m0 0" p-id="2518" fill="#707070"></path></svg>
<span style="color:red;border-bottom: 2px solid #fb8768;">商品</span>
<span>详情</span>
<span>评论</span>
<span>推荐</span>
<svg t="1667807536833" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3774" width="25" height="32"><path d="M746.662019 512c0 51.835575 42.044582 93.865831 93.865831 93.865831 51.851948 0 93.865831-42.029232 93.865831-93.865831 0-51.836599-42.013883-93.865831-93.865831-93.865831C788.706601 418.135192 746.662019 460.163401 746.662019 512z" p-id="3775" fill="#515151"></path><path d="M89.604272 512c0 51.835575 42.043558 93.865831 93.864808 93.865831 51.822272 0 93.865831-42.029232 93.865831-93.865831 0-51.836599-42.043558-93.865831-93.865831-93.865831C131.648854 418.135192 89.604272 460.163401 89.604272 512z" p-id="3776" fill="#515151"></path><path d="M418.132634 512c0 51.835575 42.013883 93.865831 93.866854 93.865831 51.821249 0 93.864808-42.029232 93.864808-93.865831 0-51.836599-42.043558-93.865831-93.864808-93.865831C460.146517 418.135192 418.132634 460.163401 418.132634 512z" p-id="3777" fill="#515151"></path></svg>
</div>
<div class="picture">
<!-- 用传过来的参数,直接渲染到页面 -->
<img :src="route.query.tp" alt="">
</div>
<div class="text">
<!-- 这部分也是获取路由跳转时传过来的信息,直接渲染到页面上 -->
<p>{{route.query.name}}</p>
<P style="color:#aaa;font-size: 16px;">{{route.query.zz}}</P>
<P style="color:red;font-size: 16px;">¥ <span style="font-size: 20px;">{{route.query.price}}</span> </P>
</div>
<div class="bottom">
<div>
<svg t="1667808724702" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2531" width="32" height="32"><path d="M940.960749 425.143816c0.093121-17.86488-2.838651-35.791158-8.207939-52.113915-0.061398-0.463558-0.153496-0.89437-0.246617-1.26583-0.370437-1.788739-0.86367-3.517103-1.573845-5.183046L858.609159 186.54565c-12.527314-37.334303-48.50369-60.228733-90.589205-60.32083L260.369006 126.22482c-42.641169 0-75.778894 22.678512-87.781252 58.531068L94.833879 368.463909c-0.370437 1.079588-0.771573 2.684132-1.110287 4.319375-5.646604 17.339924-8.485255 35.143405-8.485255 53.008284 0.047072 47.364751 19.658735 91.617627 53.040007 123.1856l0.214894 269.90315c0 43.50484 35.452443 78.895885 79.049381 78.895885l580.622914-0.370437c43.535539-0.093121 78.957283-35.57524 78.957283-79.111802l-0.058328-260.299421C917.076782 526.08888 940.986331 477.395878 940.960749 425.143816zM798.072411 835.695287l-580.529793 0.370437c-9.564843 0-17.339924-7.713682-17.339924-17.217127l-0.185218-232.914724c16.764825 5.293563 35.163871 7.983835 55.045687 7.983835 50.632167-0.153496 97.531314-22.400173 129.496329-60.47535 31.81152 37.766139 78.340229 59.858296 128.880299 60.166311 50.138934-0.401136 96.543823-22.586414 128.200824-60.32083 31.965016 38.075177 78.926584 60.228733 129.805368 60.228733 15.559371-0.077771 30.233582-1.77646 43.916209-5.060249l0.051165 229.867318C815.413358 827.889507 807.606555 835.664587 798.072411 835.695287zM823.065641 520.114818c-13.977339 7.652284-31.410384 11.570523-51.68208 11.69332-37.58092 0-71.828932-19.068288-91.823312-51.434439-1.419326-3.055592-3.795443-8.114818-8.238638-12.989849-5.090948-5.708002-14.346753-12.464893-29.588899-12.464893-12.279674 0-23.418362 5.028527-29.712719 12.743232-4.16588 4.689812-6.448876 9.348925-8.084119 12.742209-19.74674 31.966039-53.718459 51.218522-90.527806 51.496861-37.272905-0.215918-71.335698-19.407002-91.206258-51.619658-1.388627-2.838651-3.703345-7.621585-7.312546-11.663644-14.502295-17.309224-46.960545-16.414855-59.610656-1.326205-4.659113 5.090948-7.096628 10.212596-8.670473 13.700023-19.931958 31.965016-54.211692 51.126424-91.607394 51.249221-19.931958 0-36.994566-3.734044-50.755987-11.07729l-0.030699 0c0 0 0 0-0.030699 0-35.297924-18.789948-57.235562-55.32198-57.266261-95.309716 0-11.81714 1.974981-23.727401 5.92392-35.328623 0.277316-0.832971 0.523933-1.759063 0.740874-2.715855l76.581166-181.054589c1.573845-4.628414 6.325056-18.72855 30.144554-18.72855l507.805468 0c9.780761 0.586354 26.628474 2.313695 32.613792 19.931958l71.706135 178.555675c0.278339 1.295506 0.617054 2.529613 0.926092 3.547803 3.980661 11.631922 5.954619 23.449062 5.954619 35.175127C879.375112 464.761116 857.80791 501.107929 823.065641 520.114818z" p-id="2532" fill="#707070"></path></svg>
<p>店铺</p>
</div>
<div>
<svg t="1667809633396" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4325" width="32" height="32"><path d="M510.7 894.6c-37.2 0-74.3-14.4-102.6-43.2l-0.2-0.2-269.6-277.9c-24.9-25.5-44-55.5-56.8-88.9-12.3-32.3-18.2-66.3-17.4-101.1 0.8-34.9 8.2-68.8 22.1-100.6 14.4-33 35.1-62.3 61.5-87 48.6-45.9 112.5-69.3 180-66.1 66.2 3.2 128.6 31.5 175.7 79.9l9 9.2 8.3-9.3c97.9-100.4 254-106.6 355.3-14.1l0.3 0.3c26.4 24.7 47.2 54 61.6 87.1 13.9 31.8 21.3 65.7 22.1 100.7 0.8 34.8-5.1 68.8-17.4 101.1-12.8 33.4-31.9 63.4-56.8 88.9l-272.4 278c-28.3 28.7-65.5 43.2-102.7 43.2zM458 800.5c29.1 29.6 76.4 29.5 105.5-0.1l272.3-277.9c35.7-36.6 54.8-85.5 53.7-137.5-1.2-52.3-22.7-100.7-60.6-136.2-73.1-66.6-186-61.8-257.5 10.9l-30.5 34.2-0.9 0.8c-15.2 14.8-38.7 14.6-53.5-0.5l-0.1-0.1-33-33.8c-34.7-35.6-80.5-56.4-129-58.8-48.4-2.3-94.2 14.4-128.8 47.1l-0.1 0.1c-38 35.5-59.6 83.9-60.8 136.2-1.2 52 17.9 100.9 53.7 137.7L458 800.5z" p-id="4326" fill="#707070"></path><path d="M339.7 288c-64.1 1.4-98.6 29.4-116.3 52.6-10.2 13.5-16 26.8-19.3 37-4.1 10.5-7.4 22.3-9.8 35.7-3.5 19.6 9.5 38.3 29 41.8 2.2 0.4 4.3 0.6 6.4 0.6 17.1 0 32.2-12.2 35.4-29.6 1.5-8.4 3.6-16 6.2-22.7l0.9-2.1c1.1-4 3.9-11.7 10.2-19.1 8.4-9.9 20.7-16.6 36.6-19.8 6.8-1.4 14.2-2.2 22.3-2.4 17.7-0.4 32.1-13.4 34.8-30.3 0.3-2.1 0.5-4.2 0.4-6.4-0.4-19.9-16.9-35.7-36.8-35.3z" p-id="4327" fill="#707070"></path></svg>
<p>收藏</p>
</div>
<div>
<svg t="1667810312978" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5320" width="32" height="32"><path d="M928.922574 99.438757l-67.214844 0c-15.159258 0-28.122501 10.878768-30.755468 25.803689l-15.35164 86.96977L222.034932 212.212216c-17.253966 0-31.233352 13.979386-31.233352 31.233352s13.979386 31.233352 31.233352 31.233352l582.540589 0-49.773613 281.97407c-8.103562 37.283138-29.688159 81.4388-86.410022 81.4388l-375.389646 0c-32.819476 0-57.504692-5.947456-76.324316-82.851986-0.11154-0.477884-0.243547-0.945535-0.376577-1.413186l-90.304725-306.293965c-4.89038-16.531512-22.23542-25.986861-38.797631-21.12718-16.541745 4.880147-25.997094 22.245653-21.12718 38.797631l90.101087 305.603233c15.830547 64.286142 44.582381 129.752156 136.829342 129.752156l375.389646 0c74.79959 0 129.97626-49.107441 147.605779-131.348514 0.081864-0.376577 0.152473-0.741897 0.213871-1.118474l71.697949-406.186046 41.014112 0c17.253966 0 31.233352-13.979386 31.233352-31.233352S946.17654 99.438757 928.922574 99.438757z" p-id="5321" fill="#707070"></path><path d="M361.610828 333.028862c-17.253966 0-31.233352 13.979386-31.233352 31.233352l0 30.470989c0 17.253966 13.979386 31.233352 31.233352 31.233352 17.253966 0 31.233352-13.979386 31.233352-31.233352l0-30.470989C392.84418 347.008248 378.86377 333.028862 361.610828 333.028862z" p-id="5322" fill="#707070"></path><path d="M605.376691 333.028862c-17.253966 0-31.233352 13.979386-31.233352 31.233352l0 30.470989c0 17.253966 13.979386 31.233352 31.233352 31.233352 17.253966 0 31.233352-13.979386 31.233352-31.233352l0-30.470989C636.610042 347.008248 622.630656 333.028862 605.376691 333.028862z" p-id="5323" fill="#707070"></path><path d="M560.28982 474.086505c-14.539134-9.292644-33.845853-5.083785-43.149752 9.455349-0.121773 0.193405-13.379729 19.449981-33.968649 19.449981-20.008706 0-32.453133-18.127869-33.287127-19.378349-9.17087-14.407128-28.274974-18.809391-42.824341-9.750061-14.650675 9.099239-19.155269 28.355815-10.044774 43.00649 11.214413 18.047028 41.980113 48.588625 86.156242 48.588625 43.952025 0 75.094302-30.308283 86.572728-48.222281C579.048045 502.717589 574.818721 483.389382 560.28982 474.086505z" p-id="5324" fill="#707070"></path><path d="M296.093649 739.519854c-51.668777 0-93.700055 42.031279-93.700055 93.700055 0 51.668777 42.031279 93.700055 93.700055 93.700055 51.668777 0 93.700055-42.031279 93.700055-93.700055C389.793704 781.550109 347.762425 739.519854 296.093649 739.519854zM296.093649 864.453261c-17.223267 0-31.233352-14.010085-31.233352-31.233352 0-17.223267 14.010085-31.233352 31.233352-31.233352s31.233352 14.010085 31.233352 31.233352C327.327 850.443176 313.316915 864.453261 296.093649 864.453261z" p-id="5325" fill="#707070"></path><path d="M670.89387 739.519854c-51.668777 0-93.700055 42.031279-93.700055 93.700055 0 51.668777 42.031279 93.700055 93.700055 93.700055 51.668777 0 93.700055-42.031279 93.700055-93.700055C764.593925 781.550109 722.56367 739.519854 670.89387 739.519854zM670.89387 864.453261c-17.223267 0-31.233352-14.010085-31.233352-31.233352 0-17.223267 14.010085-31.233352 31.233352-31.233352s31.233352 14.010085 31.233352 31.233352C702.127222 850.443176 688.117137 864.453261 670.89387 864.453261z" p-id="5326" fill="#707070"></path></svg>
<p>购物车</p>
</div>
<div style="height: 60px;">
<button class="btn" >立即购买</button>
<button class="btn" style="background-color:#f2564a">加入购物车</button>
</div>
</div>
</template>
<script lang="ts">
// 需要导入这个路由
import { useRoute } from 'vue-router'; export default {
setup() {
// 接收路由跳转时传过来的数据
const route = useRoute()
// 通过route.query,打印传递过来的数据
console.log(route.query); return { route }
}
}
</script>
<style scoped>
.headinfo {
width: 100%;
height: 33px;
/* border: 1px solid magenta; */
display: flex;
justify-content: space-between; } .headinfo span {
line-height: 35px;
} .picture {
height: 200px;
border-bottom: 1px solid #ddd;
margin-top: 20px;
padding-bottom: 10px;
} .picture img {
width: 100%;
height: 100%;
object-fit: contain;
} .text {
border-bottom: 1px solid #ddd;
} .text p {
text-align: left;
margin-left: 20px;
font-size: 18px;
} .bottom {
width: 100%;
height: 60px;
position: fixed;
bottom: 0px;
/* border: 1px solid red; */
display: flex;
justify-content: space-around;
}
.bottom svg{
margin-top: 5px;
}
.bottom p {
margin-top: -3px;
font-size: 14px;
} .btn {
background-color: #febd21;
width: 100px;
height: 100%;
border: none;
color: #fff;
font-size: 16px;
}
</style>

2.4、父组件

<!-- 本组件为父组件,用于展示图书列表的信息 -->
<template lang="">
<div class="head">
<svg style="margin-top: 3px;" t="1667737776727" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2516" width="32" height="32"><path d="M710.4 838.4 358.4 492.8c-12.8-12.8-32-12.8-44.8 0l0 0c-12.8 12.8-12.8 32 0 44.8l352 352c12.8 12.8 32 12.8 44.8 0l0 0C723.2 876.8 723.2 851.2 710.4 838.4z" p-id="2517" fill="#707070"></path><path d="M358.4 531.2l352-352c12.8-12.8 12.8-32 0-44.8l0 0c-12.8-12.8-32-12.8-44.8 0L313.6 486.4c-12.8 12.8-12.8 32 0 44.8l0 0C326.4 544 345.6 544 358.4 531.2z" p-id="2518" fill="#707070"></path></svg>
<div class="textbox">
<svg t="1667752526391" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2608" width="32" height="32"><path d="M663.006587 602.400314l-32.11848 0-12.063745-12.080118c40.177008-44.250786 64.278915-104.586905 64.278915-168.934382 0-144.831451-116.607671-261.4381-261.439123-261.4381-144.787449 0-261.386934 116.606648-261.386934 261.4381 0 144.831451 116.598462 261.387958 261.386934 261.387958 64.390455 0 124.725551-24.09372 168.993733-64.279938l12.011556 12.081141 0 32.162482 201.112213 201.051838 60.32691-60.335096L663.006587 602.400314zM421.664154 602.400314c-100.589875 0-181.021662-80.43281-181.021662-181.014499 0-100.641041 80.43281-181.014499 181.021662-181.014499 100.624668 0 181.005289 80.373458 181.005289 181.014499C602.669443 521.967504 522.288822 602.400314 421.664154 602.400314" p-id="2609" fill="#515151"></path></svg>
<input type="text" />
</div>
<span class="screen">筛选</span>
</div>
<div class="Deputy_head">
<span style="color:red">默认</span>
<span >销量</span>
<span >价格</span>
<span >好评</span>
<span >出版价格</span>
</div>
<div class="hot_search">
<!-- 导入子组件 -->
<Search :data="lists"></Search>
</div>
<!-- 身体 -->
<List></List>
</template>
<script lang="ts">
// 导入子组件
import Search from '../components/2.1 热门搜索组件.vue'
import List from '../components/2.2 图书列表.vue' import { reactive } from 'vue';
export default {
// 注册组件
components:{
Search,
List
},
setup() {
// 定义“ 可能想搜索 ” 部分的数据,传到子组件里面
// (本来图书列表页哪里也需要在父组件定义数据传过去的,但是写的时候,还没有想到,所以就直接在子组件写了,比较推荐用以下这种方式传过去)
const lists = reactive(["vue2","vue3","react","node.js","ES6","MySql"])
return {
lists
}
}
}
</script>
<style>
/* 头部 */
.head{
display: flex;
justify-content: space-between;
/* border: 1px solid red; */
} .textbox{
width: 250px;
height: 40px;
background-color: #eeeeee;
border-radius: 20px;
line-height: 40px;
}
.textbox svg{
vertical-align: middle;
margin-left: 5px;
}
.textbox input{
font-size: 16px;
border: none;
outline: none;
background-color: #eeeeee;
}
.screen{
margin-right: 10px;
line-height: 40px;
}
/* 副头部 */
.Deputy_head{
display: flex;
justify-content: space-between;
margin: 20px 10px;
}
/* 热门搜索 */
.hot_search {
width: 90%;
height: 120px;
margin: auto;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
background-color: #f2f2f2;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
} </style>

2.5、运行结果

结果1:展示图书列表

 结果2:点击随意一本图书都可以,进入该详情页,因为已经实现了动态化

三、使用Vue 组件(component)完成一个精美的日历

3.1、组件A(天数)

<!-- 本组件用于接收父组件遍历过来的天数 -->
<template lang="">
<div>
{{day}}
</div>
</template>
<script lang="ts">
export default {
// 接收参数数据
props:['day']
}
</script>
<style scoped> </style>

3.2、组件B(选择年份)

<!-- 本组件用于:定义年份 -->
<template lang="">
<div class="ya-box">
<!-- 遍历数据 -->
<div class="year" v-for="(item, i) in list" :key="i">
<!-- 挖个坑,定义坑的名称,把年份数据传到父组件里面 -->
<slot name="cc" :data="item"></slot>
</div>
</div>
</template>
<script lang="ts">
import { reactive } from 'vue';
export default {
setup() {
// 定义年份的数据(当时没想到可以用循环遍历,所以先随意的定死了一些数据)
const list = reactive([
{ year: '2015' },
{ year: '2016' },
{ year: '2017' },
{ year: '2018' },
{ year: '2019' },
{ year: '2020' },
{ year: '2021' },
{ year: '2022' },
{ year: '2023' },
{ year: '2024' },
{ year: '2025' }
]);
// 循环添加多个年份,从2026年开始到5000年结束(年份区间可以自定义的)
for (let i = 2026; i<5000;i++) {
// 循环添加到list数组里面,强转i为字符串添加
list.push({ year: String(i) })
} // 暴露出去页面
return { list }
}
}
</script>
<style scoped>
.ya-box{
width: 100%;
height: 340px;
/* border: 1px solid #eeeeee; */
overflow-y: scroll;
overflow-x: hidden;
}
.year {
width: 100%;
height: 30px;
/* border: 1px solid lawngreen; */
line-height: 30px;
margin: 20px 0;
font-weight: bold;
cursor: pointer;
}
</style>

3.3、父组件

<!-- 本组件为日历组件的父组件 -->
<template>
<div class="big-box">
<!-- 左边的日历,选天数 -->
<div id="left-box">
<!-- 头部 -->
<div class="ri-head" style="cursor: pointer;">
<p style="color: #b2ebf2;padding-top: 15px;font-size: 16px;" @click="showYear()">{{ year }}年</p>
<p>{{ month }}月{{ day }}日 星期{{ week }}</p>
</div>
<!-- 天数的容器 -->
<div class="ri-box">
<!-- 左右切换月份 -->
<div class="riBox-head">
<!-- 点击这个为上个月 -->
<svg t="1667840633451" @click="nextorshang(1)" class="icon" viewBox="0 0 1024 1024"
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5160" width="20" height="20">
<path
d="M677.391515 873.916768c-7.86101 0-15.618586-2.999596-21.617778-8.895354L324.473535 533.721212c-11.998384-11.894949-11.998384-31.340606 0-43.235555L655.670303 159.288889c5.999192-5.999192 13.756768-8.895354 21.617778-8.895354 7.757576 0 15.618586 2.999596 21.617778 8.895354 11.894949 11.894949 11.894949 31.237172 0 43.235555L389.223434 512.103434 698.905859 821.785859c11.894949 11.998384 11.894949 31.340606 0 43.235555-5.895758 5.895758-13.756768 8.895354-21.514344 8.895354z m0 0"
fill="#2c2c2c" p-id="5161"></path>
</svg>
<!-- 日期 -->
<span>{{ year }}年{{ month }}月</span>
<!-- 点击这个为下个月 -->
<svg t="1667840592593" @click="nextorshang(0)" class="icon" viewBox="0 0 1024 1024"
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4143" width="20" height="20">
<path
d="M307.6 104.6c-14.2 14.2-14.2 37.2 0 51.4L655 503.4c2.8 2.9 2.8 7.5 0 10.3L307.6 861.2c-14.2 14.2-14.2 37.2 0 51.4 14.2 14.2 37.2 14.2 51.4 0l347.4-347.4c15.6-15.6 23.4-36 23.4-56.5s-7.8-41-23.4-56.5L359 104.6c-14.2-14.2-37.2-14.2-51.4 0z"
p-id="4144" fill="#2c2c2c"></path>
</svg>
</div>
<!-- 星期 -->
<div class="riBox-mian">
<span>一</span>
<span>二</span>
<span>三</span>
<span>四</span>
<span>五</span>
<span>六</span>
<span>日</span>
</div>
<!-- 天数 -->
<div v-for="item in list" :key="item.i2" style="cursor: pointer;">
<!-- 子组件:点击某一天的时候,切换过去,注意添加类,条件为:当前天等于循环过来的某一天 -->
<Ri @click="clcikhmrcs(item.day)" :day="item.day" class="ri-st"
:class="{ day_active: day == item.day }"></Ri>
</div>
</div>
</div> <!-- 右边 -->
<div id="right-box" style="display: none;margin-left: 50px;">
<div class="ri-head" style="cursor: pointer;">
<p style="color: #fff;padding-top: 15px;font-size: 16px;">{{ year }}年</p>
<p style="color: #aae9f1;">{{ month }}月{{ day }}日 星期{{ week }}</p>
</div>
<div class="ri-box">
<!-- 子组件 -->
<Ri_year>
<!-- 包含了一个容器,负责装年份的数据 -->
<!-- 以下用了具名插槽#cc(与子组件的name必须一致)接受数据 -->
<template #cc="{ data }">
<div :class="{ year_active: year == data.year }" @click="clickYear(data.year)">
{{ data.year }}
</div>
</template>
</Ri_year>
</div>
</div> </div>
</template>
<script lang="ts">
// 导入子组件
import Ri from "../components/3.1 日历.vue";
import Ri_year from "../components/3.2 日历选年份.vue";
import { reactive, toRefs } from 'vue'
export default {
// 注册组件
components: {
Ri,
Ri_year
},
setup() {
// arr数组负责把获取到的星期数(阿拉伯数字)转为大写
const arr = ["日", "一", "二", "三", "四", "五", "六"]; // obj数组负责存储所有的天数、年份、月份、某天的数、星期数
const obj: any = reactive({ list: [], year: "", month: 0, day: "", week: "" }) // createyueday方法是根据传入的年份和月份判断该年份是闰年还是平年
function createyueday(n: any, yue: any) {
if ((n % 4 == 0 && !(n % 100 == 0)) || n % 400 == 0) {
days('闰年', yue)
// console.log('闰年')
} else {
days('平年', yue)
// console.log('平年')
}
// 把年份和月份重新赋值给obj对象中的月份和年份,用于在页面上显示
obj.year = n;
obj.month = yue;
} // days方法主要是用于判断闰年和平年中的2月份的天数,需要传入闰年或平年、月份两个参数
function days(run: any, yue: any) {
// 定义一个空数组,用于存储循环过后的所有天数
let arr: any = []
// 然后再加以判断,如果是闰年中的2月份
if (yue == 2 && run == '闰年') {
// 闰年的2月有29天,然后接收xunhuanday方法传过来的数组赋值给arr这个空数组里
obj.list = xunhuanday(29, arr)
} else if (yue == 2 && run == '平年') { // 平年中的2月份
// 有28天
obj.list = xunhuanday(28, arr)
} else if (yue == 4 || yue == 6 || yue == 9 || yue == 11) { // 小月份
// 只有30天
obj.list = xunhuanday(30, arr)
} else { // 大月份
// 有31天
obj.list = xunhuanday(31, arr)
}
} // xunhuanday用于接收具体的一个月结束天数进行循环,把一个月具体的多少天存储到数组里面
function xunhuanday(index: any, arr: any) {
// 例如是闰年的二月份,传进来的就是29,所以从0开始,到29结束
for (let i = 0; i < index; i++) {
// 添加数据到arr数组里面,把天数存储进去
arr.push({ day: i + 1 })
}
// 最后返回数组
return arr
} // nextorshang方法用于切换月份,如果i2传进来的是1,就代表是上个月,传进来的是0,就代表下个月
function nextorshang(i2: any) {
if (i2 == 1) { // 下个月
// 月份-1
obj.month-- // 一直减,如果月份小于1月
if (obj.month < 1) {
// 就进去上一年了,所以年份需要-1
obj.year--
// 重新赋值年份,然后月份默认为上一年的12月
createyueday(obj.year, 12);
} // 如果月份没有小于1月的话,就直接输出该年份和该月份
createyueday(obj.year, obj.month) } else { // 下一个
// 月份+1
obj.month++
// 同理,如果月份大于12月就进入下一年
if (obj.month > 12) {
// 年份+1
obj.year++
// 重新赋值,下一年的话,默认月份为1月
createyueday(obj.year, 1);
} // 不大于12月就输出该年份和该月份
createyueday(obj.year, obj.month)
} // 无论点击上个月还是下个月,切换之后的天数就默认为该月的1号
obj.day = 1;
// 星期数也是需要指定当前的年月日来获取星期数,所以把当前obj的年月日传进去
obj.week = arr[new Date(obj.year + "-" + obj.month + "-" + 1).getDay()];
console.log(obj.week); // 获取到的星期日为0,所以需要重新赋值星期数为7
if (obj.week == 0) {
obj.week = 7;
} } // clcikhmrcs方法用于点击某一天时查看该天的具体日期数,传入具体的哪一天
function clcikhmrcs(day: any) {
// obj数组的天数重新赋值,改变当前天数
obj.day = day;
// 星期数也需要重新赋值,重新传天数进去
obj.week = arr[new Date(obj.year + "-" + obj.month + "-" + day).getDay()];
} // 点击头部中的年份显示选择年份的日历,把显示天数的日历隐藏
function showYear() {
// <HTMLDivElement>:ts的写法,用于操作dom元素时使用,否则会报错
(<HTMLDivElement>document.getElementById("right-box")).style.display = "block";
(<HTMLDivElement>document.getElementById("left-box")).style.display = "none";
} // clickYear方法用于选择年份来查看具体的日期,传入选择的某一年份
function clickYear(year: any) {
console.log(year);
// 把obj数组中的年份重新赋值
obj.year = year;
// 把重新赋值后的年份,和默认1月的数据渲染到页面上
createyueday(obj.year, 1);
// 天数也是默认1号
obj.day = 1;
// 重新传入年月日查询星期数
obj.week = arr[new Date(obj.year + "-" + obj.month + "-" + 1).getDay()];
// 选择完年份后,隐藏选择年份的日历,显示天数的日历出现
(<HTMLDivElement>document.getElementById("right-box")).style.display = "none";
(<HTMLDivElement>document.getElementById("left-box")).style.display = "block";
} // 初始化日历,页面加载时,就显示以下的数据
// 显示当前的年份、月份、天数、星期数
createyueday(new Date().getFullYear(), new Date().getMonth() + 1)
obj.day = new Date().getDate()
obj.week = arr[new Date().getDay()]; // 暴露出去
return {
nextorshang,
...toRefs(obj),
clcikhmrcs,
clickYear,
showYear }
}
}
</script>
<style >
.big-box {
width: 750px;
padding: 20px;
/* border: 1px solid navy; */
margin: auto;
display: flex;
justify-content: space-evenly;
} .ri-head {
width: 360px;
height: 80px;
margin: auto;
background-color: #00bcd4;
color: #fff; } .ri-head p {
text-align: left;
margin-left: 20px;
font-size: 25px;
margin-top: -10px;
} .ri-box {
display: flex;
flex-wrap: wrap;
width: 358px;
border: 1px solid #eee;
margin: auto;
padding-bottom: 20px;
} .ri-st {
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
margin: 10px; } .riBox-head,
.riBox-mian {
width: 100%;
display: flex;
justify-content: space-between;
margin: auto;
margin-top: 20px;
padding: 0px 20px;
/* border: 1px solid red; */
} .riBox-mian {
font-size: 14px;
color: #909090;
margin-left: -2px;
justify-content: space-around;
padding: 0px;
margin-bottom: 10px;
} .day_active {
background-color: #00bcd4;
color: #fff;
border-radius: 15px;
} .year_active {
color: #fff;
background-color: #00bcd4;
}
</style>

3.4、运行结果

结果1:展示日期

 结果2:选择年份,展示该年份的日期

四、使用动态插槽完成一个选项卡,点击卡片名称时动态切换。

4.1、子组件A(定义选项卡的数据)

<!-- 本组件用于:向父组件传值 -->
<template lang="">
<!-- 遍历三个数组对象 -->
<div v-for="(item,i) in list">
<!-- slot标签相当于在子组件里面挖一个坑,到父组件里填上 -->
<!-- 在这里需要定义一个名称,然后把遍历出来的数据传到父组件里面 -->
<slot name="s1" :data="item"></slot>
</div>
<div v-for="(item,i) in list2">
<slot name="s2" :data="item"></slot>
</div>
<div v-for="(item,i) in list3">
<slot name="s3" :data="item"></slot>
</div>
</template>
<script lang="ts">
import { reactive } from 'vue'
export default {
setup() {
// 定义选项卡的数据
const list = reactive([
{ name: 'vue1' },
{ name: 'vue1' },
{ name: 'vue1' }
])
const list2 = reactive([
{ name: 'vue2' },
{ name: 'vue2' },
{ name: 'vue2' }
])
const list3 = reactive([
{ name: 'vue3' },
{ name: 'vue3' },
{ name: 'vue3' }
])
// 暴露出去
return {
list,
list2,
list3
}
}
}
</script>
<style scoped> </style>

4.2、父组件

<template lang="">
<div class="big">
<!-- 选项卡按钮 -->
<!-- 点击按钮时,修改变量s的值,目的是:让s的值变为子组件那边所需要的值,看用户需要哪个数据,就点击哪个按钮,达到选项卡的效果 -->
<button style="margin-left: 0px;" @click="s = 's1'" :class="{active: s === 's1'}">vue1</button>
<button @click="s = 's2'" :class="{active: s === 's2'}">vue2</button>
<button @click="s = 's3'" :class="{active: s === 's3'}">vue3</button>
<div class="big_box">
<!-- 导入子组件 -->
<Ez >
<!-- # 相当于 v-slot -->
<!-- 这个为作用域插槽 -->
<!-- [s]定义的目的就是为了让具名发生变化,如果为s1,就传子组件那边对应的name -->
<!-- 然后在这里接受子组件传过来的数据 -->
<template #[s]="{data}">
<div class="item-box">
<!-- 输出数据到页面上 -->
{{data.name}}
</div>
</template>
</Ez>
</div>
</div>
</template>
<script lang="ts">
import Ez from "../components/4.1 动态插槽之儿子组件.vue";
import { ref } from 'vue'
export default {
components: {
Ez
},
setup() {
let s = ref('s1') return {
s
}
}
}
</script>
<style scoped>
.big{
width: 350px;
height: 390px;
background-color: #636d76;
margin: auto;
}
button{
width: 100px;
height: 40px;
background-color: #474b54;
color: #ece6b2;
border: none;
margin-left: 10px;
margin-top: 10px;
}
.big_box{
width: 91.3%;
height: 330px;
background-color: #fff;
margin: auto;
} .item-box {
width: 80%;
padding: 10px;
margin: auto;
border-bottom: 1px solid #d7dee1;
}
.active{
background-color: #fff;
color: #333;
}
</style>

4.3、运行结果:

五、使用动态组件完成一个选项卡,定义3个不同的组件,点击卡片名称时动态切换。

5.1、子组件A(第一页)

<template>
<h3>测试KeepAlive组件强制被切换掉的组件仍然保持“存活”的状态</h3>
<h1>{{s}}</h1>
<h2>{{s}}</h2>
<h3>{{s}}</h3>
<hr>
<button @click="s++">点我+1哦</button>
</template>
<script lang="ts">
import {ref} from 'vue'
export default {
// 组件里的name属性
name: 'a',
setup () {
const s = ref(1)
return {
s
}
}
}
</script>
<style scoped>
h1,h2,h3{
background-color: #e2e2e2;
color: #777;
width: 90%;
margin: auto;
margin-top: 20px;
} </style>

5.2、子组件B(第二页)

<template>
<h3>测试KeepAlive组件强制被切换掉的组件仍然保持“存活”的状态</h3>
<h1>{{s}}</h1>
<h2>{{s}}</h2>
<h3>{{s}}</h3>
<hr>
<button @click="s++">点我+1哦</button>
</template>
<script lang="ts">
import {ref} from 'vue'
export default {
// 组件里的name属性
name: 'b',
setup () {
const s = ref(10)
return {
s
}
}
}
</script>
<style scoped>
h1,h2,h3{
background-color: #e2e2e2;
color: #777;
width: 90%;
margin: auto;
margin-top: 20px;
} </style>

5.3、子组件C(第三页)

<template>
<h3>测试KeepAlive组件强制被切换掉的组件仍然保持“存活”的状态</h3>
<h1>{{s}}</h1>
<h2>{{s}}</h2>
<h3>{{s}}</h3>
<hr>
<button @click="s++">点我+1哦</button>
</template>
<script lang="ts">
import {ref} from 'vue'
export default {
// 组件里的name属性
name: 'c',
setup () {
const s = ref(100);
return {
s
}
}
}
</script>
<style scoped>
h1,h2,h3{
background-color: #e2e2e2;
color: #777;
width: 90%;
margin: auto;
margin-top: 20px;
} </style>

5.4、父组件

<template >
<div class="box">
<div class="box-head">
<div class="bh-min" style="border-radius: 0px 0px 0px 20px;" @click="componentId='A'" :class="{active: componentId === 'A'}">
<svg t="1667842015073" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6350" width="20" height="20"><path d="M527.247 204.247c113.891 0 227.885 0.717 341.777-0.307 60.373-0.511 88.923 25.48 88.31 87.491-1.434 139.474 0.408 278.947-0.82 418.42-0.716 78.18-31.926 107.241-111.333 107.343-218.573 0.307-437.044 0.307-655.618-0.204-77.667-0.205-124.84-46.764-125.25-123.613-0.716-125.557-0.511-251.114-0.204-376.568 0.204-81.454 30.289-111.845 114.403-112.664 116.245-1.126 232.49-0.307 348.735-0.307v0.41z m-9.21 558.611c109.287 0 218.676-1.33 327.963 0.614 41.443 0.716 58.225-12.382 57.304-55.667-2.252-104.58-0.307-209.364-1.33-314.045-0.103-17.09 9.414-40.625-12.485-49.834-19.954-8.391-32.642 10.13-47.07 21.693-96.906 77.36-195.653 152.572-291.023 231.774-31.517 26.196-51.573 25.275-82.272-0.102-97.11-80.533-197.084-157.484-295.012-237.095-13.098-10.642-25.378-23.74-41.648-19.136-21.08 6.038-13.2 27.22-13.303 42.057-0.716 99.975 1.33 200.052-0.716 300.027-1.126 56.485 23.536 80.328 78.69 79.816 106.831-0.818 213.867-0.204 320.902-0.102zM139.525 262.677c19.851 18.317 25.991 24.763 32.95 30.29 60.885 48.298 121.259 97.211 182.86 144.384 159.837 122.488 160.246 122.488 316.707-2.148 66.41-52.904 131.492-107.343 211.205-172.628-255.411 0.102-490.562 0.102-743.722 0.102z" fill="#7061a7" p-id="6351"></path></svg>
<span>选项卡 1</span>
</div>
<div class="bh-min" @click="componentId='B'" :class="{active: componentId === 'B'}">
<svg t="1667842222005" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7505" width="20" height="20"><path d="M1016.832 606.208q2.048 12.288-1.024 29.696t-10.24 35.328-17.408 32.256-22.528 20.48-21.504 6.144-20.48-4.096q-10.24-3.072-25.6-5.632t-31.232-1.024-31.744 6.656-27.136 17.408q-24.576 25.6-28.672 58.368t9.216 62.464q10.24 20.48-3.072 40.96-6.144 8.192-19.456 16.896t-29.184 15.872-33.28 11.264-30.72 4.096q-9.216 0-17.408-7.168t-11.264-15.36l-1.024 0q-11.264-31.744-38.4-54.784t-62.976-23.04q-34.816 0-62.976 23.04t-39.424 53.76q-5.12 12.288-15.36 17.92t-22.528 5.632q-14.336 0-32.256-5.12t-35.84-12.8-32.256-17.92-21.504-20.48q-5.12-7.168-5.632-16.896t7.68-27.136q11.264-23.552 8.704-53.76t-26.112-55.808q-14.336-15.36-34.816-19.968t-38.912-3.584q-21.504 1.024-44.032 8.192-14.336 4.096-28.672-2.048-11.264-4.096-20.992-18.944t-17.408-32.768-11.776-36.864-2.048-31.232q3.072-22.528 20.48-28.672 30.72-12.288 55.296-40.448t24.576-62.976q0-35.84-24.576-62.464t-55.296-38.912q-9.216-3.072-15.36-14.848t-6.144-24.064q0-13.312 4.096-29.696t10.752-31.744 15.36-28.16 18.944-18.944q8.192-5.12 15.872-4.096t16.896 4.096q30.72 12.288 64 7.68t58.88-29.184q12.288-12.288 17.92-30.208t7.168-35.328 0-31.744-2.56-20.48q-2.048-6.144-3.584-14.336t1.536-14.336q6.144-14.336 22.016-25.088t34.304-17.92 35.84-10.752 27.648-3.584q13.312 0 20.992 8.704t10.752 17.92q11.264 27.648 36.864 48.64t60.416 20.992q35.84 0 63.488-19.968t38.912-50.688q4.096-8.192 12.8-16.896t17.92-8.704q14.336 0 31.232 4.096t33.28 11.264 30.208 18.432 22.016 24.576q5.12 8.192 3.072 17.92t-4.096 13.824q-13.312 29.696-8.192 62.464t29.696 57.344 60.416 27.136 66.56-11.776q8.192-5.12 19.968-4.096t19.968 9.216q15.36 14.336 27.136 43.52t15.872 58.88q2.048 17.408-5.632 27.136t-15.872 12.8q-31.744 11.264-54.272 39.424t-22.528 64q0 34.816 18.944 60.928t49.664 37.376q7.168 4.096 12.288 8.192 11.264 9.216 15.36 23.552zM540.672 698.368q46.08 0 87.04-17.408t71.168-48.128 47.616-71.168 17.408-86.528-17.408-86.528-47.616-70.656-71.168-47.616-87.04-17.408-86.528 17.408-70.656 47.616-47.616 70.656-17.408 86.528 17.408 86.528 47.616 71.168 70.656 48.128 86.528 17.408z" p-id="7506" fill="#7061a7"></path></svg>
<span>选项卡 2</span>
</div>
<div class="bh-min" @click="componentId='C'" :class="{active: componentId === 'C'}">
<svg t="1667842294039" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8570" width="20" height="20"><path d="M639.892491 415.930119 383.935495 415.930119c-17.717453 0-31.994625-14.277171-31.994625-31.994625s14.277171-31.994625 31.994625-31.994625L639.892491 351.94087c17.717453 0 31.994625 14.277171 31.994625 31.994625S657.609945 415.930119 639.892491 415.930119z" p-id="8571" fill="#7061a7"></path><path d="M579.17151 543.908618 383.935495 543.908618c-17.717453 0-31.994625-14.277171-31.994625-31.994625S366.390055 479.919368 383.935495 479.919368l195.236015 0c17.717453 0 31.994625 14.277171 31.994625 31.994625S596.888964 543.908618 579.17151 543.908618z" p-id="8572" fill="#7061a7"></path><path d="M962.246934 447.924744c0-211.74937-200.912481-383.935495-447.924744-383.935495S66.225433 236.175374 66.225433 447.924744c0 116.453553 62.957164 226.026541 172.874181 300.680665 14.621199 9.976818 34.574836 6.192508 44.379641-8.428691 9.976818-14.621199 6.192508-34.574836-8.428691-44.379641-92.027549-62.441122-144.835881-152.74853-144.835881-247.700319 0-176.486477 172.186125-319.946246 383.935495-319.946246s383.935495 143.631782 383.935495 319.946246-172.186125 319.946246-383.935495 319.946246c-2.064169 0-3.612296 0.688056-5.504452 1.204099-15.137242-2.752226-30.446498 5.160423-35.778935 20.125651-6.192508 17.373425-46.44381 46.615824-94.091718 73.794053 17.373425-58.140769 9.116748-70.697799 3.440282-78.954477-6.70855-9.976818-17.889467-15.997312-29.930455-15.997312-17.717453 0-31.994625 14.277171-31.994625 31.994625 0 5.84848 1.548127 11.180917 4.300353 15.997312-3.268268 18.233496-17.201411 60.892995-33.026709 99.768184-4.988409 12.040988-2.064169 25.974131 7.396607 35.090879 6.020494 5.84848 14.105157 8.944734 22.18982 8.944734 4.300353 0 8.77272-0.860071 13.073072-2.752226 36.466991-16.341341 147.588107-69.149672 187.667395-125.570301C765.290778 828.075928 962.246934 657.609945 962.246934 447.924744z" p-id="8573" fill="#7061a7"></path></svg>
<span>选项卡 3</span>
</div>
</div>
<div class="box-mian">
<!-- KeepAlive: (接地气说法)阻止组件卸载,从a页面 切换到b页面 但是a页面输入或保存的的数据不会被销毁-->
<!-- 可以让强制被切换掉的组件仍然保持“存活”的状态 -->
<!-- 包含(include)/排除(exclude) -->
<!-- 根据组件的 name 选项进行匹配,所以组件如果想要条件性地被 KeepAlive 缓存,就必须显式声明一个 name 选项。 -->
<!-- :is -->
<!-- 被传给 :is 的值可以是以下几种:
被注册的组件名
导入的组件对象 -->
<KeepAlive include="a,b">
<component :is="components[componentId]"></component>
</KeepAlive>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import A from '../components/5.1 动态组件之A组件.vue';
import B from '../components/5.2 动态组件之B组件.vue';
import C from '../components/5.3 动态组件之C组件.vue'; let components:any = {
A,B,C
} const componentId = ref("A"); </script>
<style scoped>
.box{
width: 45%;
height: 250px;
border-bottom: 3px solid #73679e;
margin: auto;
}
.box-head{
width: 100%;
height: 50px;
display: flex;
color: #333;
background-color: #eaeaea;
border-radius: 0px 20px 0px 20px;
} .bh-min{
width: 20%;
height: 100%;
/* border: 1px solid rebeccapurple; */ }
.bh-min svg{
vertical-align: middle;
}
.bh-min span{
vertical-align: middle;
margin-left: 10px;
line-height: 50px;
} .active{
fill:#fff;
color: #fff;
background-color: #795da6;
}
.active svg path{
fill: #fff;
} .box-mian{
width: 100%;
height: 200px;
/* border: 1px solid lawngreen; */
} </style>

5.5、运行结果

Vue3 —— 组件练习题(附源码)的更多相关文章

  1. 基于vue与vux做的可滑动tab组件(附源码)

    背景 前不久,刚完成了一个商品列表+购物车功能的页面,因为一级商品分类在顶部tab中显示,可滑动,间距可定制,如下图所示: 定制的tab需求如下: 1. 每个tab-item的间距是相同的,可定制 2 ...

  2. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

    前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...

  3. C#轻量级通通讯组件StriveEngine —— C/S通信开源demo(2) —— 使用二进制协议 (附源码)

    前段时间,有几个研究ESFramework通信框架的朋友对我说,ESFramework有点庞大,对于他们目前的项目来说有点“杀鸡用牛刀”的意思,因为他们的项目不需要文件传送.不需要P2P.不存在好友关 ...

  4. 日志组件Log2Net的介绍和使用(附源码开源地址)

    Log2Net是一个用于收集日志到数据库或文件的组件,支持.NET和.NetCore平台. 此组件自动收集系统的运行日志(服务器运行情况.在线人数等).异常日志.程序员还可以添加自定义日志. 该组件支 ...

  5. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  6. 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)

    在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...

  7. ASP.NET程序读取二代身份证(附源码)

    原文:ASP.NET程序读取二代身份证(附源码) 一般来说winform应用程序解决这个问题起来时很容易的,web应用程序就麻烦一点了. 这里我说说我的解决思路: 一.你必要有联机型居民身份证阅读器一 ...

  8. 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生

    [转].NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

  9. 微服务8:通信之RPC实践篇(附源码)

    ★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...

  10. Vue过渡和动画效果展示(案例、GIF动图演示、附源码)

    前言 本篇随笔主要写了Vue过渡和动画基础.多个元素过渡和多个组件过渡,以及列表过渡的动画效果展示.详细案例分析.GIF动图演示.附源码地址获取. 作为自己对Vue过渡和动画效果知识的总结与笔记. 因 ...

随机推荐

  1. KingbaseES 归档日志清理

    WAL是Write Ahead Log的简写,和Oracle的redo日志类似,在R3版本存放在data/sys_log中,R6版本以后在data/sys_wal目录,在数据库访问过程中,任何对数据块 ...

  2. day37-IO流04

    JavaIO流04 4.常用的类03 4.4节点流和处理流02 4.4.5对象处理流-ObjectInputStream和ObjectOutputStream 1.序列化和反序列化 例子1: 看一个需 ...

  3. [Python]-openpyxl模块Excel数据处理-读取公式的结果

    日常需要Python来处理各种数据,处理Excel数据常用的库一般有openpyxl.xlrd(读取).xlwt(写入). 经过对比发现openpyxl模块比较好用. openpyxl模块 这篇笔记比 ...

  4. win10系统应用商店打开后无法联网 代码: 0x80131500 的解决办法

    官方提供的建议网址: https://answers.microsoft.com/zh-hans/windows/forum/all/代码/cbbe7aaf-8f66-4779-89c8-3c74f5 ...

  5. 堆Pwn:House Of Storm利用手法

    0x00:介绍 利用手法的背景: house of storm是一种结合了unsorted bin attack和Largebin attack的攻击技术,其基本原理和Largebin attack类 ...

  6. C语言在Linux下创建一个僵尸进程

    第三章编程题3.12 1.僵尸进程是什么 每一个进程都有一个PCB(进程控制块),其中包含进程执行的状态等一系列信息. 当父进程fork()出一个子进程,子进程执行结束后操作系统会回收子进程使用的内存 ...

  7. ECMAScript6 ES6 ES2015新语法总结

    1.let定义变量:不能重复定义.作用域 2.const:定义常量 3.解构赋值:let [a,b,c] = [1,2,3];// a=1 b=2 c=3 4.箭头函数: function fn(a, ...

  8. hmtl5 web SQL 和indexDB

    前端缓存有cookie,localStorage,sessionStorage,webSQL,indexDB: cookie:有缺点 localStorage:功能单一 sessionStorage: ...

  9. 【强烈推荐】用glob库的一行命令显著加速批量读取处理数据

    在我们气象领域,对数据进行批处理随处可见,尤其是在处理模式数据的时候.为了能让这个过程加速,很多大佬们提出了不同的方法,比如使用numba库进行计算.使用dask库进行并行等等,都是非常好的加速手段. ...

  10. day48-JDBC和连接池04

    JDBC和连接池04 10.数据库连接池 10.1传统连接弊端分析 传统获取Connection问题分析 传统的 JDBC 数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都 ...