当前位置 博文首页 > CSDN凉宸:uni-app实战项目,跟着做完你就可以独立作战了(二)

    CSDN凉宸:uni-app实战项目,跟着做完你就可以独立作战了(二)

    作者:[db:作者] 时间:2021-07-08 10:13

    实现内容切换

    实现内容左右滑动

    我们新建list组件

    里面使用swiper基础组件
    我们将首页这一部分剪切过来
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    这样就可以正常内容左右滑动切换了
    但是有一个问题,不能上下滚动
    在这里插入图片描述
    我们将list组件放到容器中,然后设置一下样式
    但我们还需要在组件中设置样式来撑起高度
    在这里插入图片描述
    这样就可以上下滚动了
    暂时代码

    <template>
    	<swiper class="home-swiper">
    		<swiper-item class="swiper-item">
    			<list-scrool class="list-scrool">
    				<list-card mode="base" ></list-card>
    				<list-card mode="image" ></list-card>
    				<list-card mode="column" ></list-card>
    				<list-card mode="base" ></list-card>
    				<list-card mode="image" ></list-card>
    				<list-card mode="column" ></list-card>
    			</list-scrool>
    		</swiper-item>
    		<swiper-item class="swiper-item">
    			<list-scrool class="list-scrool">
    				<list-card mode="base" ></list-card>
    				<list-card mode="image" ></list-card>
    				<list-card mode="column" ></list-card>
    				<list-card mode="base" ></list-card>
    				<list-card mode="image" ></list-card>
    				<list-card mode="column" ></list-card>
    			</list-scrool>
    		</swiper-item>
    	</swiper>
    </template>
    
    <script>
    	export default {
    		data() {
    			return {
    
    			};
    		}
    	}
    </script>
    
    <style lang="scss">
    	.home-swiper {
    		height: 100%;
    		.swiper-item{
    			height: 100%;
    			overflow: hidden;
    			.list-scrool{
    				height: 100%;
    			}
    		}
    	}
    </style>
    
    

    改造:
    我们在list组件下新建list-item.vue文件
    在这里插入图片描述
    我们要设置高度哦

    	.list-scrool{
    		height: 100%;
    	}
    

    list.vue组件中
    在这里插入图片描述
    我们给子组件传值
    在这里插入图片描述
    子组件接收并循环
    在这里插入图片描述
    这样我们的内容区域和选项卡区域可以对的上了 都是6块

    实现内容与选项卡关联

    实现左右滑动内容,选项卡对应高亮

    我们在list组件中写一个change事件来监听变化
    再用$emit传给首页index.vue
    在这里插入图片描述
    在首页中
    我们接收事件 并且定义一个变量 传给选项卡
    在这里插入图片描述
    在tab选项卡中
    我们接收值,并且在watch事件中监听变化赋值给activeIndex即可
    在这里插入图片描述

    实现选项卡与内容关联

    实现点击选项卡,内容区域变化
    之前我们在tab选项卡组件中定义了点击事件及传值给父组件
    在这里插入图片描述
    在首页父组件中

    点击选项卡传值过来后将值赋给变量activeIndex,然后在传给内容组件
    在这里插入图片描述
    在list组件中我们接收传递过来的activeIndex值
    swiper有一个属性current可以指定调整到索引为多少的内容区域,所以我们将activeIndex赋值过去
    在这里插入图片描述

    数据初始化

    我们将静态内容从数据库获取放到页面中

    新建云函数

    在这里插入图片描述

    get_list中编写
    获取到内容之后,我们要过滤掉content字段(使用field),然后返回给客户端
    在这里插入图片描述
    我们在如下地方写
    在这里插入图片描述
    然后我们在list组件中写调用函数,在created中调用
    在这里插入图片描述
    获取到值以后,我们赋值给list 然后在传递给子组件list-item
    在这里插入图片描述
    list-item在接收到值以后循环一下,然后将mode类赋值给mode属性
    然后在传递item过去,将内容替换
    在这里插入图片描述

    我们在list-card组件中接收传递过来的值item
    在这里插入图片描述
    我们在上面做一个更改
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    完整代码在下方

    <template>
    	<view class="list">
    		<!-- 基础卡片 -->
    		<view v-if="mode==='base'" class="listcard">
    			<view class="listcard-image">
    				<image :src="item.cover[0]" mode="aspectFill"></image>
    			</view>
    			<view class="listcard-content">
    				<view class="listcard-content_title">
    					<text>{{item.title}}</text>
    				</view>
    				<view class="listcard-content_des">
    					<view class="listcard-content_des-label">
    						<view class="listcard-content_des-label-item">
    							{{item.classify}}
    						</view>
    					</view>
    					<view class="listcard-content_des-browe">
    						{{item.browse_count}}浏览
    					</view>
    				</view>
    			</view>
    		</view>
    		
    		<!-- 多图模式 -->
    		<view v-if="mode==='image'" class="listcard mode-column">
    			<view class="listcard-content">
    				<view class="listcard-content_title">
    					<text>{{item.title}}</text>
    				</view>
    				<view class="listcard-image">
    					<view v-if="index<3" v-for="(item,index) in item.cover" :key="index" class="listcard-image_item">
    						<image :src="item" mode="aspectFill"></image>
    					</view>
    				</view>
    				<view class="listcard-content_des">
    					<view class="listcard-content_des-label">
    						<view class="listcard-content_des-label-item">
    							{{item.classify}}
    						</view>
    					</view>
    					<view class="listcard-content_des-browe">
    						{{item.browse_count}}浏览
    					</view>
    				</view>
    			</view>
    		</view>
    		<!-- 大图模式 -->
    		<view v-if="mode==='column'" class="listcard mode-image">
    			<view class="listcard-content">
    				<view class="listcard-image">
    					<image :src="item.cover[0]" mode="aspectFill"></image>
    				</view>
    				<view class="listcard-content_title">
    					<text>{{item.title}}</text>
    				</view>
    				<view class="listcard-content_des">
    					<view class="listcard-content_des-label">
    						<view class="listcard-content_des-label-item">
    							{{item.classify}}
    						</view>
    					</view>
    					<view class="listcard-content_des-browe">
    						{{item.browse_count}}浏览
    					</view>
    				</view>
    			</view>
    		</view>
    	</view>
    </template>
    
    <script>
    	export default {
    		props:{
    			mode:{
    				type:String,
    				default:'base'
    			},
    			item:{
    				type:Object,
    				default(){
    					return {}
    				}
    			}
    		},
    		data() {
    			return {
    
    			};
    		}
    	}
    </script>
    
    <style lang="scss">
    	.list{
    		.listcard {
    			display: flex;
    			padding: 10px;
    			margin: 10px;
    			border-radius: 5px;
    			box-shadow: 0 0 5px 1px rgba($color: #000000, $alpha: 0.1);
    			box-sizing: border-box;
    		
    			.listcard-image {
    				flex-shrink: 0;
    				width: 60px;
    				height: 60px;
    				border-radius: 5px;
    				overflow: hidden;
    		
    				image {
    					width: 100%;
    					height: 100%;
    				}
    			}
    		
    			.listcard-content {
    				display: flex;
    				flex-direction: column;
    				justify-content: space-between;
    				padding-left: 10px;
    				width: 100%;
    		
    				.listcard-content_title {
    					position: relative;
    					padding-right: 30px;
    					font-size: 14px;
    					color: #333;
    					font-weight: 400;
    					line-height: 1.2;
    		
    					text {
    						overflow: hidden;
    						text-overflow: ellipsis;
    						display: -webkit-box;
    						-webkit-line-clamp: 2;
    						-webkit-box-orient: vertical;
    					}
    		
    				}
    		
    				.listcard-content_des {
    					display: flex;
    					justify-content: space-between;
    					font-size: 12px;
    		
    					.listcard-content_des-label {
    						display: flex;
    		
    						.listcard-content_des-label-item {
    							padding: 0 5px;
    							margin-right: 5px;
    							border-radius: 15px;
    							color: $mk-base-color;
    							border: 1px $mk-base-color solid;
    						}
    					}
    		
    					.listcard-content_des-browe {
    						color: #999;
    						line-height: 1.5;
    					}
    				}
    			}
    		
    			&.mode-column {
    				.listcard-content {
    					width: 100%;
    					padding-left: 0;
    				}
    		
    				.listcard-image {
    					display: flex;
    					margin-top: 10px;
    					width: 100%;
    					height: 70px;
    		
    					.listcard-image_item {
    						margin-left: 10px;
    						width: 100%;
    						border-radius: 5px;
    						overflow: hidden;
    		
    						&:first-child {
    							margin-left: 0;
    						}
    		
    						image {
    							width: 100%;
    							height: 100%;
    						}
    					}
    				}
    		
    				.listcard-content_des {
    					margin-top: 10px;
    				}
    			}
    		
    			&.mode-image {
    				flex-direction: column;
    				.listcard-image {
    					width: 100%;
    					height: 100px;
    				}
    		
    				.listcard-content {
    					padding-left: 0;
    					margin-top: 10px;
    		
    					.listcard-content_des {
    						display: flex;
    						align-items: center;
    						margin-top: 10px;
    					}
    				}
    			}
    		}
    	}
    </style>
    
    

    在这里插入图片描述
    页面暂时是这样了 有的图片可能因为地址过期获取没有权限展示不出,没有问题的

    页面内容展示与选项卡相同

    我们在首先执行的时候传递第一个需要展示的内容
    在改变选项卡高亮和内容区域时再次调用将获取到的tab数组中的name值传递过去

    在这里插入图片描述
    在这里插入图片描述
    效果
    在这里插入图片描述
    但是此时有一个弊端,他不是及时更新,而是启用之前的缓存
    我们要做如下更改
    在这里插入图片描述
    list传值也做下更改,将listCatchData[index]传过去
    在这里插入图片描述
    这样就不会出现如上问题了
    在这里插入图片描述

    list.vue完整代码

    <template>
    	<swiper class="home-swiper" :current="activeIndex" @change="change">
    		<swiper-item v-for="(item,index) in tab" class="swiper-item" :key="index">
    			<list-item :list="listCatchData[index]"></list-item>
    		</swiper-item>
    	</swiper>
    </template>
    
    <script>
    	import listItem from './list-item.vue'
    	export default {
    		components:{
    			listItem
    		},
    		props:{
    			tab:{
    				type:Array,
    				default(){
    					return []
    				}
    			},
    			activeIndex:{
    				type:Number,
    				default:0
    			}
    		},
    		data() {
    			return {
    				list:[],
    				listCatchData:{}
    			};
    		},
    		created() {
    			// this.get_list(0)
    		},
    		watch:{
    			tab(newVal){
    				if(newVal.length===0) return
    				this.get_list(this.activeIndex)
    			}
    		},
    		methods:{
    			change(e){
    				const {current}=e.detail
    				this.$emit('change',current)
    				this.get_list(current)
    			},
    			get_list(current){
    				this.$api.get_list({
    					name:this.tab[current].name
    				})
    				.then(res=>{
    					// this.list=res.data.data
    					// this.listCatchData[current]=res.data.data
    					this.$set(this.listCatchData,current,res.data.data)
    				})
    			}
    		}
    	}
    </script>
    
    <style lang="scss">
    	.home-swiper {
    		height: 100%;
    		.swiper-item{
    			height: 100%;
    			overflow: hidden;
    			.list-scrool{
    				height: 100%;
    			}
    		}
    	}
    </style>
    
    

    我们将tab选项卡添加一个数据’全部’
    pages/index.vue/index.vue
    在这里插入图片描述
    云函数get_list
    在这里插入图片描述
    在这里插入图片描述

    我们在list组件的change事件中添加如下代码
    否则会多次请求数据库,会造成服务器压力
    在这里插入图片描述

    引入加载插件

    插件市场导入
    在这里插入图片描述
    list-item中使用
    在这里插入图片描述

    这里会有一个问题,在最下面会一直存在加载中,所以我们要做判断
    我们在获取列表数据里面加入俩个条件
    在这里插入图片描述
    在get_list中加入下面代码
    在这里插入图片描述

    这样就可以获取每页多少条,我们后面去做判断,划到最后是显示正在加载还是没有更多数据提升
    我们用的list-scrool组件
    在这里插入图片描述
    在list-scrool组件中添加上划到底事件
    在这里插入图片描述
    我们从组件一级一级传出事件到list组件中
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    我们在这几处加入代码,为了下滑到底加载更多数据
    在这里插入图片描述
    这时有一个问题,如果我们在全部页下滑加载完全部数据,划到单独分栏不会加载数据的

    我们将page变量删除改为load:{} 即可完美解决
    在这里插入图片描述
    加入如下代码在list组件
    在这里插入图片描述
    然后在list-item组件中接收即可
    在这里插入图片描述
    再往下划会报错
    在这里插入图片描述
    加入如下代码,就完美解决了
    在这里插入图片描述
    在这里插入图片描述
    最后这样如果数据库没有新数据就不会再次发起请求了
    别的页面也能正常运行了
    在这里插入图片描述
    我们做一个小小修改,加入一行代码在index.vue
    在这里插入图片描述
    加入一行代码在list-item.vue中
    在这里插入图片描述
    这样我们就完美解决了

    收藏功能

    新建likes组件
    在这里插入图片描述
    然后再list-card中每个模式标题下面引入
    在这里插入图片描述
    再likes中做点击事件
    在这里插入图片描述
    编写新的云函数
    在这里插入图片描述
    api中加入
    在这里插入图片描述
    likes组件中加入传值
    在这里插入图片描述
    然后我们在likes.vue组件中进行接收

    在点击收藏时我们直接调用我们的函数,我们也写了一个变量like,为了让收藏按钮是显示收藏还是为收藏
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    但是我们收藏状态在刷新后是不存储的
    我们要做一下修改
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    改变文章收藏状态
    在这里插入图片描述
    加个收藏提示,是收藏还是取消
    在这里插入图片描述
    到此我们的收藏就完成了


    结束语

    到现在我们首页就完成了
    敬请期待下一篇: 搜索功能的实现

    cs