交友網(wǎng)站開(kāi)發(fā)的意義網(wǎng)站推廣的策略
為什么需要封裝自定義導(dǎo)航
- 首先如果開(kāi)發(fā)的是微信小程序,那么在安卓環(huán)境下導(dǎo)航欄標(biāo)題是
默認(rèn)靠左對(duì)齊
的(雖然你在微信開(kāi)發(fā)者工具上看到的依舊是居中展示),而在ios環(huán)境則是居中展示的。 - 很多時(shí)候我們需要對(duì)整個(gè)項(xiàng)目有一個(gè)
主題色或者公共的樣式配置
,封裝一個(gè)公共的自定義導(dǎo)航欄更易于實(shí)現(xiàn)與管理。 系統(tǒng)導(dǎo)航欄高度
根據(jù)機(jī)型會(huì)發(fā)生變化,大部分是44px,但是有時(shí)候也會(huì)是40px等高度,如果你需要針對(duì)導(dǎo)航欄和狀態(tài)欄高度對(duì)頁(yè)面做一些定制需求那會(huì)顯得比較困難。(網(wǎng)上有一些根據(jù)膠囊按鈕獲取導(dǎo)航欄高度的方法實(shí)測(cè)后發(fā)現(xiàn)并不精準(zhǔn)。)
當(dāng)然原生導(dǎo)航也并不是一無(wú)是處的。原生導(dǎo)航的體驗(yàn)更好,渲染新頁(yè)面時(shí),原生導(dǎo)航欄的渲染無(wú)需等待新頁(yè)面dom加載,可以在新頁(yè)面進(jìn)入動(dòng)畫(huà)開(kāi)始時(shí)就渲染。原生導(dǎo)航還可以避免滾動(dòng)條通頂,并方便的控制原生下拉刷新。
封裝思路
這里我們借助uniapp官方提供的uni-nav-bar進(jìn)行封裝。(vue3 + ts + setup)
- 首先,我們希望可以自動(dòng)獲取每個(gè)頁(yè)面的標(biāo)題,并不是每次使用自定義組件再去設(shè)置,我們置頂
page.json
里面包含了我們所有的頁(yè)面的標(biāo)題,所以我們直接導(dǎo)入該文件,使用currentPage獲取當(dāng)前頁(yè)面的路由,然后匹配page.json文件里面的page或者subPackages路由,需要注意的是subPackages里面的路由需要自己收到拼裝。const { title, ...$attrs } = useAttrs() const defaultTitle = '我是默認(rèn)標(biāo)題' // 通過(guò)page.json文件里面的pages與subPackages數(shù)組自動(dòng)獲取標(biāo)題欄 const getCurrentPageTitle = () => {// 有傳入的標(biāo)題直接使用傳入的標(biāo)題if (title) {return title}const { route } = currentPage()const page = pagesjson.pages.find((item) => item.path === route)if (page) {return page.style?.navigationBarTitleText || defaultTitle}for (const subPackage of pagesjson.subPackages) {const subPage = subPackage.pages?.find((item) => route === `${subPackage.root}/${item.path}`)if (subPage) {return subPage.style?.navigationBarTitleText || defaultTitle}} }
- 然后我們使用
getCurrentInstance
和``createSelectorQuery定義一個(gè)方法返回自定義導(dǎo)航欄的高度,便于我們需要的時(shí)候使用。const pageInstace = getCurrentInstance() const emits = defineEmits(['getHeight']) onMounted(() => {const query = uni.createSelectorQuery().in(pageInstace?.proxy)query.select('.uniNavBar').boundingClientRect((data: any) => {emits('getHeight', data.height + 'px')}).exec() })
- 最后我們還需使用
$attrs
對(duì)組件的屬性方法進(jìn)行穿透,這在我們對(duì)組件進(jìn)行二次封裝的時(shí)候應(yīng)該都是必須要做的操作。
完整代碼
<template><uni-nav-barclass="uniNavBar"v-bind="$attrs":border="border":statusBar="statusBar":fixed="fixed":leftIcon="leftIcon":title="getCurrentPageTitle()"@clickLeft="clickLeft"></uni-nav-bar>
</template><script lang="ts" setup>
import { onMounted, getCurrentInstance } from 'vue'
import { useAttrs } from 'vue'
import pagesjson from '@/pages.json'
import { currentPage } from '@/utils/tools'interface Props {border?: booleanstatusBar?: booleanfixed?: booleanleftIcon?: string
}const props = withDefaults(defineProps<Props>(), {border: false,statusBar: true,fixed: true,leftIcon: 'left',
})const { title, ...$attrs } = useAttrs()
const pageInstace = getCurrentInstance()
const emits = defineEmits(['getHeight'])
onMounted(() => {const query = uni.createSelectorQuery().in(pageInstace?.proxy)query.select('.uniNavBar').boundingClientRect((data: any) => {emits('getHeight', data.height + 'px')}).exec()
})const defaultTitle = '我是默認(rèn)標(biāo)題'
// 通過(guò)page.json文件里面的pages與subPackages數(shù)組自動(dòng)獲取標(biāo)題欄
const getCurrentPageTitle = () => {// 有傳入的標(biāo)題直接使用傳入的標(biāo)題if (title) {return title}const { route } = currentPage()const page = pagesjson.pages.find((item) => item.path === route)if (page) {return page.style?.navigationBarTitleText || defaultTitle}for (const subPackage of pagesjson.subPackages) {const subPage = subPackage.pages?.find((item) => route === `${subPackage.root}/${item.path}`)if (subPage) {return subPage.style?.navigationBarTitleText || defaultTitle}}
}// navbar返回按鈕事件
const clickLeft = () => {uni.navigateBack()
}
</script>