美文网首页
mpvue 开发中问题

mpvue 开发中问题

作者: chauI | 来源:发表于2018-10-26 11:46 被阅读109次

    原生开发

    • 原生组件
      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>
    

    模板的作用域是独立的。

    相关文章

      网友评论

          本文标题:mpvue 开发中问题

          本文链接:https://www.haomeiwen.com/subject/wjoliftx.html