注:前言、目錄見 https://god-excious.blog.csdn.net/article/details/105312456
文章目錄
- 【024】page-json配置
- 【025】圖文、視訊和清單樣式(上)
-
- 圖檔引入
- 設計細節
- 整體代碼
- 【026】圖文、視訊和清單樣式(下)
-
- 設計細節
- 整體代碼
- 【027】封裝清單樣式元件
-
- 資料存儲
- 狀态(關注、贊、踩)辨別
- 封裝元件
- 【028】滾動tab導航開發
-
- 操作步驟
- 其他注意點
- 整體代碼
- 【029】滾動tab導航開發(下)
-
- 注意點
- 詳細代碼
- 【030】封裝滾動tab導航元件
-
- 步驟總結
- 詳細代碼
- 【031】上拉加載元件開發
-
- 流程簡述
- 核心代碼
- 效果圖
- 【032】封裝上拉加載元件
-
- 流程簡述
- 核心代碼
- 【033】優化圖文清單元件
-
- 具體優化
- 元件代碼
- 【034】封裝無資料預設元件
-
- 具體優化
- 核心代碼
- 效果圖
【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
對應了圖示項目中的iconfont.ttf檔案的路徑,一般将其引入到uni-app項目中的fontSrc
檔案夾下/static/font
-
中提示文字buttons
,填寫的内容為圖示項目中demo_index.html打開後Unicode下,該圖示的編号。例如:某圖示在Unicode中編号為text
,就應該填寫
,以此類推。"text": "\ue601"
【025】圖文、視訊和清單樣式(上)
圖檔引入
圖檔元件——官方文檔 https://uniapp.dcloud.io/component/image
格式大緻如下
屬性 | 功能 |
---|---|
| 圖檔路徑 |
| 圖檔裁剪、縮放的模式( 代表寬度不變,高度自動變化,保持原圖寬高比不變) |
| 圖檔懶加載 |
設計細節
在設計時,需要注意以下一些細節
- 首先按照設計圖,對某個區域可以分成若幹行,我們把這些行都做成
的class="網頁名-list-i"
元件,然後将它們放到一個view
的class="網頁名-list"
元件中view
- 像是頭像、昵稱這一組,或者是**+icon、關注這一組,都是水準方向上垂直居中排列的,可以把文字(直接寫到父标簽下,不一定要建立标簽)、圖像放到一個
元件下,然後以flex布局(預設主軸方向即可)設定交叉軸(縱向)居中——view
**,即可在同一行上垂直居中排版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
來辨別,值為
代表“未操作”,值為
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
前,将元件檔案引入進來,形如:
注:将中劃線命名改寫為小駝峰命名
- 在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
值(先設定為0代表初始選中第一個),然後在tabIndex
中設定一個處理函數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
注意點
- 建立數組資料
,裡面是6個newslist
對象,分别與卷軸框上的6個種類對應list
- 為了能夠讓能容橫向滾動,和上一節類似地在
的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()
裡,然後把結果傳入這個變量值中。由于在uin.css檔案中,uni.getSystemInfo
、.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檔案的
中定義好要使用到的變量,在index.vue檔案中用自定義的props
元件将導航欄引入,然後以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>