NervJS / taro

开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/
https://docs.taro.zone/
Other
35.64k stars 4.8k forks source link

Taro 3.5.10在小程序中加载元素DOM节点比较深时,滚动时,已加载的元素会出现闪屏(H5平台正常) #13056

Open DuduStyle opened 1 year ago

DuduStyle commented 1 year ago

相关平台

微信小程序

小程序基础库: 2.28.1 使用框架: React

复现步骤

企业微信截图_16723836407623

企业微信截图_1672383684618

期望结果

已加载的元素,已指定key,在小程序中滚动或者数据发生变更时,已存在的元素不会闪屏

实际结果

在小程序中滚动或者数据发生变更时,已存在的元素会闪屏,图片widthFix模式下最为明显。

环境信息

 Taro CLI 3.5.10 environment info:
    System:
      OS: Windows 10
    Binaries:
      Node: 14.17.5 - C:\Program Files\nodejs\node.EXE
      Yarn: 1.22.18 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
      npm: 6.14.14 - C:\Program Files\nodejs\npm.CMD
tourze commented 1 year ago

遇事不决,都可以使用CustomWrapper将可能闪烁的组件包起来再试试。。

DuduStyle commented 1 year ago

遇事不决,都可以使用CustomWrapper将可能闪烁的组件包起来再试试。。

这个按照文档教程试了呢,还是会出现此问题

Linefate commented 1 year ago

在小程序中滚动或者数据发生变更时,已存在的元素会闪屏,图片widthFix模式下最为明显。 这个滚动现在有解决方式吗?

Linefate commented 1 year ago

想到的一个解决方案: 需要的可以先这样处理

  1. image先使用mode: widthFix
  2. 监听image的onload 事件,拿到图片的宽度和高度
  3. 根据图片宽高比,再计算图片在当前屏幕屏幕宽度下,图片真正渲染的高度 finalHeight
  4. 根据真正渲染的高度finalHeight,修改image 标签的样式,修改图片的 mode:scaleToFill

`const CustomImage = React.memo( ({ src }) => {

const [imgInfo, setImgInfo] = useState({
  width: 0,
  height: 0,
})

const finalHeight = useMemo(() => {
  if (!imgInfo.width || !imgInfo.height) {
    return 0
  } else {
    // 暂时按 100vw计算
    const height = floatFormat((100 * imgInfo.height) / imgInfo.width, 2)
    return `${height}vw`
  }
}, [imgInfo.width, imgInfo.height])

const style = useMemo(() => {
  if (!finalHeight) return
  return {
    height: finalHeight,
  }
}, [finalHeight])

const onLoad = (res) => {
  // *由于无法从接口处拿到图片的宽高,加载完图片后,记录图片的宽高,再设置style
  // !因为taro的Bug issuesID: 13056
  // 在小程序中滚动或者数据发生变更时,已存在的元素会闪屏,图片widthFix模式下最为明显。
  setImgInfo({
    width: res?.detail?.width || 0,
    height: res?.detail?.height || 0,
  })
}
return (
  <Image
    style={style}
    mode={finalHeight ? 'scaleToFill' : 'widthFix'}
    src={src}
    className="w-full align-middle"
    lazyLoad
    onLoad={onLoad}
  ></Image>
)

}, (pre, next) => { if (pre === next) { return true } return false } )`