经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
uni-app+vue3会遇到哪些问题
来源:cnblogs  作者:唯之为之  时间:2024/2/2 9:08:55  对本文有异议

已经用 uni-app+vue3+ts 开发了一段时间,记录一下日常遇见的问题和解决办法

uni-app 中的单端代码

uni-app 是支持多端,如果你想让你的代码,只在部分平台使用,那么就需要用的它的单端处理语法 //#ifdef//#ifndef 等。

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

  1. //#ifdef MP-WEIXIN
  2. menuButtonInfo = '微信'
  3. //#endif

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

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

安全边距

1. 异形屏

因为有异形手机屏的存在,最顶部有摄像头,最下面有导航条,为了避免界面内容出现在这些位置,所以每次在界面初始要设置安全边距。

  1. <script setup lang="ts">
  2. // 获取屏幕边界到安全区域距离
  3. const { safeAreaInsets } = uni.getSystemInfoSync()
  4. </script>
  5. <template>
  6. <view class="specification-panel flex-column" :style="{ paddingTop: safeAreaInsets.top + 'px' }">
  7. <!-- 底部导航 -->
  8. <view class="bottomNav" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }"></view>
  9. </view>
  10. </template>

2. 微信胶囊

由于微信小程序右上角有微信胶囊,很多时候我们为了保持界面整齐,需要获取微信胶囊的位置,来让我们得元素和它对齐。

  1. // 微信胶囊一定处于安全位置,所以有微信胶囊就拿胶囊的位置,否则再去获取安全边距
  2. export const safeTop = () => {
  3. const { safeAreaInsets } = uni.getWindowInfo()
  4. // 获取胶囊信息 https://uniapp.dcloud.net.cn/api/ui/menuButton.html#getmenubuttonboundingclientrect
  5. let menuButtonInfo = { top: 0 }
  6. //#ifdef MP-WEIXIN
  7. menuButtonInfo = uni.getMenuButtonBoundingClientRect()
  8. //#endif
  9. const top = menuButtonInfo.top || safeAreaInsets?.top
  10. return {
  11. top
  12. }
  13. }

全局组件

全局组件 目前只能在 src/pages.json 里配置,代码如下:

  1. // 组件自动导入
  2. "easycom": {
  3. // 开启自动扫描
  4. "autoscan": true,
  5. "custom": {
  6. // 使用了uni-ui 规则如下配置
  7. "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
  8. // 自定义组件,需要使用正则表达式
  9. "^Weiz(.*)": "@/components/Weiz$1/index.vue"
  10. }
  11. }

使用的时候,直接在界面使用即可,无需再导入。

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

获取DOM信息

有的时候我们需要去拿到界面元素的相关信息,然后进行一些处理,uni-app 提供了相关API,但需要和 vue3 配合使用

  1. <script setup lang="ts">
  2. import { getCurrentInstance } from 'vue'
  3. const instance = getCurrentInstance()
  4. const getNodeInfo = () => {
  5. const query = uni.createSelectorQuery().in(instance)
  6. query
  7. .select('.similar') // 获取界面元素,也可以传id
  8. .boundingClientRect((data) => {
  9. const nodeInfo: UniApp.NodeInfo = data as UniApp.NodeInfo
  10. console.log(nodeInfo)
  11. })
  12. .exec()
  13. }
  14. </script>

是的你没看错,不需要给元素设置 ref

url 传参

url 跳转界面有两种方式,一种是使用 navigator 标签,一种是使用 uni.navigateTo 方法。
需要注意的是url有长度限制,太长的字符串会传递失败,而且参数中出现空格等特殊字符时需要对参数进行编码,如使用 encodeURIComponent 等。

1. 传递参数

  1. uni.navigateTo({
  2. url: 'pages/test?id=1&name=uniapp'
  3. });

或者

  1. <script setup lang="ts">
  2. const item = ref({ id: 1, name: 'uniapp' })
  3. </script>
  4. <template>
  5. <navigator :url="'/pages/test/test?item='+ encodeURIComponent(JSON.stringify(item))"></navigator>
  6. </template>

2. 接受参数

pages/test 界面

  1. onLoad: function(option) {
  2. console.log(option.id, option.name)
  3. // 如果传递的是经过编码的参数
  4. const item = JSON.parse(decodeURIComponent(option.item));
  5. }

父子组件通信

简单参数

子组件:

  1. <script setup lang="ts">
  2. // 使用 defineProps 来接受参数,非必要参数使用 xxx? 的形式
  3. defineProps<{
  4. title: string
  5. subTitle?: string
  6. }>()
  7. </script>
  8. <template>
  9. <view class="weiz-title">
  10. <view class="title">{{ title }}</view>
  11. <view class="sub-title">{{ subTitle }}</view>
  12. </view>
  13. </template>

父组件:

  1. // 由于是全局组件,所以无需再引入,如果不是全局组件,需要单独引入 <WeizTitle title="详情" />

复杂参数

如果参数比较复杂,可以直接用 TS 去定义类型,下面举例:

子组件:

  1. <script setup lang="ts">
  2. // 引入参数类型
  3. import type { CategoryItem } from '@/types/api'
  4. // 定义 props 接收数据
  5. defineProps<{
  6. list: CategoryItem[]
  7. }>()
  8. </script>

父组件:

  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. import { onLoad } from '@dcloudio/uni-app'
  4. // 引入数据类型
  5. import type { CategoryItem } from '@/types/api'
  6. // 引入接口
  7. import { getCategoryIndexAPI } from '@/api/category'
  8. // 定义响应式数据
  9. const categoryList = ref<CategoryItem[]>([])
  10. // 获取数据方法
  11. const getCategoryList = async () => {
  12. const res = await getCategoryIndexAPI()
  13. // 拿到数据赋值
  14. categoryList.value = res.result
  15. }
  16. // 调用方法
  17. onLoad(() => {
  18. getCategoryList()
  19. })
  20. </script>
  21. <template>
  22. <WeizCategory :list="categoryList" @refresh="getCategoryList" />
  23. </template>

父调子方法

父调子需要子组件通过 defineExpose 暴露方法给父组件,然后父组件拿到子组件实例再去调用子组件方法。

1. 子组件暴露方法

  1. // 定义方法
  2. const getCurrentSpec = () => {
  3. return currentSpec.value
  4. }
  5. // 暴露方法给父组件
  6. defineExpose({
  7. getCurrentSpec
  8. })

2. 父组件拿到实例调用

可参考章节 TS 相关 - 定义组件实例类型,调用子组件需要先拿到子组件的实例,拿到实例后直接调用即可。

  1. // 拿到子组件实例 WeizCategoryInstance 需要我们去 ts 里定义
  2. const weizCategory = ref<WeizCategoryInstance>()
  3. // 调用子组件实例的方法
  4. weizCategory.value.getCurrentSpec()

子调父方法

子调父方法,需要父组件去给子组件添加自定义事件,然后子组件通过 defineEmits 去触发。

1. 父组件声明自定义事件

  1. <script setup lang="ts">
  2. const handleUpdate = (value: string) => {
  3. console.log('拿到子组件的传值,并且调用了父组件', value)
  4. }
  5. </script>
  6. <template>
  7. <WeizCategory :list="categoryList" @update="handleUpdate" />
  8. </template>

2. 子组件使用 defineEmits

  1. <script setup lang="ts">
  2. import { ref, defineEmits } from 'vue'
  3. const message = ref('子组件的值')
  4. const popupEmit = defineEmits(['update'])
  5. function sendMessage() {
  6. popupEmit('update', message.value)
  7. }
  8. </script>
  9. <template>
  10. <div>
  11. <button @click="sendMessage">触发父组件方法</button>
  12. </div>
  13. </template>

TS 相关

定义组件实例类型

定义组件实例类型文件 xxx.d.ts

  1. // 导入组件
  2. import WeizCardList from '@/components/WeizCardList/index.vue'
  3. // 什么全局类型
  4. declare module 'vue' {
  5. export interface GlobalComponents {
  6. WeizCardList: typeof WeizCardList
  7. }
  8. }
  9. // 导出组件实例类型, 需要用到 InstanceType
  10. export type CardListInstance = InstanceType<typeof WeizCardList>

在 vue 页面里使用:

  1. // 导入组件实例类型
  2. import type { CardListInstance } from '@/types/components'
  3. // 拿到组件实例
  4. const cardList = ref<CardListInstance>()
  5. // 调用组件实例的方法
  6. cardList.value?.resetData()

原文链接:https://www.cnblogs.com/weizwz/p/18002189

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号