uni-app 中的單端代碼
uni-app 是支持多端,如果你想讓你的代碼荣刑,只在部分平臺使用合溺,那么就需要用的它的單端處理語法 //#ifdef
和//#ifndef
等。
-
//#ifdef xxx
只在xxx平臺生效
//#ifdef MP-WEIXIN
menuButtonInfo = '微信'
//#endif
-
//#ifndef xxx
除了xxx平臺则果,其他都生效
//#ifndef MP-WEIXIN
menuButtonInfo = '只要不是微信,其他都可以'
//#endif
安全邊距
- 異形屏
因?yàn)橛挟愋问謾C(jī)屏的存在顽决,最頂部有攝像頭短条,最下面有導(dǎo)航條,為了避免界面內(nèi)容出現(xiàn)在這些位置才菠,所以每次在界面初始要設(shè)置安全邊距茸时。
<script setup lang="ts">
// 獲取屏幕邊界到安全區(qū)域距離
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>
<template>
<view class="specification-panel flex-column" :style="{ paddingTop: safeAreaInsets.top + 'px' }">
<!-- 底部導(dǎo)航 -->
<view class="bottomNav" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }"></view>
</view>
</template>
- 微信膠囊
由于微信小程序右上角有微信膠囊,很多時候我們?yōu)榱吮3纸缑嬲R赋访,需要獲取微信膠囊的位置可都,來讓我們得元素和它對齊。
// 微信膠囊一定處于安全位置蚓耽,所以有微信膠囊就拿膠囊的位置渠牲,否則再去獲取安全邊距
export const safeTop = () => {
const { safeAreaInsets } = uni.getWindowInfo()
// 獲取膠囊信息 https://uniapp.dcloud.net.cn/api/ui/menuButton.html#getmenubuttonboundingclientrect
let menuButtonInfo = { top: 0 }
//#ifdef MP-WEIXIN
menuButtonInfo = uni.getMenuButtonBoundingClientRect()
//#endif
const top = menuButtonInfo.top || safeAreaInsets?.top
return {
top
}
}
全局組件
全局組件 目前只能在 src/pages.json
里配置,代碼如下:
// 組件自動導(dǎo)入
"easycom": {
// 開啟自動掃描
"autoscan": true,
"custom": {
// 使用了uni-ui 規(guī)則如下配置
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
// 自定義組件步悠,需要使用正則表達(dá)式
"^Weiz(.*)": "@/components/Weiz$1/index.vue"
}
}
使用的時候签杈,直接在界面使用即可,無需再導(dǎo)入。
<WeizCarousel class="categories-banner" size="small" />
獲取DOM信息
有的時候我們需要去拿到界面元素的相關(guān)信息答姥,然后進(jìn)行一些處理铣除,uni-app 提供了相關(guān)API
,但需要和 vue3
配合使用
<script setup lang="ts">
import { getCurrentInstance } from 'vue'
const instance = getCurrentInstance()
const getNodeInfo = () => {
const query = uni.createSelectorQuery().in(instance)
query
.select('.similar') // 獲取界面元素鹦付,也可以傳id
.boundingClientRect((data) => {
const nodeInfo: UniApp.NodeInfo = data as UniApp.NodeInfo
console.log(nodeInfo)
})
.exec()
}
</script>
是的你沒看錯尚粘,不需要給元素設(shè)置ref
url 傳參
url 跳轉(zhuǎn)界面有兩種方式,一種是使用 navigator
標(biāo)簽敲长,一種是使用 uni.navigateTo
方法郎嫁。
需要注意的是url有長度限制,太長的字符串會傳遞失敗祈噪,而且參數(shù)中出現(xiàn)空格等特殊字符時需要對參數(shù)進(jìn)行編碼泽铛,如使用 encodeURIComponent
等。
- 傳遞參數(shù)
uni.navigateTo({
url: 'pages/test?id=1&name=uniapp'
});
或者
<script setup lang="ts">
const item = ref({ id: 1, name: 'uniapp' })
</script>
<template>
<navigator :url="'/pages/test/test?item='+ encodeURIComponent(JSON.stringify(item))"></navigator>
</template>
- 接受參數(shù)
在pages/test
界面
onLoad: function(option) {
console.log(option.id, option.name)
// 如果傳遞的是經(jīng)過編碼的參數(shù)
const item = JSON.parse(decodeURIComponent(option.item));
}
父子組件通信
簡單參數(shù)
子組件:
<script setup lang="ts">
// 使用 defineProps 來接受參數(shù)钳降,非必要參數(shù)使用 xxx? 的形式
defineProps<{
title: string
subTitle?: string
}>()
</script>
<template>
<view class="weiz-title">
<view class="title">{{ title }}</view>
<view class="sub-title">{{ subTitle }}</view>
</view>
</template>
父組件:
// 由于是全局組件厚宰,所以無需再引入腌巾,如果不是全局組件遂填,需要單獨(dú)引入 <WeizTitle title="詳情" />
復(fù)雜參數(shù)
如果參數(shù)比較復(fù)雜,可以直接用 TS 去定義類型澈蝙,下面舉例:
子組件:
<script setup lang="ts">
// 引入?yún)?shù)類型
import type { CategoryItem } from '@/types/api'
// 定義 props 接收數(shù)據(jù)
defineProps<{
list: CategoryItem[]
}>()
</script>
父組件:
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
// 引入數(shù)據(jù)類型
import type { CategoryItem } from '@/types/api'
// 引入接口
import { getCategoryIndexAPI } from '@/api/category'
// 定義響應(yīng)式數(shù)據(jù)
const categoryList = ref<CategoryItem[]>([])
// 獲取數(shù)據(jù)方法
const getCategoryList = async () => {
const res = await getCategoryIndexAPI()
// 拿到數(shù)據(jù)賦值
categoryList.value = res.result
}
// 調(diào)用方法
onLoad(() => {
getCategoryList()
})
</script>
<template>
<WeizCategory :list="categoryList" @refresh="getCategoryList" />
</template>
父調(diào)子方法
父調(diào)子需要子組件通過defineExpose
暴露方法給父組件吓坚,然后父組件拿到子組件實(shí)例再去調(diào)用子組件方法。
- 子組件暴露方法
// 定義方法
const getCurrentSpec = () => {
return currentSpec.value
}
// 暴露方法給父組件
defineExpose({
getCurrentSpec
})
- 父組件拿到實(shí)例調(diào)用
可參考章節(jié)TS
相關(guān) - 定義組件實(shí)例類型灯荧,調(diào)用子組件需要先拿到子組件的實(shí)例礁击,拿到實(shí)例后直接調(diào)用即可。
// 拿到子組件實(shí)例 WeizCategoryInstance 需要我們?nèi)?ts 里定義
const weizCategory = ref<WeizCategoryInstance>()
// 調(diào)用子組件實(shí)例的方法
weizCategory.value.getCurrentSpec()
子調(diào)父方法
子調(diào)父方法逗载,需要父組件去給子組件添加自定義事件哆窿,然后子組件通過 defineEmits
去觸發(fā)。
- 父組件聲明自定義事件
<script setup lang="ts">
const handleUpdate = (value: string) => {
console.log('拿到子組件的傳值厉斟,并且調(diào)用了父組件', value)
}
</script>
<template>
<WeizCategory :list="categoryList" @update="handleUpdate" />
</template>
- 子組件使用
defineEmits
<script setup lang="ts">
import { ref, defineEmits } from 'vue'
const message = ref('子組件的值')
const popupEmit = defineEmits(['update'])
function sendMessage() {
popupEmit('update', message.value)
}
</script>
<template>
<div>
<button @click="sendMessage">觸發(fā)父組件方法</button>
</div>
</template>
TS 相關(guān)
定義組件實(shí)例類型
定義組件實(shí)例類型文件xxx.d.ts
// 導(dǎo)入組件
import WeizCardList from '@/components/WeizCardList/index.vue'
// 什么全局類型
declare module 'vue' {
export interface GlobalComponents {
WeizCardList: typeof WeizCardList
}
}
// 導(dǎo)出組件實(shí)例類型, 需要用到 InstanceType
export type CardListInstance = InstanceType<typeof WeizCardList>
在 vue 頁面里使用:
// 導(dǎo)入組件實(shí)例類型
import type { CardListInstance } from '@/types/components'
// 拿到組件實(shí)例
const cardList = ref<CardListInstance>()
// 調(diào)用組件實(shí)例的方法
cardList.value?.resetData()