uni-app实战项目,跟着做完你就可以独立作战了
Posted David凉宸
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uni-app实战项目,跟着做完你就可以独立作战了相关的知识,希望对你有一定的参考价值。
实现内容切换
实现内容左右滑动
我们新建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,为了让收藏按钮是显示收藏还是为收藏
但是我们收藏状态在刷新后是不存储的
我们要做一下修改
改变文章收藏状态
加个收藏提示,是收藏还是取消
到此我们的收藏就完成了
结束语
到现在我们首页就完成了
敬请期待下一篇: 搜索功能的实现
以上是关于uni-app实战项目,跟着做完你就可以独立作战了的主要内容,如果未能解决你的问题,请参考以下文章