Vue3在IOS下的一個小bug

自從Vue3 Beta發佈以來,我就嘗試在小項目中使用它了,不得不說真是香,雖然對新手可能不太友好,但是對於用過React Hooks的人來說簡直不要太爽,解決了React Hooks多次運行以及性能優化等多項心智負擔,但是就在剛剛做好的一個動效在自己手機上完美運行,美滋滋的拿去給同事測試,然而同事的蘋果手機卻沒有任何動態效果:

而在我的手機效果是這樣的:

這個特效的邏輯是這樣的:首先獲取後置攝像頭權限進行拍攝,然後在視頻上方循環播放幀動畫(其實就是仿AR),由於公司無力開發AR模型,只能讓美工渲圖然後web端做個僞AR,那麼問題來了,如果是WebGL做出來的模型即使代碼量很大,也依然就幾百K頂多1M,但是幀動畫就不一樣了,美工給了我幾百張圖,每一張大概在50k左右,加在一起十多M二十來M的,加載時間太長了,所以需要一個等待動畫,這個等待動畫就是一個小心心,小心心裏面是你攝像頭目前拍攝到的畫面,這個小心心會隨着你加載的圖片的數量而越來越大,當加載完畢後小心心佔滿全屏(也就是看不到小心心啦)。

組件間傳值

在幀動畫那個組件裏請求的圖片,但是圖片請求了多少張這個數值需要傳遞到小心心那個組件去,發現$emit這種vue2傳值法居然不好使了!

// 子組件
import { defineComponent } from 'vue'

export default defineComponent((props, ctx) => {
    ctx.$emit('event', '來自子組件的值')
    return {}
})
<!--父組件-->
<Child @event="getChildValue"/>

那個ctx就相當於vue2.x的this

然而這種在vue2.x中十分常見的傳值方法在這裏卻沒有任何效果。

Vue3傳值方式

那麼該如何傳值呢?試試在React Hooks的那種自定義Hook再試試:

//抽取出來一個js文件
import { ref } from 'vue'

const count = ref(0)

export default number => {
  count.value = number || count.value
  return { count }
}
<!--子組件A-->
<template>
  <span>{{count}}</span>
</template>

<script>
import { defineComponent } from 'vue'
import useCount from '../use/useCount'

export default defineComponent(_ => {
  const { count } = useCount()

  return { count }
})
</script>
<!--子組件B-->
<template>
  <button @click="addCount">+</button>
  <a href="#">{{count}}</a>
</template>

<script>
import { defineComponent } from 'vue'
import useCount from '../use/useCount'

export default defineComponent(_ => {
  const { count } = useCount()

  const addCount = _ => count.value++

  return { count, addCount }
})
</script>
<!--父組件-->
<template>
  <A/>
  <B/>
</template>

<script>
import A from './A'
import B from './B'

export default {
  components: { A, B }
}
</script>


可以看到和React Hooks的自定義Hook用法很相似。

watch + onMounted在IOS下的坑

本來是需要監聽請求圖片那個組件傳回來的值來給小心心組件,每多請求回來一張圖,小心心就放大一些,直到小心心充滿屏幕。
於是乎我這樣寫了:

import { onMounted } from 'vue'
import { useXxx } from '../use/useXxx'
// 只貼出了關鍵代碼
setup () {
    const { val } = useXxx()
    onMounted(_ => {
        // 此處省略若干行業務代碼
        watch(val, v => console.log(v))
    })
}

這段代碼在我的PC端和移動端都運行良好打印出值來,並且沒有任何的報錯,所以我才自信滿滿的去給別人看,結果一碰見蘋果手機就……

解決方案

把watch函數提到生命週期函數外部使用。

import { onMounted } from 'vue'
import { useXxx } from '../use/useXxx'
// 只貼出了關鍵代碼
setup () {
    const { val } = useXxx()
    watch(val, v => console.log(v))
    onMounted(_ => {
        // 此處省略若干行業務代碼
    })
}

建議不要將watch函數與各種生命週期函數放在一起混用,否則可能會出現意想不到的bug。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章