一、底部导航栏 首先,首页有个底部导航——tabBar,分为四个模块,故对应在pages下创建模块,pages.json文件中代码如下:
{
"pages": [ //pages数组中第一项表示应用启动页
{
"path": "pages/index/index",
"style": {}
,{
"path" : "pages/news/news",
"style" : {}
}
,{
"path" : "pages/paper/paper",
"style" : {}
}
,{
"path" : "pages/home/home",
"style" : {}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "仿糗事百科",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#FFFFFF"
},
"tabBar": {
"color" : "#B5B5B5",
"selectedColor" : "#FEE42B",
"borderStyle" : "black",
"backgroundColor" : "#FFFFFF",
"list" : [
{
"pagePath":"pages/index/index",
"text":"糗事",
"iconPath":"/static/tabbar/index.png",
"selectedIconPath":"/static/tabbar/indexed.png"
},
{
"pagePath":"pages/news/news",
"text":"动态",
"iconPath":"/static/tabbar/news.png",
"selectedIconPath":"/static/tabbar/newsed.png"
},
{
"pagePath":"pages/paper/paper",
"text":"小纸条",
"iconPath":"/static/tabbar/paper.png",
"selectedIconPath":"/static/tabbar/papered.png"
},
{
"pagePath":"pages/home/home",
"text":"我的",
"iconPath":"/static/tabbar/home.png",
"selectedIconPath":"/static/tabbar/homeed.png"
}
]
}
}
然后,参照原型图对启动页设置自定义导航栏(app-plus/titleNView),中间一个搜索框(searchInput) + 两侧各一图标(buttons),在对应page下的style中设置,代码如下:
{
"path": "pages/index/index",
"style": {//不显示标题==》搜索框 + 左右图标
"app-plus":{//设置编译到 App 平台的特定样式
"scrollIndicator":"none",//隐藏滚动条
"titleNView":{//导航栏
"searchInput":{// 搜索框配置
"align":"center",
"backgroundColor":"#F7F7F7",
"borderRadius":"4px",
"placeholder":"搜索糗事",
"placeholderColor":"#CCCCCC",
"disabled":true
},
"buttons":[//配置按钮
{// 左边
"color":"#FF9619",
"colorPressed":"#BBBBBB",
"float":"left",
"fontSize":"22px",
"fontSrc":"/static/font/icon.ttf",
"text":"\ue609"
},
{// 右边
"color":"#000000",
"colorPressed":"#BBBBBB",
"float":"right",
"fontSize":"22px",
"fontSrc":"/static/font/icon.ttf",
"text":"\ue653"
}
]
}
}
}
}
二、列表样式及数据展示并封装 首先,在实现界面效果时,先要对一些属性的状态有所了解。
关于 Flex容器属性
- 决定主轴的方向flex-direction:row | row-reverse | column | column-reverse;
- 如果一条轴线排不下,如何换行flex-wrap:nowrap | wrap | wrap-reverse;
- flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap
flex-flow: || ;
- 定义了项目在主轴上的对齐方式justify-content:flex-start | flex-end | center |
space-between | space-around;
- 定义项目在交叉轴上如何对齐align-items:flex-start | flex-end | center | baseline
| stretch;
- 定义了多根轴线的对齐方式align-content:flex-start | flex-end | center |
space-between | space-around | stretch;
Flex项目属性
order:定义项目的排列顺序。数值越小,排列越靠前,默认为0
flex-grow:定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
flex-shrink:定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
flex-basis:定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
flex: flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto
align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch
取值如 auto | flex-start | flex-end | center | baseline | stretch
根据项目需求,封装定义flex相关属性的文件common.css
/* flex布局 自定义封装*/
.u-f,.u-f-ac,.u-f-ajc{
display: flex;
}
.u-f-ac,.u-f-ajc{
align-items: center;
}
.u-f-ajc{
justify-content: center;
}
.u-f-jsb{
justify-content: space-between;
}
对应index.vue文件中添加数据,并封装对应list的布局样式
index-list.vue文件
{{item.username}}
关注
{{item.title}}
{{item.playnum}}次播放 {{item.long}}
{{item.infonum.dingnum}}
{{item.infonum.cainum}}
{{item.commentnum}}
{{item.sharenum}}
//scoped?
.index-list{
padding: 20upx;
border-bottom: 1upx solid #EEEEEE;
}
.index-list1>view:first-child{
color: #999999;
}
.index-list1>view:first-child image{
width: 85upx;
height: 85upx;
border-radius: 100%;
margin-right: 10upx;
}
.index-list1>view:last-child{
background: #F4F4F4;
border-radius:5upx;
padding: 0 10upx;
}
.index-list2{
padding-top: 15upx;
font-size: 32upx;
}
.index-list3{
position: relative;
padding-top: 15upx;
}
.index-list3>image{
width: 100%;
border-radius: 20upx;
}
.index-list4 view{
color: #999999;
}
.index-list4{
padding: 15upx 0;
}
.index-list4>view>view>view,.index-list4>view>view:first-child{
margin-right: 10upx;
}
.index-list-play{
position: absolute;
font-size: 140upx;
color: #FFFFFF;
}
.index-list-playinfo{
position: absolute;
background: rgba(51, 51, 51, 0.72);
color: #FFFFFF;
bottom: 8upx;
right: 8upx;
border-radius: 40upx;
font-size: 22upx;
padding: 0 12upx;
}
.index-list4 .active,.index-list4 .active>view{
color: #C5F61C;
}
问题记录:
1 props什么意思?什么情况下使用?
==》
2 style中设置scoped的作用
==》
三、滚动tab导航功能实现及封装 在官方提供的Demo中可拖动顶部选项卡:
scroll-view-——循环block(tabBars)
默认选中:active
{{tab.name}}
data() {
return {
tabIndex:0,
tabBars:[
{ name:"关注",id:"guanzhu" },
{ name:"推荐",id:"tuijian" },
{ name:"体育",id:"tiyu"},
{ name:"热点",id:"redian"},
{ name:"财经",id:"caijing" },
{ name:"娱乐",id:"yule"},
],
}
}
添加点击事件:@tap
methods: {
tabtap(index){
this.tabIndex=index;
}
}
样式优化:
.uni-swiper-tab{
border-bottom: 1upx solid #EEEEEE;
}
.swiper-tab-list{
color: #969696;
font-weight: bold;
}
.uni-tab-bar .active{
color: #343434;
}
.active .swiper-tab-line{
border-bottom: 6upx solid #FEDE33;
width: 70upx;
margin: auto;
border-top: 6upx solid #FEDE33;
border-radius:20upx;
}
显示中间部分swiper-view(动态绑定style不支持upx)
需计算高度:
onLoad() {
uni.getSystemInfo({
success: (res)=> {//ES5(加function?)与ES6写法的区?此处是ES6的写法
let height=res.windowHeight-uni.upx2px(100)
this.swiperheight=height;
}
});
},
methods: {
// tabbar点击事件
tabtap(index){
this.tabIndex=index;
},
// 滑动事件
tabChange(e){
this.tabIndex=e.detail.current;
}
},
添加显示数据
data() {
return {
tabIndex:0,
tabBars:[
{ name:"关注",id:"guanzhu" },
{ name:"推荐",id:"tuijian" },
{ name:"体育",id:"tiyu"},
{ name:"热点",id:"redian"},
{ name:"财经",id:"caijing" },
{ name:"娱乐",id:"yule"},
],
newslist:[
{
list:[
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:false,
title:"我是标题",
type:"img", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
infonum:{
index:0,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
},
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:true,
title:"我是标题",
type:"video", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
playnum:"20w",
long:"2:47",
infonum:{
index:1,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
}
]
},
{
list:[
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:false,
title:"我是标题",
type:"img", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
infonum:{
index:0,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
},
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:true,
title:"我是标题",
type:"video", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
playnum:"20w",
long:"2:47",
infonum:{
index:1,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
},
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:false,
title:"我是标题",
type:"img", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
infonum:{
index:0,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
},
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:true,
title:"我是标题",
type:"video", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
playnum:"20w",
long:"2:47",
infonum:{
index:1,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
}
]
},
{
list:[
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:false,
title:"我是标题",
type:"img", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
infonum:{
index:0,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
},
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:true,
title:"我是标题",
type:"video", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
playnum:"20w",
long:"2:47",
infonum:{
index:1,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
},
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:false,
title:"我是标题",
type:"img", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
infonum:{
index:0,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
},
{
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:true,
title:"我是标题",
type:"video", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
playnum:"20w",
long:"2:47",
infonum:{
index:1,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
}
]
},
{
list:[]
},
{
list:[]
},
{
list:[]
}
],
}
}
【uni-app开发(三)(项目实战之仿糗百首页)】封装横向滚动组件:props初始化数据? + 赋值组件间的通信
swiper-tab-head.vue
{{tab.name}}
.uni-swiper-tab{
border-bottom: 1upx solid #EEEEEE;
}
.swiper-tab-list{
color: #969696;
font-weight: bold;
}
.uni-tab-bar .active{
color: #343434;
}
.active .swiper-tab-line{
border-bottom: 6upx solid #FEDE33;
width: 70upx;
margin: auto;
border-top: 6upx solid #FEDE33;
border-radius:20upx;
}
index.vue
四、上拉加载组件开发及封装 布局显示及触底事件scrolltolower
+
+{{items.loadtext}}
并在每个list上添加loadtext
newslist:[
{
+loadtext:"上拉加载更多",
list:[
{......},
{.....}
]
},
{
+loadtext:"上拉加载更多",
list:[
{......},
{......},
{......},
{......}
]
},
{
+loadtext:"上拉加载更多",
list:[
{......},
{......},
{......},
{......}
]
},
{
+loadtext:"上拉加载更多",
list:[]
},
{
+loadtext:"上拉加载更多",
list:[]
},
{
+loadtext:"上拉加载更多",
list:[]
}
],
loadmore四种状态处理
// 上拉加载
loadmore(index){
if(this.newslist[index].loadtext!="上拉加载更多"){ return;
}
// 修改状态
this.newslist[index].loadtext="加载中...";
// 获取数据
setTimeout(()=> {
//获取完成
let obj={
userpic:"../../static/demo/userpic/12.jpg",
username:"昵称",
isguanzhu:false,
title:"我是标题",
type:"img", // img:图文,video:视频
titlepic:"../../static/demo/datapic/11.jpg",
infonum:{
index:0,//0:没有操作,1:顶,2:踩;
dingnum:11,
cainum:11,
},
commentnum:10,
sharenum:10,
};
this.newslist[index].list.push(obj);
this.newslist[index].loadtext="上拉加载更多";
}, 1000);
// this.newslist[index].loadtext="没有更多数据了";
}
下拉反弹样式的隐藏
pages.json的app-plus中添加“bounce”: “none”
封装上拉加载更多效果
第一步:创建新的load-more.vue文件
{{loadtext}}
.load-more{
text-align: center;
color: #AAAAAA;
padding: 15upx;
}
第二步:调用load-more.vue文件
-
+
五、优化图文列表组件 5.1 列表中添加动画显示效果(index-list.vue)
animated + 动画效果如rotateIn/fadeInLeft + 速度如fast
5.2 关注事件:当关注成功弹toast提示,并隐藏关注按钮
+
关注
methods:{
// 关注
guanzhu(){
this.item.isguanzhu=true;
uni.showToast({
title: '关注成功',
});
},
},
5.3 顶踩逻辑处理
+
{{item.infonum.dingnum}}
+
{{item.infonum.cainum}}
// 顶踩
caozuo(type){
switch (type){
case "ding":
if(this.item.infonum.index==1){ return;
}
this.item.infonum.dingnum++;
if(this.item.infonum.index==2){
this.item.infonum.cainum--;
}
this.item.infonum.index=1;
break;
case "cai":
if(this.item.infonum.index==2){ return;
}
this.item.infonum.cainum++;
if(this.item.infonum.index==1){
this.item.infonum.dingnum--;
}
this.item.infonum.index=2;
break;
}
},
5.4 点击跳转到详情界面处理
+ {{item.title}} +
{{item.playnum}}次播放 {{item.long}}
// 进入详情页
opendetail(){
console.log("进入详情页")
}
5.5 无数据默认组件及封装
第一步:无数据的页面布局文件nothing.vue
.nothing{
background: #FFFFFF;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.nothing image{
width: 50%;
}
第二步:index.vue中通过条件渲染处理显示无数据界面
+
+
+ +
+
引入控件并注册
import indexList from "../../components/index/index-list.vue";
import swiperTabHead from "../../components/index/swiper-tab-head.vue";
import loadMore from "../../components/common/load-more.vue";
+ import noThing from "../../components/common/no-thing.vue";
export default {
components:{
indexList,
swiperTabHead,
loadMore,
+noThing
},
}
推荐阅读
- 学习笔记|uni-app开发小程序
- uni-app开发(四)(项目实战之仿糗百搜索页)
- uni-app开发(二)(基础组件及样式)
- uni-app开发(一)(准备工作及环境配置)
- view里面内容左对齐或者右对齐
- uniapp 输入对话框 漂亮