最近对于ipad端开发和移动端开发的一些总结和一些小功能总结分享,foreach不是同步函数

706 阅读5分钟

废话

老规矩,废话部分,也是很久没写博客了。主要是最近都被工作缠身,没什么太多独立学习的内容。

一、forEach不是一个纯粹的同步函数

年前到年初的一段时间重构一个功能,需要接收话术市场数据结构,然后前端进行解析,重新排列数据,再纯前端数据整理,之后调用存储json的接口,存到后端。这里发生一个事情就是我有一个数据处理函数。里面使用纯forEach,不断嵌套,使用。最大层次达到3层,中间还有使用async await请求接口数据,然后等待得到结果的情况。

大致代码结构是如下

forEach(async () => {
    const data = await fun
})
async fun () {
    await data()
}

最后我得到的数据在数据量较少情况下一开始没有发生问题,后来数据较多的一次发生情况,我的数据最后之间被返回出去了,没有被处理。

最后发现,类似上述代码情况,要使用for循环代替foreach情况,否则,你的数据就会处理不完全。结果是错的。

这个属于一个小知识点吧。

二、最近做了一个ipad端,横屏的,引发的rem适配问题

做横屏的时候说实在,rem适配发现在手机端完全错误了。但是我手机原生浏览器没问题。

设备信息:小米6,原生浏览器,百度,uc,QQ,原生没问题,uc,qq,百度全军覆没。

我的方案是,下面是适配ipad端的方式

html {
    font-size: calc(100vw/1024);
}

上面的代码适配ipad的,电脑,等等都没问题。但是手机端就完全行不通。页面错的厉害。

我个人最后是放弃了rem适配方案,采用了vw去适配响应式,效果出奇的好,完美适配。

最后分享下vw和各个设计图比值

设计图比值
1240:0.08065vw  
1024: 0.09765625vw  
####手机
750: 0.1333vw  
375: 0.2667vw

我个人后来也是多方百度,猜测的结果应该是font-size值太小了,发生了最小font-size问题。但是我没机会验证了,主要是发生vw有点香。你不去适配很老的机型就完全OK啊。

不过我大致也知道了我上面的rem方式应该最后再乘以100,这样就不会发生最小font-size问题了。也是为什么大家对于rem一般采用除以20或者10的方式了。

真的很好奇,小程序的rpx单位怎么实现的。

三、总结一个函数,包含页面下拉,滚动到底部,监听页面返回,页面滚动,页面显示隐藏等功能。

代码地址:github.com/ht-sauce/to…

当然这个代码是存在缺陷的。

特别是页面下拉和滚动到底部的监听容易发生问题。

关于页面下拉监听推荐使用vant封装的组件,或者自己去封装一个。

然后页面滚动到底部这个组件因为vant没有封装,那么我只能自己再封装一个了。核心函数是上面js里面拿出来的。

vue3组件:文档地址

<template>
  <div class="root" @scroll="OnScroll" ref="root">
    <slot></slot>
  </div>
</template>

<script>
import { ref, defineComponent, onBeforeUnmount, onMounted } from 'vue'

export default defineComponent({
  name: 'DhtReachBottom',
  emit: ['load', 'roll'],
  props: {
    bottom: {
      type: Number,
      default: 10,
    },
  },
  setup(props, ctx) {
    const root = ref('root')
    let _currentScroll = 0 // 当前滚动距离,判断上还是下
    let _isOnReachBottom = false // 是否触发过滑动到底部事件,保证不会一次性触发多次事件
    function OnScroll() {
      const dom = root.value
      const clientHeight = dom.clientHeight
      const contentHeight = dom.scrollHeight //内容高度
      const scrollTop = dom.scrollTop // 滚动距离

      const scollType = scrollTop >= _currentScroll ? 'down' : 'up'

      const BottomDistance = contentHeight - clientHeight - scrollTop
      // 页面滚动事件
      ctx.emit('roll', {
        dom: dom,
        clientHeight,
        contentHeight,
        scrollTop,
        PercentageDown: scrollTop / (contentHeight - clientHeight), // 向下滚动百分比
        BottomDistance: BottomDistance, // 底部距离,px
      })

      //到达底部10px时,页面滚动到底部的事件
      if (!_isOnReachBottom && scollType === 'down' && BottomDistance <= props.bottom) {
        _isOnReachBottom = true
        ctx.emit('load')
      }

      if (scollType === 'up') {
        _isOnReachBottom = false
      }

      _currentScroll = scrollTop
    }

    return {
      root,
      OnScroll,
    }
  },
})
</script>

<style scoped lang="scss"></style>

四、监听页面大小变化,元素是否隐藏的问题

这个问题是因为ipad上面测试的时候会发生页面底部使用abslote或者fixed的元素会被输入框顶起来。部分机型,不是所有。这里提供一个解决方案就是页面变小的时候隐藏。之后再显示回来。

同样是vue3代码,使用的时候,导出一个ref:fiexdShow,根据这个去控制显隐就行了

import { ref, onBeforeUnmount, onDeactivated, watch, reactive } from 'vue'

export default function () {
  const fiexdShow = ref(true) // 显示或者隐藏

  onBeforeUnmount(() => {
    window.removeEventListener('resize', heightscroll)
  })
  onDeactivated(() => {
    window.removeEventListener('resize', heightscroll)
  })

  const h2 = reactive({
    docmHeight: document.documentElement.clientHeight, //默认屏幕高度
    showHeight: document.documentElement.clientHeight, //实时屏幕高度
  })

  window.addEventListener('resize', heightscroll)

  function heightscroll() {
    h2.showHeight = document.documentElement.clientHeight
  }

  watch(
    () => h2.showHeight,
    () => {
      if (h2.docmHeight > h2.showHeight) {
        fiexdShow.value = false
      } else {
        fiexdShow.value = true
      }
    },
  )

  return {
    fiexdShow,
  }
}

五、我们常用的navigator.userAgent无法判断出来安卓平板是手机还是ipad

这个问题真的是操蛋的很,一来是我电脑上面测的好好的,结果到平板上面就各种不行啊。最后发现,到安卓平板上面得出的只是安卓系统,也就是只能是手机,但不知道是平板还是手机。

还好项目还没三端适配,我直接给干成全ipad页面了。但是这个问题也是很困扰,多方百度情况下,本来想获取页面物理英寸判断,但是貌似不管用。

最后发现也就像素比较好使了。但是像素有点靠经验判断。我总结一个函数

但是实际使用建议大家根据横竖屏再判断一下

// 根据px判断是手机端,pc,平板
export default function clientPX() {
  const width = window.screen.width
  if (width <= 600) {
    return 'mobile'
  }
  if (width > 600 && width < 960) {
    return 'ipad'
  }

  return 'pc'
}

横竖屏判断

// 判断横屏还是竖屏
export function orientation() {
  const clientWidth = document.documentElement.clientWidth
  const clientHeight = document.documentElement.clientHeight
  // 横
  if (clientWidth >= clientHeight) return 'vertical'
  else return 'transverse' // 竖
}

六、canvas生成二维码并且下载图片和a标签下载提供

// 利用a标签下载东西
export function Download(url) {
  if (!url) return false
  let a = document.createElement('a')
  a.href = url
  a.download = url
  a.click()
  a = null
}

canvas生成二维码,下载

import QRCode from 'qrcode'

export default function (text, name = '二维码.png') {
  let canvas = document.createElement('canvas')
  return new Promise((resolve, reject) => {
    QRCode.toCanvas(
      canvas,
      text,
      {
        width: 400,
        height: 400,
      },
      function (error) {
        if (error) reject(error)
        else {
          const fullQuality = canvas.toDataURL('image/jpeg', 1.0)
          let save_link = document.createElement('a')
          save_link.href = fullQuality
          save_link.download = name
          save_link.click()
          save_link = null
          canvas = null
          return resolve()
        }
      },
    )
  })
}

致谢:

感谢观赏,喜欢点个赞。