注:前言、目錄見 https://god-excious.blog.csdn.net/article/details/105312456
文章目錄
【024】page-json配置
官方文檔 https://uniapp.dcloud.io/collocation/pages?id=配置項列表
官方文檔 https://uniapp.dcloud.io/collocation/pages?id=style
可以在page-json中配置一些樣式,包括“導航欄”、“按鈕”、“下拉刷新”等樣式。
大多數內容可以到官方文檔中找到,下面給出一種配置的樣式
{
"pages": [ //pages數組中第一項表示應用啓動頁,參考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
// "navigationBarTitleText": "仿糗事百科"
"app-plus": {
// 隱藏滾動條
"scrollIndicator":"none",
// 配置導航欄
"titleNView": {
// 配置搜索框
"searchInput": {
// 對齊方式(默認值center)
"align": "center",
// 背景色
"backgroundColor": "#F7F7F7",
// 邊框圓角
"borderRadius": "4px",
// 提示文字
"placeholder": "搜索糗事",
// 阻止輸入(一般都是阻止輸入,點擊後跳轉到搜索頁面)
"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"
}
]
}
}
}
}
,{
"path" : "pages/news/news",
"style" : {}
}
,{
"path" : "pages/paper/paper",
"style" : {}
}
,{
"path" : "pages/home/home",
"style" : {}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "仿糗事百科",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color":"#adadad", // 導航欄文字默認顏色
"selectedColor":"#fee42a", // 導航欄選中顏色
"backgroundColor":"#fff", // 導航欄背景顏色
"borderStyle":"white", // 導航欄邊框樣式
"list":[ // tab的列表
{
"pagePath":"pages/index/index", // 導航欄對應頁面路徑(不用寫.vue)
"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/homed.png"
}
]
}
}
注:
buttons
中字體的路徑fontSrc
對應了圖標項目中的iconfont.ttf文件的路徑,一般將其引入到uni-app項目中的/static/font
文件夾下buttons
中提示文字text
,填寫的內容爲圖標項目中demo_index.html打開後Unicode下,該圖標的編號。例如:某圖標在Unicode中編號爲
,就應該填寫"text": "\ue601"
,以此類推。
【025】圖文、視頻和列表樣式(上)
圖片引入
圖片組件——官方文檔 https://uniapp.dcloud.io/component/image
格式大致如下
<image src="../../static/demo/userpic/12.jpg" mode="widthFix" lazy-load></image>
屬性 | 功能 |
---|---|
src |
圖片路徑 |
mode |
圖片裁剪、縮放的模式(widthFix 代表寬度不變,高度自動變化,保持原圖寬高比不變) |
lazy-load |
圖片懶加載 |
設計細節
在設計時,需要注意以下一些細節
- 首先按照設計圖,對某個區域可以分成若干行,我們把這些行都做成
class="網頁名-list-i"
的view
組件,然後將它們放到一個class="網頁名-list"
的view
組件中 - 像是頭像、暱稱這一組,或者是**+icon、關注這一組,都是水平方向上垂直居中排列的,可以把文字(直接寫到父標籤下,不一定要新建標籤)、圖像放到一個
view
組件下,然後以flex佈局(默認主軸方向即可)設置交叉軸(縱向)居中——align-item: center;
**,即可在同一行上垂直居中排版 - 像是贊數、踩數這一組,或者是評論數、轉發數這一組,水平方向上垂直居中和上面類似,還要設計好圖標與文字之間的間距,可以給圖標設置一個**
margin-right
,如果有多個圖標和文字的組,並且排列在同一側,可以給圖標的父標籤設置一個margin-right
**,讓組與組之間保持間距。 - 設計圖中的一些圓角不要忽略了
- 行與行之間的間距可以通過給類名爲
網頁名-list-i
的元素設置一個padding-top
,最後一個行元素可以考慮設置一個padding: ??px, 0;
讓上下都保持一部分間距 - 整個區域內部的邊緣地區若有少量間距,可以對整個區域的標籤設置一個
padding
,顯示出這樣的空隙。 - 整個區域往下的分隔線,可以通過設置
border-bottom
屬性實現 - 阿里巴巴矢量圖庫項目的圖標引入,可以參考章節【010】
- 爲了增強CSS代碼複用性,可以把flex佈局的相關代碼提取出來,封裝到common.css文件裏去,一般根據flex佈局的樣式來起名,我們可以取出類似
u-f
、u-f-ac
、u-f-ajc
、u-f-jsb
這樣的類名,然後給需要的標籤加上這些類名。
整體代碼
-
index.css文件
<template> <view> <view class="index-list"> <view class="index-list1 u-f-ac u-f-jsb"> <view class="u-f-ac"> <image src="../../static/demo/userpic/12.jpg" mode="widthFix" lazy-load></image> 暱稱 </view> <view class="u-f-ac"> <view class="icon iconfont icon-zengjia"></view>關注 </view> </view> <view class="index-list2">這是標題</view> <view class="index-list3"> <image src="../../static/demo/datapic/11.jpg" mode="widthFix" lazy-load></image> </view> <view class="index-list4 u-f-ac u-f-jsb"> <view class="u-f-ac"> <view class="u-f-ac"> <view class="icon iconfont icon-icon_xiaolian-mian u-f-ac"></view> 10 </view> <view class="u-f-ac"> <view class="icon iconfont icon-kulian u-f-ac"></view> 10 </view> </view> <view class="u-f-ac"> <view class="u-f-ac"> <view class="icon iconfont icon-pinglun1 u-f-ac"></view> 10 </view> <view class="u-f-ac"> <view class="icon iconfont icon-zhuanfa u-f-ac"></view> 10 </view> </view> </view> </view> </view> </template> <script> export default { data() { return { title: 'Hello' } }, onLoad() { }, methods: { } } </script> <style> /* common.css在App.vue文件中引入了進來 */ .index-list { padding: 20upx; border-bottom: 1upx solid #EEEEEE; } .index-list1>view:first-child { color: #999999; } .index-list1>view:first-child image { width: 90upx; height: 90upx; border-radius: 50%; margin-right: 10upx; } .index-list1>view:last-child { background-color: #F4F4F4; border-radius: 5upx; padding: 0 10upx; } .index-list2 { padding-top: 15upx; font-size: 32upx; } .index-list3 { padding-top: 15upx; } .index-list3>image { width: 100%; border-radius: 20upx; } .index-list4 { padding: 15upx 0; } .index-list4>view { color: #999999; } .index-list4>view>view:first-child, .index-list4>view>view>view { margin-right: 10upx; } </style>
-
common.css文件
/* 代表flex佈局 */ .u-f, .u-f-ac, .u-f-ajc, .u-f-jsb { display: flex; } .u-f-ac, .u-f-ajc { align-items: center; } .u-f-ajc { justify-content: center; } .u-f-jsb { justify-content: space-between; }
-
App.vue文件
<script> export default { onLaunch: function() { console.log('App Launch') }, onShow: function() { console.log('App Show') }, onHide: function() { console.log('App Hide') } } </script> <style> /*每個頁面公共css */ @import './common/uni.css'; @import './common/icon.css'; @import './common/animate.css'; @import './common/common.css'; </style>
-
pages.json文件
和上一節一樣
-
效果圖
【026】圖文、視頻和列表樣式(下)
設計細節
在設計時,有以下一些細節
- 要讓某個組件顯示在另一個組件之上,可以把他們放到同一個父組件下,然後對父組件用
postion: relative;
,對子組件用postion: absolute;
。然後如果需要顯示在父組件的正中央,可以給父組件設置一個class="u-f-ajc"
;如果需要顯示在父組件的邊上,可以設置right
、left
、top
、bottom
其中的不同方向上的兩個。 - 如果需要調節帶透明的背景色,可以到Chrome瀏覽器中打開開發者工具,隨便找一個元素,添加屬性
color
,然後點擊對應的顏色,拖動透明度條,進行調節,如果需要rgba
,點擊上下切換的小箭頭切換,然後把color
屬性裏的rgba
值複製過來。 - 對於阿里巴巴矢量圖標庫項目中,通過添加類名引入的圖標,如果要設置其大小,只需要設置
font-size
屬性即可。
整體代碼
-
index.vue文件
和上一節課相比,主要增加、改動的地方是17~21行、94行、115~130行
<template> <view> <view class="index-list"> <view class="index-list1 u-f-ac u-f-jsb"> <view class="u-f-ac"> <image src="../../static/demo/userpic/12.jpg" mode="widthFix" lazy-load></image> 暱稱 </view> <view class="u-f-ac"> <view class="icon iconfont icon-zengjia"></view>關注 </view> </view> <view class="index-list2">這是標題</view> <view class="index-list3 u-f-ajc"> <!-- 圖片 --> <image src="../../static/demo/datapic/11.jpg" mode="widthFix" lazy-load></image> <!-- 視頻 --> <view class="index-list-play icon iconfont icon-bofang"></view> <view class="index-list-playinfo"> 20w次播放 2:17 </view> </view> <view class="index-list4 u-f-ac u-f-jsb"> <view class="u-f-ac"> <view class="u-f-ac"> <view class="icon iconfont icon-icon_xiaolian-mian u-f-ac"></view> 10 </view> <view class="u-f-ac"> <view class="icon iconfont icon-kulian u-f-ac"></view> 10 </view> </view> <view class="u-f-ac"> <view class="u-f-ac"> <view class="icon iconfont icon-pinglun1 u-f-ac"></view> 10 </view> <view class="u-f-ac"> <view class="icon iconfont icon-zhuanfa u-f-ac"></view> 10 </view> </view> </view> </view> </view> </template> <script> export default { data() { return { title: 'Hello' } }, onLoad() { }, methods: { } } </script> <style> .index-list { padding: 20upx; border-bottom: 1upx solid #EEEEEE; } .index-list1>view:first-child { color: #999999; } .index-list1>view:first-child image { width: 90upx; height: 90upx; border-radius: 50%; margin-right: 10upx; } .index-list1>view:last-child { background-color: #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 { padding: 15upx 0; } .index-list4>view { color: #999999; } .index-list4>view>view:first-child, .index-list4>view>view>view { margin-right: 10upx; } .index-list-play { position: absolute; font-size: 140upx; color: #FFFFFF; } .index-list-playinfo { position: absolute; background-color: rgba(51, 51, 51, 0.62); color: #FFFFFF; bottom: 8upx; right: 8upx; border-radius: 40upx; font-size: 22upx; padding: 0 12upx; } </style>
-
其他文件
和上一小節相同,不再重複
-
效果圖
【027】封裝列表樣式組件
數據存儲
在script
腳本的data()
中,用數組將頁面中出現的數據封裝成一個個對象
<script>
export default {
data() {
return {
list:[
{
// 用戶頭像
userpic: "../../static/demo/userpic/12.jpg",
// 用戶名
username: "暱稱",
// 關注情況
isguanzhu: false,
// 標題
title: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
userpic: "../../static/demo/userpic/12.jpg",
username: "暱稱",
isguanzhu: true,
title: "這是標題",
type: "video",
titlepic: "../../static/demo/datapic/11.jpg",
// 播放次數
playnum: "2w",
long: "2:47",
infonum: {
index: 2,
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
]
}
},
onLoad() {
},
methods: {
}
}
</script>
因爲有可能存在多個對象,所以需要列表渲染(循環),詳細代碼見下面一小段。
狀態(關注、贊、踩)標識
“是否關注”這一狀態可以完全放到list
對象中一個對象的一個布爾變量來標識,用v-show
進行條件渲染。
“是否點贊、是否點踩”這些狀態,和點贊數、點踩數一起放到list
對象中一個對象的一個infonum
裏,狀態用index
來標識,值爲0
代表“未操作”,值爲1
代表“點了贊”,值爲2
代表“點了踩”。然後在:class
屬性中根據一個條件表達式選擇判斷是否獲得點擊後的類名active
的樣式。
<template>
<view>
<block v-for="(item, index) in list" :key="index">
<view class="index-list">
<view class="index-list1 u-f-ac u-f-jsb">
<view class="u-f-ac">
<image :src="item.userpic" mode="widthFix" lazy-load></image>
{{item.username}}
</view>
<!-- v-if會導致一點佈局異常,還是用v-show好一些 -->
<view class="u-f-ac" v-show="item.isguanzhu">
<view class="icon iconfont icon-zengjia"></view>關注
</view>
</view>
<view class="index-list2">{{item.title}}</view>
<view class="index-list3 u-f-ajc">
<!-- 圖片 -->
<image :src="item.titlepic" mode="widthFix" lazy-load></image>
<!-- 視頻 -->
<template v-if="item.type=='video'">
<view class="index-list-play icon iconfont icon-bofang"></view>
<view class="index-list-playinfo">
{{item.playnum}}次播放 {{item.long}}
</view>
</template>
</view>
<view class="index-list4 u-f-ac u-f-jsb">
<view class="u-f-ac">
<view class="u-f-ac" :class="{'active':(item.infonum.index==1)}">
<view class="icon iconfont icon-icon_xiaolian-mian u-f-ac"></view>
{{item.infonum.dingnum}}
</view>
<view class="u-f-ac" :class="{'active':(item.infonum.index==2)}">
<view class="icon iconfont icon-kulian u-f-ac"></view>
{{item.infonum.cainum}}
</view>
</view>
<view class="u-f-ac">
<view class="u-f-ac">
<view class="icon iconfont icon-pinglun1 u-f-ac"></view>
{{item.commentnum}}
</view>
<view class="u-f-ac">
<view class="icon iconfont icon-zhuanfa u-f-ac"></view>
{{item.sharenum}}
</view>
</view>
</view>
</view>
</block>
</view>
</template>
<script>
export default {
data() {
return {
list:[
{
// 用戶頭像
userpic: "../../static/demo/userpic/12.jpg",
// 用戶名
username: "暱稱",
// 關注情況
isguanzhu: false,
// 標題
title: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
userpic: "../../static/demo/userpic/12.jpg",
username: "暱稱",
isguanzhu: true,
title: "這是標題",
type: "video",
titlepic: "../../static/demo/datapic/11.jpg",
// 播放次數
playnum: "2w",
long: "2:47",
infonum: {
index: 2,
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
]
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.index-list {
padding: 20upx;
border-bottom: 1upx solid #EEEEEE;
}
.index-list1>view:first-child {
color: #999999;
}
.index-list1>view:first-child image {
width: 90upx;
height: 90upx;
border-radius: 50%;
margin-right: 10upx;
}
.index-list1>view:last-child {
background-color: #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 {
padding: 15upx 0;
}
.index-list4>view {
color: #999999;
}
.index-list4>view>view:first-child, .index-list4>view>view>view {
margin-right: 10upx;
}
.index-list-play {
position: absolute;
font-size: 140upx;
color: #FFFFFF;
}
.index-list-playinfo {
position: absolute;
background-color: rgba(51, 51, 51, 0.62);
color: #FFFFFF;
bottom: 8upx;
right: 8upx;
border-radius: 40upx;
font-size: 22upx;
padding: 0 12upx;
}
.index-list4 .active, .index-list4 .active > view{
color: #C5F61C;
}
</style>
效果圖
封裝組件
像是上面我們做好的一個list樣式,就可以封裝起來。
封裝的步驟如下:
-
創建好一個components文件夾,然後右鍵新建組件,在components文件夾下再創建一個index文件夾,把之前新建好的組件文件index-list.vue文件放到index文件夾下
-
將index.vue文件中block標籤下的所有標籤剪切,放到index-list.vue文件中對應位置
-
將index.vue文件中
style
下的所有樣式剪切,放到index-list.vue文件中對應位置。注:最好給裏面的
style
加上一個屬性scoped
,避免在引入組件樣式後污染原本設置好的其他樣式 -
在index-list.vue文件的
script
下的props
中,定義需要傳入的變量及其類型,像是這裏就需要將循環中的item
和index
傳進來,形式爲變量名: 類型
-
在index.vue文件的
script
的export default
前,將組件文件引入進來,形如:import indexList from "../../components/index/index-list.vue";
注:將中劃線命名改寫爲小駝峯命名
-
在index.vue文件的
script
的components
中,註冊相應的組件 -
以標籤形式將組件進行引入,在屬性中傳入需要的參數,形如:
<block v-for="(item, index) in list" :key="index"> <index-list :item="item" :index="index"></index-list> </block>
封裝後的項目代碼文件如下:
-
index.vue文件
<template> <view> <block v-for="(item, index) in list" :key="index"> <index-list :item="item" :index="index"></index-list> </block> </view> </template> <script> import indexList from "../../components/index/index-list.vue"; export default { components: { indexList }, data() { return { list:[ { // 用戶頭像 userpic: "../../static/demo/userpic/12.jpg", // 用戶名 username: "暱稱", // 關注情況 isguanzhu: false, // 標題 title: "這是標題", // 類型(img-圖文,video-視頻) type: "img", // 封面圖 titlepic: "../../static/demo/datapic/11.jpg", // 贊、踩數,標記情況 infonum: { index: 1, // 0-無操作,1-頂了,2-踩了 dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, { userpic: "../../static/demo/userpic/12.jpg", username: "暱稱", isguanzhu: true, title: "這是標題", type: "video", titlepic: "../../static/demo/datapic/11.jpg", // 播放次數 playnum: "2w", long: "2:47", infonum: { index: 2, dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, ] } }, onLoad() { }, methods: { } } </script> <style> </style>
-
index-list.vue文件
<template> <view class="index-list"> <view class="index-list1 u-f-ac u-f-jsb"> <view class="u-f-ac"> <image :src="item.userpic" mode="widthFix" lazy-load></image> {{item.username}} </view> <!-- v-if會導致一點佈局異常,還是用v-show好一些 --> <view class="u-f-ac" v-show="item.isguanzhu"> <view class="icon iconfont icon-zengjia"></view>關注 </view> </view> <view class="index-list2">{{item.title}}</view> <view class="index-list3 u-f-ajc"> <!-- 圖片 --> <image :src="item.titlepic" mode="widthFix" lazy-load></image> <!-- 視頻 --> <template v-if="item.type=='video'"> <view class="index-list-play icon iconfont icon-bofang"></view> <view class="index-list-playinfo"> {{item.playnum}}次播放 {{item.long}} </view> </template> </view> <view class="index-list4 u-f-ac u-f-jsb"> <view class="u-f-ac"> <view class="u-f-ac" :class="{'active':(item.infonum.index==1)}"> <view class="icon iconfont icon-icon_xiaolian-mian u-f-ac"></view> {{item.infonum.dingnum}} </view> <view class="u-f-ac" :class="{'active':(item.infonum.index==2)}"> <view class="icon iconfont icon-kulian u-f-ac"></view> {{item.infonum.cainum}} </view> </view> <view class="u-f-ac"> <view class="u-f-ac"> <view class="icon iconfont icon-pinglun1 u-f-ac"></view> {{item.commentnum}} </view> <view class="u-f-ac"> <view class="icon iconfont icon-zhuanfa u-f-ac"></view> {{item.sharenum}} </view> </view> </view> </view> </template> <script> export default { props: { item: Object, index: Number } } </script> <style scoped> .index-list { padding: 20upx; border-bottom: 1upx solid #EEEEEE; } .index-list1>view:first-child { color: #999999; } .index-list1>view:first-child image { width: 90upx; height: 90upx; border-radius: 50%; margin-right: 10upx; } .index-list1>view:last-child { background-color: #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 { padding: 15upx 0; } .index-list4>view { color: #999999; } .index-list4>view>view:first-child, .index-list4>view>view>view { margin-right: 10upx; } .index-list-play { position: absolute; font-size: 140upx; color: #FFFFFF; } .index-list-playinfo { position: absolute; background-color: rgba(51, 51, 51, 0.62); color: #FFFFFF; bottom: 8upx; right: 8upx; border-radius: 40upx; font-size: 22upx; padding: 0 12upx; } .index-list4 .active, .index-list4 .active > view{ color: #C5F61C; } </style>
-
其他文件
和之前基本一樣
-
效果圖
和上一段展示的效果圖一樣
【028】滾動tab導航開發
操作步驟
根據uni-app-hello項目中的tabbar.vue文件,依次進行以下操作:
- 將uni-app-hello項目中的uni.css文件引入,方法可以參考【009】
- 將導航欄的文字內容以若干組
{name: "??", id: "??"}
的形式,寫到data
中的數組tabBars
下。 - 在外層創建一個
class="uni-tab-bar"
的view
組件 - 在上述
view
組件下創建一個class="uni-swiper-tab" scroll-x
的scroll-view
組件 - 在上述
scroll-view
組件下創建一個block
組件,屬性爲v-for="(tab,index) in tabBars" :key="tab.id"
,列表渲染class="swiper-tab-list"
的view
組件 - 每一個被列表渲染的
view
組件內容顯示{{tab.name}}
其他注意點
有如下注意點:
- 如果需要設置導航欄中當前選中項的樣式,可以對被列表渲染的
view
組件設置:class="{'active': tabIndex==index}"
- 如果需要設置導航欄中某一項被點擊後成爲當前選中項,可以先在
data
中設置tabIndex
值(先設置爲0代表初始選中第一個),然後在methods
中設置一個處理函數tabtap(index)
,內容就是this.tabIndex=index;
,最後放到被列表渲染的view
組件上用@tap="tabtap(index)"
綁定事件處理 - 可以對
.uni-swiper-tab
的scroll-view
組件設置border-bottom
屬性,調整導航欄分隔線的樣式 - 可以對
.swiper-tab-list
的列表渲染view
組件設置文字的樣式 - 可以對
.uni-tab-bar
下的.active
的列表渲染view
組件設置被選中後的文字樣式 - 如果要添加被選中後文字下方出現下劃線的樣式,可以在被列表渲染的
view
組件下再加一個class="swiper-tab-line"
的view
組件,然後對.active
下的.swiper-tab-line
設置類似border-botom
、margin: 0 auto;
、border-radius
等等樣式
整體代碼
以下僅展示index.vue文件的代碼
<template>
<view>
<view class="uni-tab-bar">
<scroll-view scroll-x class="uni-swiper-tab">
<block v-for="(tab, index) in tabBars" :key="tab.id">
<view class="swiper-tab-list" :class="{'active': tabIndex==index}" @tap="tabtap(index)">
{{tab.name}}
<view class="swiper-tab-line"></view>
</view>
</block>
</scroll-view>
</view>
<!-- <block v-for="(item, index) in list" :key="index">
<index-list :item="item" :index="index"></index-list>
</block> -->
</view>
</template>
<script>
import indexList from "../../components/index/index-list.vue";
export default {
components: {
indexList
},
data() {
return {
tabIndex: 0,
tabBars: [
{name: "關注", id: "guanzhu"},
{name: "推薦", id: "tuijian"},
{name: "體育", id: "tiyu"},
{name: "熱點", id: "redian"},
{name: "財經", id: "caijing"},
{name: "娛樂", id: "yule"}
],
list:[
{
// 用戶頭像
userpic: "../../static/demo/userpic/12.jpg",
// 用戶名
username: "暱稱",
// 關注情況
isguanzhu: false,
// 標題
title: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
userpic: "../../static/demo/userpic/12.jpg",
username: "暱稱",
isguanzhu: true,
title: "這是標題",
type: "video",
titlepic: "../../static/demo/datapic/11.jpg",
// 播放次數
playnum: "2w",
long: "2:47",
infonum: {
index: 2,
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
]
}
},
onLoad() {
},
methods: {
tabtap(index){
this.tabIndex=index;
}
}
}
</script>
<style>
.swiper-tab-list {
color: #969696;
font-weight: bold;
}
.uni-swiper-tab {
border-bottom: 1upx solid #EEEEEE;
}
.uni-tab-bar .active {
color: #343434;
}
/* 被選中才出現下劃線 */
.active .swiper-tab-line {
border-bottom: 6upx solid #FEDE33;
width: 70upx;
margin: 0 auto;
border-top: 6upx solid #FEDE33;
border-radius: 20upx;
}
</style>
效果圖
【029】滾動tab導航開發(下)
swiper
組件·官方文檔 https://uniapp.dcloud.io/component/swiper
獲取系統信息·官方文檔 https://uniapp.dcloud.io/api/system/info
注意點
- 創建數組數據
newslist
,裏面是6個list
對象,分別與滾動欄上的6個種類對應 - 爲了能夠讓能容橫向滾動,和上一節類似地在
class="uni-tab-bar"
的view
組件中使用了class="swiper-box"
的swiper
組件,在swiper
組件下用swiper-item
組件對數組newslist
進行列表渲染,然後在swiper-item
組件下用scroll-view
組件創建滾動條,滾動條內將之前的內容block
組件放入,大致就完成了 - 爲了獲取運行的系統的相關信息(如:系統的屏幕尺寸、顯示尺寸……),可以在
script
下的onLoad()
中用uni.getSystemInfo({ success:(res)=> { } })
在函數體中用res.windowHeight
獲取顯示高度(其他屬性見上面給出的官方文檔) - 如果要調節自適應的大小,可以變量
swiperheight
存儲大小對應的px
值,然後給swiper
組件設置相應尺寸的style
(因爲upx
不支持在style
中動態綁定)。swiperheight
的計算應該放到onLoad()
中的uni.getSystemInfo
裏,然後把結果傳入這個變量值中。由於在uin.css文件中,.uni-tab-bar
、.swiper-box
的height
被計算爲calc(100% - 100upx)
,我們可以用類似的方法,計算出this.swiperheight=res.windowHeight-uni.upx2px(100);
,這樣的高度是差不多就是可以自適應的。 - 給
swiper
組件設置:current:"tabIndex";
可以讓橫向滾動時,顯示出對應的列表內容。 - 給
swiper
組件設置@change="tabChange"
,然後定義好函數tabChange
,裏面有默認參數event
(調用時不用加上括號和參數列表),函數的內容定義this.tabIndex=e.detail.current;
,這樣可以設置橫向滾動時,讓導航欄也一起隨之變化
詳細代碼
<template>
<view>
<view class="uni-tab-bar">
<scroll-view scroll-x class="uni-swiper-tab">
<block v-for="(tab, index) in tabBars" :key="tab.id">
<view class="swiper-tab-list" :class="{'active': tabIndex==index}" @tap="tabtap(index)">
{{tab.name}}
<view class="swiper-tab-line"></view>
</view>
</block>
</scroll-view>
</view>
<view class="uni-tab-bar">
<swiper class="swiper-box" :style="{height: swiperheight+'px'}" :current="tabIndex" @change="tabChange">
<swiper-item v-for="(items, index) in newslist" :key="index">
<scroll-view scroll-y class="list">
<block v-for="(item, index1) in items.list" :key="index1">
<index-list :item="item" :index="index1"></index-list>
</block>
</scroll-view>
</swiper-item>
</swiper>
</view>
</view>
</template>
<script>
import indexList from "../../components/index/index-list.vue";
export default {
components: {
indexList
},
data() {
return {
swiperheight: 500,
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: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
userpic: "../../static/demo/userpic/12.jpg",
username: "暱稱",
isguanzhu: true,
title: "這是標題",
type: "video",
titlepic: "../../static/demo/datapic/11.jpg",
// 播放次數
playnum: "2w",
long: "2:47",
infonum: {
index: 2,
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
]
},
{
list:[
{
// 用戶頭像
userpic: "../../static/demo/userpic/12.jpg",
// 用戶名
username: "暱稱",
// 關注情況
isguanzhu: false,
// 標題
title: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
userpic: "../../static/demo/userpic/12.jpg",
username: "暱稱",
isguanzhu: true,
title: "這是標題",
type: "video",
titlepic: "../../static/demo/datapic/11.jpg",
// 播放次數
playnum: "2w",
long: "2:47",
infonum: {
index: 2,
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
// 用戶頭像
userpic: "../../static/demo/userpic/12.jpg",
// 用戶名
username: "暱稱",
// 關注情況
isguanzhu: false,
// 標題
title: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
userpic: "../../static/demo/userpic/12.jpg",
username: "暱稱",
isguanzhu: true,
title: "這是標題",
type: "video",
titlepic: "../../static/demo/datapic/11.jpg",
// 播放次數
playnum: "2w",
long: "2:47",
infonum: {
index: 2,
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
]
},
{
list:[
{
// 用戶頭像
userpic: "../../static/demo/userpic/12.jpg",
// 用戶名
username: "暱稱",
// 關注情況
isguanzhu: false,
// 標題
title: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
{
userpic: "../../static/demo/userpic/12.jpg",
username: "暱稱",
isguanzhu: true,
title: "這是標題",
type: "video",
titlepic: "../../static/demo/datapic/11.jpg",
// 播放次數
playnum: "2w",
long: "2:47",
infonum: {
index: 2,
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
},
]
},
{
list:[]
},
{
list:[]
},
{
list:[]
}
]
}
},
onLoad() {
uni.getSystemInfo({
success:(res)=> {
let height = res.windowHeight-uni.upx2px(100);
this.swiperheight=height;
}
});
},
methods: {
// tabBar點擊事件
tabtap(index) {
this.tabIndex=index;
},
// 滑動聯動切換導航欄
tabChange(e) {
// console.log(JSON.stringify(e.detail));
this.tabIndex=e.detail.current;
}
}
}
</script>
<style>
.swiper-tab-list {
color: #969696;
font-weight: bold;
}
.uni-swiper-tab {
border-bottom: 1upx solid #EEEEEE;
}
.uni-tab-bar .active {
color: #343434;
}
/* 被選中才出現下劃線 */
.active .swiper-tab-line {
border-bottom: 6upx solid #FEDE33;
width: 70upx;
margin: 0 auto;
border-top: 6upx solid #FEDE33;
border-radius: 20upx;
}
</style>
【030】封裝滾動tab導航組件
步驟總結
步驟如下:
- 首先還是和以前一樣,在components文件夾下的index文件夾下,新建swiper-tab-head.vue文件,將導航欄部分代碼剪切過來,將樣式部分代碼剪切過來,將點擊處理的方法剪切過來,在swiper-tab-head.vue文件的
props
中定義好要使用到的變量,在index.vue文件中用自定義的swiper-tab-head
組件將導航欄引入,然後以:tabBars="tabBars" :tabIndex="tabIndex"
的方式傳入相關變量 - 但是僅僅是上面這樣還不夠,因爲點擊事件的方法調用在子組件裏,沒有修改到父組件裏面的變量值,因此要在子組件裏將點擊事件的處理改成
this.$emit('tabtap', index);
,意思是監聽一個自定義的名爲'tabtap'
的事件、然後把index
傳過去,然後在父組件裏通過設置屬性@tabtap="tabtap"
,意思是當觸發了tabtap
事件後、將子組件中通過tabtap
事件傳入的index
作爲參數、傳入父組件的函數tabtap
中、進行事件處理,從而達到父子組件通信的效果。
詳細代碼
-
index.vue文件
<template> <view> <swiper-tab-head :tabBars="tabBars" :tabIndex="tabIndex" @tabtap="tabtap"></swiper-tab-head> <view class="uni-tab-bar"> <swiper class="swiper-box" :style="{height: swiperheight+'px'}" :current="tabIndex" @change="tabChange"> <swiper-item v-for="(items, index) in newslist" :key="index"> <scroll-view scroll-y class="list"> <block v-for="(item, index1) in items.list" :key="index1"> <index-list :item="item" :index="index1"></index-list> </block> </scroll-view> </swiper-item> </swiper> </view> </view> </template> <script> import indexList from "../../components/index/index-list.vue"; import swiperTabHead from "../../components/index/swiper-tab-head.vue"; export default { // 註冊組件 components: { indexList, swiperTabHead }, data() { return { swiperheight: 500, 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: "這是標題", // 類型(img-圖文,video-視頻) type: "img", // 封面圖 titlepic: "../../static/demo/datapic/11.jpg", // 贊、踩數,標記情況 infonum: { index: 1, // 0-無操作,1-頂了,2-踩了 dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, { userpic: "../../static/demo/userpic/12.jpg", username: "暱稱", isguanzhu: true, title: "這是標題", type: "video", titlepic: "../../static/demo/datapic/11.jpg", // 播放次數 playnum: "2w", long: "2:47", infonum: { index: 2, dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, ] }, { list:[ { // 用戶頭像 userpic: "../../static/demo/userpic/12.jpg", // 用戶名 username: "暱稱", // 關注情況 isguanzhu: false, // 標題 title: "這是標題", // 類型(img-圖文,video-視頻) type: "img", // 封面圖 titlepic: "../../static/demo/datapic/11.jpg", // 贊、踩數,標記情況 infonum: { index: 1, // 0-無操作,1-頂了,2-踩了 dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, { userpic: "../../static/demo/userpic/12.jpg", username: "暱稱", isguanzhu: true, title: "這是標題", type: "video", titlepic: "../../static/demo/datapic/11.jpg", // 播放次數 playnum: "2w", long: "2:47", infonum: { index: 2, dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, { // 用戶頭像 userpic: "../../static/demo/userpic/12.jpg", // 用戶名 username: "暱稱", // 關注情況 isguanzhu: false, // 標題 title: "這是標題", // 類型(img-圖文,video-視頻) type: "img", // 封面圖 titlepic: "../../static/demo/datapic/11.jpg", // 贊、踩數,標記情況 infonum: { index: 1, // 0-無操作,1-頂了,2-踩了 dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, { userpic: "../../static/demo/userpic/12.jpg", username: "暱稱", isguanzhu: true, title: "這是標題", type: "video", titlepic: "../../static/demo/datapic/11.jpg", // 播放次數 playnum: "2w", long: "2:47", infonum: { index: 2, dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, ] }, { list:[ { // 用戶頭像 userpic: "../../static/demo/userpic/12.jpg", // 用戶名 username: "暱稱", // 關注情況 isguanzhu: false, // 標題 title: "這是標題", // 類型(img-圖文,video-視頻) type: "img", // 封面圖 titlepic: "../../static/demo/datapic/11.jpg", // 贊、踩數,標記情況 infonum: { index: 1, // 0-無操作,1-頂了,2-踩了 dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, { userpic: "../../static/demo/userpic/12.jpg", username: "暱稱", isguanzhu: true, title: "這是標題", type: "video", titlepic: "../../static/demo/datapic/11.jpg", // 播放次數 playnum: "2w", long: "2:47", infonum: { index: 2, dingnum: 11, cainum: 11, }, commentnum: 10, sharenum: 10 }, ] }, { list:[] }, { list:[] }, { list:[] } ] } }, onLoad() { uni.getSystemInfo({ success:(res)=> { let height = res.windowHeight-uni.upx2px(100); this.swiperheight=height; } }); }, methods: { // tabBar點擊事件 tabtap(index) { this.tabIndex=index; }, // 滑動聯動切換導航欄 tabChange(e) { // console.log(JSON.stringify(e.detail)); this.tabIndex=e.detail.current; } } } </script> <style> </style>
-
swiper-tab-head文件
<template> <view class="uni-tab-bar"> <scroll-view scroll-x class="uni-swiper-tab"> <block v-for="(tab, index) in tabBars" :key="tab.id"> <view class="swiper-tab-list" :class="{'active': tabIndex==index}" @tap="tabtap(index)"> {{tab.name}} <view class="swiper-tab-line"></view> </view> </block> </scroll-view> </view> </template> <script> export default { props: { tabBars: Array, tabIndex: Number }, methods: { // tabBar點擊事件 tabtap(index) { this.$emit('tabtap', index); }, } } </script> <style> .swiper-tab-list { color: #969696; font-weight: bold; } .uni-swiper-tab { border-bottom: 1upx solid #EEEEEE; } .uni-tab-bar .active { color: #343434; } /* 被選中才出現下劃線 */ .active .swiper-tab-line { border-bottom: 6upx solid #FEDE33; width: 70upx; margin: 0 auto; border-top: 6upx solid #FEDE33; border-radius: 20upx; } </style>
-
其餘文件
其餘文件和之前的項目文件大致相同
【031】上拉加載組件開發
流程簡述
- 在
swiper
組件下的swiper-item
組件下的scroll-view
組件下增加一個view
組件,用於上拉加載 - 給
swiper
組件下的swiper-item
組件下的scroll-view
組件的scrolltolower
事件綁定一個自定義函數loadmore(index)
loadmore
函數中,先根據newslist[index].loadtext
的內容判斷加載狀態,如果不是待加載狀態,就不進行加載- 加載前將狀態調整至加載中,加載到的數據追加到
newslist[index].list
中,然後再把加載狀態調整至待加載 - 沒有更多數據的狀態以後再討論
核心代碼
<template>
<view>
<!-- ...... -->
<view class="uni-tab-bar">
<swiper class="swiper-box" :style="{height: swiperheight+'px'}" :current="tabIndex" @change="tabChange">
<swiper-item v-for="(items, index) in newslist" :key="index">
<scroll-view scroll-y class="list" @scrolltolower="loadmore(index)">
<!-- 圖文列表 -->
<block v-for="(item, index1) in items.list" :key="index1">
<index-list :item="item" :index="index1"></index-list>
</block>
<!-- 上拉加載 -->
<view class="load-more">{{items.loadtext}}</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</view>
</template>
<script>
import indexList from "../../components/index/index-list.vue";
import swiperTabHead from "../../components/index/swiper-tab-head.vue";
export default {
// 註冊組件
components: {
indexList,
swiperTabHead
},
data() {
return {
//......
newslist: [
{
loadtext: "上拉加載更多",
list:[
{
//......
},
{
//......
},
]
},
{
loadtext: "上拉加載更多",
list:[
{
//......
},
{
//......
},
{
//......
},
{
//......
},
]
},
{
loadtext: "上拉加載更多",
list:[
{
//......
},
{
//......
},
]
},
{
loadtext: "上拉加載更多",
list:[]
},
{
loadtext: "上拉加載更多",
list:[]
},
{
loadtext: "上拉加載更多",
list:[]
}
]
}
},
onLoad() {
//......
},
methods: {
//......
// 上拉加載狀態
loadmore(index) {
// 三種狀態
// this.newslist[index].loadtext='上拉加載更多';
// this.newslist[index].loadtext='加載中';
// this.newslist[index].loadtext='沒有更多數據了';
// 正在加載中或者沒有更多數據的時候不會向服務器發送請求
if (this.newslist[index].loadtext!=='上拉加載更多') {
return;
}
// 模擬請求數據
this.newslist[index].loadtext='加載中'; // 修改狀態
setTimeout(()=> {
// 獲取完成
let obj = {
// 用戶頭像
userpic: "../../static/demo/userpic/12.jpg",
// 用戶名
username: "暱稱",
// 關注情況
isguanzhu: false,
// 標題
title: "這是標題",
// 類型(img-圖文,video-視頻)
type: "img",
// 封面圖
titlepic: "../../static/demo/datapic/11.jpg",
// 贊、踩數,標記情況
infonum: {
index: 1, // 0-無操作,1-頂了,2-踩了
dingnum: 11,
cainum: 11,
},
commentnum: 10,
sharenum: 10
};
this.newslist[index].list.push(obj); // 加入數組
this.newslist[index].loadtext='上拉加載更多'; // 修改狀態
}, 1000);
},
//......
}
</script>
<style>
.load-more {
text-align: center;
color: #AAAAAA;
padding: 15upx 0;
}
</style>
效果圖
【032】封裝上拉加載組件
流程簡述
之前其實也描述過了封裝的一般流程 點這裏
這裏再來描述一下:
- 在components文件夾下新建common文件夾代表這個組件是多頁面通用的
- 在common文件夾下新建一個頁面(這裏就是load-more.vue)
- 將要封裝的部分(這裏就是
<view class="load-more">{{items.loadtext}}</view>
),剪切粘貼到剛纔新建的頁面中 - 將對應的樣式(這裏就是
.load-more
的樣式)剪切粘貼到剛纔新建的頁面中 - 將剛剛剪切的組件中要用到的數據在
props
中註冊,然後再把組件中使用的變量換成相應的變量名 - 在原來的頁面中通過
import 小駝峯名 from ".vue文件路徑"
- 在原來的頁面中通過
commponents
註冊相應的組件 - 在原來的頁面中原來的組件的位置,使用自定義的組件,如果要傳參數可以用
:變量名="具體變量"
的形式傳入
核心代碼
-
index.vue文件
<template> <view> <!-- ...... --> <view class="uni-tab-bar"> <!-- ...... --> <!-- ...... --> <!-- ...... --> <!-- 上拉加載 --> <load-more :loadtext="items.loadtext"></load-more> <!-- ...... --> <!-- ...... --> <!-- ...... --> </view> </view> </template> <script> //...... import loadMore from "../../components/common/load-more.vue"; export default { // 註冊組件 components: { //...... loadMore }, data() { //...... }, onLoad() { //...... }, methods: { // 上拉加載狀態 loadmore(index) { //...... }, </script> <style> </style>
-
load-more.vue文件
<template> <view class="load-more">{{loadtext}}</view> </template> <script> export default { props: { loadtext: String } } </script> <style scoped> .load-more { text-align: center; color: #AAAAAA; padding: 15upx 0; } </style>
【033】優化圖文列表組件
具體優化
- 點擊【關注】之後將不再出現【關注】按鈕(個人感覺這個可以優化爲已關注,方便快速取關)
- 點擊【頂】、【踩】之後,相應的數據會進行修改,相關的狀態會進行調整
- 點擊【文章標題】、【文章圖片】之後,會跳轉到相應的詳情頁(這裏先寫一個接口,只打印一下提示,以後再做具體實現)
組件代碼
(index-list組件)
<template>
<view class="index-list animated rollIn">
<view class="index-list1 u-f-ac u-f-jsb">
<view class="u-f-ac">
<image :src="item.userpic" mode="widthFix" lazy-load></image>
{{item.username}}
</view>
<!-- v-if會導致一點佈局異常,還是用v-show好一些 -->
<view class="u-f-ac" v-show="!item.isguanzhu" @tap="guanzhu">
<view class="icon iconfont icon-zengjia"></view>關注
</view>
</view>
<view class="index-list2" @tap="opendetail">{{item.title}}</view>
<view class="index-list3 u-f-ajc" @tap="opendetail">
<!-- 圖片 -->
<image :src="item.titlepic" mode="widthFix" lazy-load></image>
<!-- 視頻 -->
<template v-if="item.type=='video'">
<view class="index-list-play icon iconfont icon-bofang"></view>
<view class="index-list-playinfo">
{{item.playnum}}次播放 {{item.long}}
</view>
</template>
</view>
<view class="index-list4 u-f-ac u-f-jsb">
<view class="u-f-ac">
<view class="u-f-ac" :class="{'active':(item.infonum.index==1)}" @tap="caozuo('ding')">
<view class="icon iconfont icon-icon_xiaolian-mian u-f-ac"></view>
{{item.infonum.dingnum}}
</view>
<view class="u-f-ac" :class="{'active':(item.infonum.index==2)}" @tap="caozuo('cai')">
<view class="icon iconfont icon-kulian u-f-ac"></view>
{{item.infonum.cainum}}
</view>
</view>
<view class="u-f-ac">
<view class="u-f-ac">
<view class="icon iconfont icon-pinglun1 u-f-ac"></view>
{{item.commentnum}}
</view>
<view class="u-f-ac">
<view class="icon iconfont icon-zhuanfa u-f-ac"></view>
{{item.sharenum}}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
item: Object,
index: Number
},
methods: {
// 關注
guanzhu() {
this.item.isguanzhu = true;
uni.showToast({
title: "關注成功"
});
},
// 頂踩
caozuo(type) {
switch(type) {
case 'ding':
if (this.item.infonum.index === 1) { // 已經頂了(取消頂)
--this.item.infonum.dingnum;
this.item.infonum.index = 0;
} else if (this.item.infonum.index === 2) { // 已經踩了(取消踩,頂)
++this.item.infonum.dingnum;
--this.item.infonum.cainum;
this.item.infonum.index = 1;
} else { // 未操作(頂)
++this.item.infonum.dingnum;
this.item.infonum.index = 1;
}
break;
case 'cai':
if (this.item.infonum.index === 2) { // 已經踩了(取消踩)
--this.item.infonum.cainum;
this.item.infonum.index = 0;
} else if (this.item.infonum.index === 1) { // 已經頂了(取消頂,踩)
++this.item.infonum.cainum;
--this.item.infonum.dingnum;
this.item.infonum.index = 2;
} else { // 未操作(踩)
++this.item.infonum.cainum;
this.item.infonum.index = 2;
}
break;
}
},
// 進入詳情頁
opendetail() {
// 暫時留一個接口,先不做具體實現
console.log("進入詳情頁");
}
},
}
</script>
<style scoped>
.index-list {
padding: 20upx;
border-bottom: 1upx solid #EEEEEE;
}
.index-list1>view:first-child {
color: #999999;
}
.index-list1>view:first-child image {
width: 90upx;
height: 90upx;
border-radius: 50%;
margin-right: 10upx;
}
.index-list1>view:last-child {
background-color: #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 {
padding: 15upx 0;
}
.index-list4>view {
color: #999999;
}
.index-list4>view>view:first-child, .index-list4>view>view>view {
margin-right: 10upx;
}
.index-list-play {
position: absolute;
font-size: 140upx;
color: #FFFFFF;
}
.index-list-playinfo {
position: absolute;
background-color: rgba(51, 51, 51, 0.62);
color: #FFFFFF;
bottom: 8upx;
right: 8upx;
border-radius: 40upx;
font-size: 22upx;
padding: 0 12upx;
}
.index-list4 .active, .index-list4 .active > view{
color: #C5F61C;
}
</style>
【034】封裝無數據默認組件
具體優化
對於無數據的頁面,優化了展示的效果,不再是幾乎一片空白,並將組件進行了封裝。
核心代碼
-
index.vue文件
<template> <view> <swiper-tab-head :tabBars="tabBars" :tabIndex="tabIndex" @tabtap="tabtap"></swiper-tab-head> <view class="uni-tab-bar"> <!-- ...... --> <!-- ...... --> <!-- ...... --> <template v-if="items.list.length > 0"> <!-- 圖文列表 --> <block v-for="(item, index1) in items.list" :key="index1"> <index-list :item="item" :index="index1"></index-list> </block> <!-- 上拉加載 --> <load-more :loadtext="items.loadtext"></load-more> </template> <template v-else> <!-- 無內容默認 --> <nothing></nothing> </template> <!-- ...... --> <!-- ...... --> <!-- ...... --> </view> </view> </template> <script> //...... import nothing from "../../components/common/nothing.vue"; export default { // 註冊組件 components: { //...... nothing }, data() { return { //...... } }, onLoad() { //...... }, methods: { //...... } } </script> <style> </style>
-
nothing.vue文件
<template> <view class="nothing u-f-ajc animated fadeIn"> <image src="../../static/common/nothing.png" mode="widthFix"></image> </view> </template> <script> </script> <style> .nothing { position: absolute; left: 0; right: 0; top: 0; bottom: 0; } .nothing > image { width: 50%; } </style>