文章目錄
- 簡介
- 一、自定義背景圖布局
- 1.1 效果預覽
- 1.2 實現思路
- 1.3 custom-page 組件全量代碼
- 1.4 頁面使用
- 二、普通頁面布局
- 2.1 效果預覽
- 2.2 實現思路
- 2.3 公共樣式部分
- 2.4 頁面使用
- 三、分頁表單頁面布局
- 3.1 效果預覽
- 3.2 實現思路
- 3.3 頁面代碼
簡介
開發工具:VsCode
技術棧:vue3 + Ts + uni-app + unibest + Wot Design Uni
簡介:圖文結合,十分鐘帶你搞定微信小程序常見頁面布局
一、自定義背景圖布局
1.1 效果預覽
1.2 實現思路
- 因為小程序原生頂部導航欄只有白色、黑色兩種背景色,所以使用自定義導航欄
- 提高代碼復用率,采用組件封裝得形式。代碼見 ——》步驟 1.3 custom-page 組件全量代碼
- wot design uni 組件庫的 wd-navbar 組件剛好符合需求
- 關鍵:wd-navbar 組件有一個屬性(placeholder:固定在頂部時,在標簽位置生成一個等高的占位元素),解決了頂部高度計算的問題
- 具體文檔所在位置如下圖
1.3 custom-page 組件全量代碼
<template><view class="h-full w-full bg-[#F5F5F5] custom-page-container"><!-- 自定義頂部背景圖(可選) --><image src="@/static/images/home/bg.png" class="custom-page-bg" /><!-- 頁面內容 --><view class="custom-page-main"><!-- 自定義頂部--導航欄 --><wd-navbar:title="title"safeAreaInsetTopplaceholder:left-arrow="showBack"@click-left="handleClickLeft"custom-class="wd-navbar-custom"></wd-navbar><!-- 頁面主體--功能版塊 --><view class="custom-page-content"><!-- 頁面主體內容--插槽 --><view :class="showPagePadding ? 'page-content-p' : ''" class="custom-slot-content"><slot name="content"></slot></view><!-- 頁面底部按鈕--插槽 --><slot name="footer"></slot></view></view></view>
</template><script lang="ts" setup>
defineProps({// navbar標題title: {type: String,default: '',required: true,},// 是否顯示返回按鈕showBack: {type: Boolean,default: true,},// 頁面主體是否需要展示左右邊距showPagePadding: {type: Boolean,default: true,},
})
/*** 返回上一級*/
function handleClickLeft() {uni.navigateBack()
}
</script><style lang="scss" scoped>
.custom-page-container {position: relative;.custom-page-bg {position: absolute;top: 0;left: 0;z-index: 1;width: 100%;height: 668rpx;}.custom-page-main {position: absolute;top: 0;left: 0;z-index: 2;display: flex;flex-direction: column;width: 100%;height: 100%;overflow: hidden;.custom-page-content {display: flex;flex: 1;flex-direction: column;justify-content: space-between;max-height: 100%;overflow: hidden;.custom-slot-content {flex: 1;overflow: hidden;}}}
}
</style>
1.4 頁面使用
二、普通頁面布局
2.1 效果預覽
2.2 實現思路
- 整個頁面 flex 布局,中間部分 flex:1。
- 抽離公共布局樣式,不采用組件封裝方式,減小心智負擔
2.3 公共樣式部分
// /src/style/public.scss
// 公共頁面布局樣式--簡易版
.custom-page-simple {display: flex;flex-direction: column;width: 100%;height: 100vh;overflow: hidden;background-color: $open-bg-grey;.page-main {flex: 1;padding: 28rpx;margin: 28rpx;overflow: auto;background: $open-bg-primary;border-radius: $open-border-radius;}.page-footer {width: 100%;height: 130rpx;padding: 30rpx 28rpx;background-color: $open-text-color-inverse;box-shadow: 0rpx 0rpx 27.78rpx 0rpx rgba(9, 197, 133, 0.25);}
}
2.4 頁面使用
三、分頁表單頁面布局
3.1 效果預覽
3.2 實現思路
- 使用 z-paging 組件
- z-paging 官方文檔:z-paging官方文檔
- 組件安裝方式參考官方,沒有比這個更清晰的了
3.3 頁面代碼
<route lang="json5" type="page">
{layout: 'default',style: {navigationBarTitleText: '公告列表',},custom: true,
}
</route><template><z-pagingref="pagingRef"v-model="noticeList":paging-style="{ backgroundColor: '#fff' }":default-page-size="pageQuery.size"@query="queryList"><!-- 頂部搜索欄 --><template #top><wd-searchref="searchRef"v-model="pageQuery.someText"placeholder="請輸入搜索內容"placeholder-lefthide-cancel:maxlength="50"@change="handleSearchChangeDebounce"/></template><!-- 通告列表 --><div class="notice-list"><div class="notice-item" v-for="(item, index) in noticeList" :key="index"><!-- 標題 --><div class="notice-title">{{ item.title }}</div><!-- 內容 --><span v-if="!item.details || item.details.length < 58" class="notice-content">{{ item.details || '--' }}</span><wd-collapsev-elsev-model="item.showMoreContent"viewmorecustom-class="notice-content":line-num="2">{{ item.details || '--' }}</wd-collapse><!-- 發布時間 --><div class="notice-publish-time">{{ '發布時間:' + parseTime(item.updateTime, '{y}-{m}-{d} {h}:{i}') }}</div><!-- 圖片、視頻列表 --><div class="notice-file flex items-center"><divclass="notice-file-item"v-for="(file, fileIndex) in item.pictureUrlList":key="fileIndex"><wd-img:width="100":height="75":src="file":enable-preview="true"mode="aspectFill"/></div><divclass="notice-file-item"v-for="(file, fileIndex) in item.videoUrlList":key="fileIndex"><video :src="file" :id="`video${fileIndex}`" controls></video></div></div></div></div></z-paging>
</template><script lang="ts" setup>
import { debounce } from 'lodash-es'
import { useUserStore } from '@/store'
import { fetchNoticePageList } from '@/api/fitness-test/notice'
import { INoticePageQuery, INoticePageResponseListItem } from '@/api/fitness-test/notice/types'
import { parseTime } from '@/utils/business'const userStore = useUserStore()// 通知公列表--數據
const noticeList = ref<INoticePageResponseListItem[]>([])/** ================================ 分頁請求 start ================================== */
// z-paging 組件實例
const pagingRef = ref<ZPagingRef>()// 分頁查詢參數
const pageQuery = reactive<Omit<INoticePageQuery, 'schoolId'>>({current: 1,size: 6,someText: '',
})// 搜索框實例
const searchRef = ref()
// 數據總數
const total = ref(0)// 學校id
const schoolId = computed(() => userStore.getUserInfo.schoolId)/*** 分頁查詢* @param pageNo 當前頁* @param pageSize 每頁條數*/
function queryList(pageNo: number, pageSize: number) {// console.log('queryList', pageNo, pageSize)fetchNoticePageList({current: pageNo,size: pageSize,schoolId: schoolId.value,someText: pageQuery.someText,}).then((res) => {const { count, data, size, current } = res.data// 賦值給totaltotal.value = count// 賦值給pageQuery.sizepageQuery.size = size// 賦值給pageQuery.currentpageQuery.current = currentconst resultList = (data || []).map((item) => {return {...item,showMoreContent: false,pictureUrlList: item.pictureUrlList || [],videoUrlList: item.videoUrlList || [],}})// 將請求的結果數組傳遞給z-paging// 參考文檔:https://z-paging.zxlee.cn/api/methods/main.html#%E6%95%B0%E6%8D%AE%E5%88%B7%E6%96%B0-%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95pagingRef.value?.completeByTotal([...resultList], total.value)}).catch((err) => {console.log(err)pagingRef.value?.complete(false)})
}// 為提升性能,避免高頻觸發接口,搜索框改變時觸發用 防抖 函數
const handleSearchChangeDebounce = debounce(handleSearchChange, 500)/*** 搜索框改變時觸發* @param value 搜索框的值*/
function handleSearchChange(ipt: { value: string }) {// console.log('handleSearchChange', ipt)// 重新請求pagingRef.value?.reload()
}
/** ================================ 分頁請求 end ================================== */
</script>