uni-app+vue3會遇到哪些問題

来源:https://www.cnblogs.com/weizwz/p/18002189
-Advertisement-
Play Games

已經用 uni-app+vue3+ts 開發了一段時間,記錄一下日常遇見的問題和解決辦法 uni-app 中的單端代碼 uni-app 是支持多端,如果你想讓你的代碼,只在部分平臺使用,那麼就需要用的它的單端處理語法 //#ifdef 和 //#ifndef 等。 1. //#ifdef xxx 只 ...


已經用 uni-app+vue3+ts 開發了一段時間,記錄一下日常遇見的問題和解決辦法

uni-app 中的單端代碼

uni-app 是支持多端,如果你想讓你的代碼,只在部分平臺使用,那麼就需要用的它的單端處理語法 //#ifdef//#ifndef 等。

1. //#ifdef xxx 只在xxx平臺生效

//#ifdef MP-WEIXIN
menuButtonInfo = '微信'
//#endif

2. //#ifndef xxx 除了xxx平臺,其他都生效

//#ifndef MP-WEIXIN
menuButtonInfo = '只要不是微信,其他都可以'
//#endif

安全邊距

1. 異形屏

因為有異形手機屏的存在,最頂部有攝像頭,最下麵有導航條,為了避免界面內容出現在這些位置,所以每次在界面初始要設置安全邊距。

<script setup lang="ts">
// 獲取屏幕邊界到安全區域距離
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>

<template>
  <view class="specification-panel flex-column" :style="{ paddingTop: safeAreaInsets.top + 'px' }">
    <!-- 底部導航 -->
    <view class="bottomNav" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }"></view>
  </view>
</template>

2. 微信膠囊

由於微信小程式右上角有微信膠囊,很多時候我們為了保持界面整齊,需要獲取微信膠囊的位置,來讓我們得元素和它對齊。

// 微信膠囊一定處於安全位置,所以有微信膠囊就拿膠囊的位置,否則再去獲取安全邊距
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 里配置,代碼如下:

// 組件自動導入
"easycom": {
  // 開啟自動掃描
  "autoscan": true,
  "custom": {
    // 使用了uni-ui 規則如下配置
    "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
    // 自定義組件,需要使用正則表達式
    "^Weiz(.*)": "@/components/Weiz$1/index.vue"
  }
}

使用的時候,直接在界面使用即可,無需再導入。

<WeizCarousel class="categories-banner" size="small" />

獲取DOM信息

有的時候我們需要去拿到界面元素的相關信息,然後進行一些處理,uni-app 提供了相關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>

是的你沒看錯,不需要給元素設置 ref

url 傳參

url 跳轉界面有兩種方式,一種是使用 navigator 標簽,一種是使用 uni.navigateTo 方法。
需要註意的是url有長度限制,太長的字元串會傳遞失敗,而且參數中出現空格等特殊字元時需要對參數進行編碼,如使用 encodeURIComponent 等。

1. 傳遞參數

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>

2. 接受參數

pages/test 界面

onLoad: function(option) {
  console.log(option.id, option.name)
  // 如果傳遞的是經過編碼的參數
  const item = JSON.parse(decodeURIComponent(option.item));
}

父子組件通信

簡單參數

子組件:

<script setup lang="ts">
  // 使用 defineProps 來接受參數,非必要參數使用 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>

父組件:

// 由於是全局組件,所以無需再引入,如果不是全局組件,需要單獨引入 <WeizTitle title="詳情" />

複雜參數

如果參數比較複雜,可以直接用 TS 去定義類型,下麵舉例:

子組件:

<script setup lang="ts">
  // 引入參數類型
  import type { CategoryItem } from '@/types/api'

  // 定義 props 接收數據
  defineProps<{
    list: CategoryItem[]
  }>()
</script>

父組件:

<script setup lang="ts">
  import { ref } from 'vue'
  import { onLoad } from '@dcloudio/uni-app'
  // 引入數據類型
  import type { CategoryItem } from '@/types/api'
  // 引入介面
  import { getCategoryIndexAPI } from '@/api/category'

  // 定義響應式數據
  const categoryList = ref<CategoryItem[]>([])
  // 獲取數據方法
  const getCategoryList = async () => {
    const res = await getCategoryIndexAPI()
    // 拿到數據賦值
    categoryList.value = res.result
  }
  // 調用方法
  onLoad(() => {
    getCategoryList()
  })
</script>

<template>
  <WeizCategory :list="categoryList" @refresh="getCategoryList" />
</template>

父調子方法

父調子需要子組件通過 defineExpose 暴露方法給父組件,然後父組件拿到子組件實例再去調用子組件方法。

1. 子組件暴露方法

// 定義方法
const getCurrentSpec = () => {
  return currentSpec.value
}
// 暴露方法給父組件
defineExpose({
  getCurrentSpec
})

2. 父組件拿到實例調用

可參考章節 TS 相關 - 定義組件實例類型,調用子組件需要先拿到子組件的實例,拿到實例後直接調用即可。

// 拿到子組件實例 WeizCategoryInstance 需要我們去 ts 里定義
const weizCategory = ref<WeizCategoryInstance>()
// 調用子組件實例的方法
weizCategory.value.getCurrentSpec()

子調父方法

子調父方法,需要父組件去給子組件添加自定義事件,然後子組件通過 defineEmits 去觸發。

1. 父組件聲明自定義事件

<script setup lang="ts">
  const handleUpdate = (value: string) => {
    console.log('拿到子組件的傳值,並且調用了父組件', value)
  }
</script>

<template>
  <WeizCategory :list="categoryList" @update="handleUpdate" />
</template>

2. 子組件使用 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">觸發父組件方法</button>
  </div>
</template>

TS 相關

定義組件實例類型

定義組件實例類型文件 xxx.d.ts

// 導入組件
import WeizCardList from '@/components/WeizCardList/index.vue'
// 什麼全局類型
declare module 'vue' {
  export interface GlobalComponents {
    WeizCardList: typeof WeizCardList
  }
}
// 導出組件實例類型, 需要用到 InstanceType
export type CardListInstance = InstanceType<typeof WeizCardList>

在 vue 頁面里使用:

// 導入組件實例類型
import type { CardListInstance } from '@/types/components'
// 拿到組件實例
const cardList = ref<CardListInstance>()
// 調用組件實例的方法
cardList.value?.resetData()

文章作者:唯之為之

文章出處:https://www.cnblogs.com/weizwz/p/18002189

版權聲明:本博客所有文章除特別聲明外,均採用 「CC BY-NC-SA 4.0 DEED」 國際許可協議,轉載請註明出處!

內容粗淺,如有錯誤,歡迎大佬批評指正


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 本文作者:佳嵐 The more your tests resemble the way your software is used, the more confide ...
  • 聽我說 從 條件渲染 那一篇,我學習到瞭如何用Vue對dom節點根據條件顯示 但單單有條件還不夠啊,有時候數據是一大坨一大坨的數據,如果Vue不提供咱要麼使用“v-html” 要麼就沒辦法實現 v-html又感覺太low了,Vue提供了另外的指令更好的實現,那便是:列表渲染 列表渲染:v-for 簡 ...
  • 與其說是年終總結,更像是一場回顧,看看這一年 Fantastic-admin 都做了哪些與眾不同的功能,也給大家提供一些創造思路。 ...
  • 回顧 大致掌握了上一節的 插值語法 我已經可以把想要的數據顯示到頁面上,並且僅需要修改變數,頁面就會跟著實時改變 但如果對於已經熟悉前端的人來說,單單有數據還是不太行,還需要css對數據進行樣式的修飾,讓頁面更加好看 所本篇將記錄記錄 Class 與 Style 綁定 的學習 總所周知,想要給DOM ...
  • 回顧 大致掌握了上一節的 插值語法 我已經可以把想要的數據顯示到頁面上,並且僅需要修改變數,頁面就會跟著實時改變 但如果對於已經熟悉前端的人來說,單單有數據還是不太行,還需要css對數據進行樣式的修飾,讓頁面更加好看 所本篇將記錄記錄 Class 與 Style 綁定 的學習 總所周知,想要給DOM ...
  • `async` 和 `defer` 是兩種不同的JavaScript特性,它們的主要區別在於它們的執行順序和時間點。 `async` 意味著函數或代碼塊會被非同步執行。當瀏覽器遇到帶有 `async` 屬性的資源時,它會立即開始下載該資源,同時繼續載入頁面。這樣可以避免由於同步執行而導致的頁面載入阻 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 如何實現一個雨滴落下效果 前言 下雨天坐在車窗前,看著雨滴順著車窗漸漸落下,這一唯美的場景,忍不住想記錄下來。最近在糾結電腦壁紙時,無意間看到有類似的場景,可以將自己喜歡的壁紙加上這種效果。作為多年切圖仔,不由地想到了用css動畫應該可以 ...
  • 描述 這是一個用於 Tampermonkey 或其他支持用戶腳本的瀏覽器擴展的油猴腳本。 看到論壇經常有小伙伴們需要下載某創力文檔-某人文庫一些免費文檔,但是相關網站瀏覽體驗不好各種廣告,各種登錄驗證,需要很多步驟才能下載文檔,該腳本就是為瞭解決您的煩惱而誕生,儘可能做到自動化。 安裝 安裝 Tam ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...