mpvue 开发中问题

原生开发

  • 原生组件
    scroll-view 中使用 textarea、map、canvas、video 组件出现冲突问题

  • 页面的脚本逻辑是在 JsCore 中运行,JsCore 是一个没有窗口对象的环境,所以不能在脚本中使用 window,也无法在脚本中操作组件。获取节点信息依赖于 wx.createSelectorQuery & wx.createIntersectionObserver

  • rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为 750rpx。如在 iPhone6 上,屏幕宽度为 375px,共有 750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

  • wx.showLoadingwx.showToast 会互相影响,wx.hideLoading 会影响 toast 内容。

  • showLoading 一定要配合 hideLoading

  • 编译模式

  • 更新模式
    小程序冷启动时如果发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一次冷启动才会应用上。

  • 分包

  • 回调函数里的 this:使用变量 that 或者 ES6 的箭头函数。需要注意的是箭头函数不能作为 Page 的参数。

  • ES6

  • 版本兼容
    iOS 9 /10 中出现过 display:flex; 属性失效问题;
    iOS 9 /10 <image> 标签宽高自适应width:100%;height:100%不显示图片问题。

  • 小程序分享及用户信息授权等接口能力的调整通知

  • setData
    Q:setData 方法是有 react 那样的虚拟 dom 优化吗?
    A:有做虚拟 DOM 的优化,但设置相同数据还是会触发新渲染的。

  • console.log
    直接 log 对象实例时会打印出该对象引用地址,可能出现对象中的值不是同步执行代码后的结果,应该使用JSON.stringify 获取实时的数据。

  • IDE 黑屏

  • 读写文件

  • 动态跳转路径跳转问题(v)

mpvue 专属

解决方式:
在全局的 Vue 实例中挂载方法删除数据

// 定义插件
const somePlugin = {
  install: function () {
    Vue.mixin({
      onUnload() {
        if (this.$options.data) {
            Object.assign(this.$data, this.$options.data())
        }
      }
    })
  }
}
// 使用插件
Vue.use(somePlugin)

支持数据备份的版本:


export default {
  install (_Vue) {
    // 添加全局方法或属性
    _Vue.prototype.$isPage = function isPage () {
      return this.$mp && this.$mp.mpType === 'page'
    }

    _Vue.prototype.$pageId = function pageId () {
      return this.$isPage() ? this.$mp.page.__wxWebviewId__ : null
    }

    // 注入组件
    _Vue.mixin({

      methods: {
        stashPageData () {
          // 备份route
          return { data: { ...this.$data }, route: this.$route }
        },
        restorePageData (oldData) {
          // 恢复route
          this._route = oldData.route
          this.$router.currentRoute = oldData.route
          Object.assign(this.$data, oldData.data)
        }
      },

      onLoad () {
        if (this.$isPage()) {
          // 新进入页面
          Object.assign(this.$data, this.$options.data())
        }
      },

      onUnload () {
        if (this.$isPage()) {
          // 退出页面,删除数据
          delete pageDatas[this.$pageId()]
          this.$needReloadPageData = true
        }
      },

      onHide () {
        if (this.$isPage()) {
          // 将要隐藏时,备份数据
          pageDatas[this.$pageId()] = this.stashPageData()
        }
      },

      onShow () {
        if (this.$isPage()) {
          console.log('onShow')
          // 如果是后退回来的,拿出历史数据来设置data
          if (this.$needReloadPageData) {
            const oldData = pageDatas[this.$pageId()]

            if (oldData) {
              this.restorePageData(oldData)
            }
            this.$needReloadPageData = false
          }
        }
      }

    })
  }
}
  • intput 使用 v-model 绑定数据

表现:输入内容闪烁、回退。
https://github.com/Meituan-Dianping/mpvue/issues/296

方案一:使用 v-model.lazy 延迟更新数据显示,同样的原理可以使用 computed

<template>
  <div>
     <input type="search" v-model="search">
  </div>
</template>
<script>
export default {
  computed: {
    search: {
      set(value) {
        this.searchText = value
        clearTimeout(this.timer)
        this.timer = setTimeout(() => {
          // TODO
        }, 500)
      },
      get() {
        return this.searchText
      }
    }
}
</script>

方案二:使用表单获取输入值

<template>
  <view class='box'>
    <form @submit='submit'>
        <input type='text' name='username'></input>
        <input type='text' name='pwd'></input>
        <button class='login' form-type='submit'>登录</button>
    </form>
  </view>
</template>

<script>
export default {
  methods: {
    submit:function(e) {
      var name = e.detail.value.username
      var pwd = e.detail.value.pwd
    }
  }
}
</script>
  • 使用 v-model 出现重复赋值的问题

scroll-view 中使用 v-model 绑定 scroll-top,只要刷新 data 里的任一数据都会出现重新赋值导致 scroll-view 回弹。

<!-- scrollTop 控制垂直方向上滑动的距离 -->
<scroll-view scroll-y :scroll-top="scrollTop" >

组件渲染是串行的,而原生的是并行的。

onShareAppMessage(){
  this.scrollYView = 'peopleListTitle'
  //同步阻塞 2s
  let start = new Date().getTime()
  for (let i = 0; i < 1e7; i++) {
    if (new Date().getTime() - start > 2000) {
      break
    }
  }
  return {}
}
  • 悬浮方案

定高方案,不定高的 scroll-view ( 事件冲突 )

当前方案:

<template>
<div>
  <div class="float-top"> </div>
  <div class="list" :style="{'margin-top': topHeight +'px'}"></div>
</div>
</template>

<script>
  onLoad() {
    var intersectionObserver = wx.createIntersectionObserver()
    // 设置回调的时候 float-top 和 .list 如果没有被渲染将无效
    intersectionObserver.relativeTo('.float-top').observe('.list', res => {
      // 顶部悬浮框和列表页的相交监听
      if (res.intersectionRatio > 0 && this.topHeight < 50) {
        wx.createSelectorQuery().select('.float-top')
          .boundingClientRect(rect => {
            // TODO 是否可以注销回调
            // intersectionObserver.disconnect()
            this.topHeight = rect.bottom
          })
          .exec()
      }
    })
  }
</script>

大致有两个方案,一个是用小程序原生的 movable-view( 拖动组件 ),另一个是通过监听 move 事件去设置 view 的坐标。
第二个方案在 Android 上出现很严重的性能问题,过于频繁的 setData() 导致页面卡顿。

<div :style="{'top': currTop + 'px'}" :class="{'public-product-move': productIndex == currindex}"
@touchmove.stop="move" @touchstart="movestart" @touchend="moveend" />

    movestart(e) {
      // currindex = e.target.dataset.index
      this.x = e.touches[0].clientX
      this.y = e.touches[0].clientY
      this.x1 = e.currentTarget.offsetLeft
      this.y1 = e.currentTarget.offsetTop
    },
    move(e) {
      this.yy = e.currentTarget.offsetTop
      this.x2 = e.touches[0].clientX - this.x + this.x1
      this.y2 = e.touches[0].clientY - this.y + this.y1
    },
    moveend() {
      // this.currindex = -1
    }
  • v-for 中使用组件出现渲染问题
  • 文字缩略,省略号
    父布局为 position: relative; 的情况下
.text { 
  font-size: 9pt;
  color: #888888;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  width: 100%;
  position: absolute;
  left: 0;
}
  • 生命周期

mpvue 中 created 会在小程序冷启动时回调。


image.png
  • z-index

如果设置了 item 的 z-index,最好一起设置包裹了 item 的父布局的 z-index

  • iOS 时间戳解析失败

iOS 中无法解析出格式为 yyyy-MM-dd 的时间戳,需要转换为 yyyy/MM/dd

getDateDiff( new Date(item.created_at.replace(/-/gi, '/')).valueOf())
  • 组件的渲染机制

  • vuex 存储的数据太大的时候会导致页面无法刷新

  • IDEA 2018.09.26 问题
    A 新增 project.config.json packOptions.ignore / debugOptions.hidedInDevtools 支持 Glob 和 RegExp 规则

  • 组件和模板

调用组件方法,指定组件的 ref 并使用 this.refs.{{refName}}.{{method}} 调用:

<template>
  <div class="container">
    <homePage v-if="selectIndex === 1" ref="home" @reloadUserInfo='reloadUserInfo' ></homePage>
  </div>
</template>
<script>
import homePage from '@/components/home/home'
export default {
  data() {
    return {}
  },
  components: {
    homePage
  }
  onPullDownRefresh: function(e) {
     this.$refs.home.refresh()
  }
}
</script>

模板的作用域是独立的。

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 6,812评论 1 38
  • 共享好老师,学习无烦恼 老师好共享平台,是一个共享好老师、免费找老师的O2O服务平台。致力于帮助家长和学生解决找好...
    老师好共享平台阅读 44评论 0 0
  • 空中有座南山小院 小狗在用玉米刷牙 蝴蝶撞破音乐的晚霞 有只小花朝着太阳撒娇 一旁的云朵害羞的红了脸颊 谁知道月亮...
    马泥酱阅读 125评论 6 8
  • 家有宝妞5岁 一 “妈妈,你觉得我选你当妈妈幸运吗?” “这个要问你自己。” “有时候觉得幸运,有时候觉得不幸运”...
    步烟飞阅读 34评论 0 0
  • 今年的母亲节前几天007社群都开始举办关于007er写母亲的文章r的活动,我本来也没想着写,因为心里觉得妈妈真没有...
    阳光心屋阅读 109评论 1 1