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
  • 在C#中使用SQL Server實現事務的ACID(原子性、一致性、隔離性、持久性)屬性和使用資料庫鎖(悲觀鎖和樂觀鎖)時,你可以通過ADO.NET的SqlConnection和SqlTransaction類來實現。下麵是一些示例和概念說明。 實現ACID事務 ACID屬性是事務處理的四個基本特征, ...
  • 我們在《SqlSugar開發框架》中,Winform界面開發部分往往也用到了自定義的用戶控制項,對應一些特殊的界面或者常用到的一些局部界面內容,我們可以使用自定義的用戶控制項來提高界面的統一性,同時也增強了使用的便利性。如我們Winform界面中用到的分頁控制項、附件顯示內容、以及一些公司、部門、菜單的下... ...
  • 在本篇教程中,我們學習瞭如何在 Taurus.MVC WebMVC 中進行數據綁定操作。我們還學習瞭如何使用 ${屬性名稱} CMS 語法來綁定頁面上的元素與 Model 中的屬性。通過這些步驟,我們成功實現了一個簡單的數據綁定示例。 ...
  • 是在MVVM中用來傳遞消息的一種方式。它是在MVVMLight框架中提供的一個實現了IMessenger介面的類,可以用來在ViewModel之間、ViewModel和View之間傳遞消息。 Send 接受一個泛型參數,表示要發送的消息內容。 Register 方法用於註冊某個對象接收消息。 pub ...
  • 概述:在WPF中,通過EventHandler可實現基礎和高級的UI更新方式。基礎用法涉及在類中定義事件,併在UI中訂閱以執行更新操作。高級用法藉助Dispatcher類,確保在非UI線程上執行操作後,通過UI線程更新界面。這兩種方法提供了靈活而可靠的UI更新機制。 在WPF(Windows Pre ...
  • 概述:本文介紹了在C#程式開發中如何利用自定義擴展方法測量代碼執行時間。通過使用簡單的Action委托,開發者可以輕鬆獲取代碼塊的執行時間,幫助優化性能、驗證演算法效率以及監控系統性能。這種通用方法提供了一種便捷而有效的方式,有助於提高開發效率和代碼質量。 在軟體開發中,瞭解代碼執行時間是優化程式性能 ...
  • 概述:Cron表達式是一種強大的定時任務調度工具,通過配置不同欄位實現靈活的時間規定。在.NET中,Quartz庫提供了簡便的方式配置Cron表達式,實現精準的定時任務調度。這種靈活性和可擴展性使得開發者能夠根據需求輕鬆地制定和管理定時任務,例如每天備份系統日誌或其他重要操作。 Cron表達式詳解 ...
  • 概述:.NET提供多種定時器,如System.Windows.Forms.Timer適用於UI,System.Web.UI.Timer用於Web,System.Diagnostics.Timer用於性能監控,System.Threading.Timer和System.Timers.Timer用於一般 ...
  • 問題背景 有同事聯繫我說,在生產環境上,訪問不了我負責的common服務,然後我去檢查common服務的health endpoint, 沒問題,然後我問了下異常,timeout導致的System.OperationCanceledException。那大概率是客戶端的問題,會不會是埠耗盡,用ne ...
  • 前言: 在本篇 Taurus.MVC WebMVC 入門開發教程的第四篇文章中, 我們將學習如何實現數據列表的綁定,通過使用 List<Model> 來展示多個數據項。 我們將繼續使用 Taurus.Mvc 命名空間,同時探討如何在視圖中綁定並顯示一個 Model 列表。 步驟1:創建 Model ...