天天看點

小程式系列(三)——踩坑(持續更新)

前言 

基于mpvue架構:mpvue官方文檔

文法同vue架構:vue官方文檔

小程式中會有一些坑點,這裡會就工作中遇到的坑一一列舉出來

v-show無法使用在小程式中

<!-- 下面這行代碼無法正常工作 -->
<img v-show="IDcard" :src="IDcard" alt="">

<!-- 替代方案 -->
<img v-if="IDcard" :src="IDcard" alt="">
           

input标簽的type無法動态指派

<!-- 下面的inputType的值可能為:number|text|tel -->
<!-- 下面的代碼無法得到正确結果 -->
<input class="value" :type="inputType" v-model="value">

<!-- 替代方案 -->
<input v-if="inputType === 'text'" class="value" v-model="value" type="text">
<input v-else-if="inputType === 'number'" class="value" v-model="value" type="number">
<input v-else class="value" v-model="value" type="tel">
           

img标簽的src内不可使用三元運算符

<!-- 下面的寫法導緻src拿不到bg_identity.png -->
<img :src="IDcard?IDcard:'../../../static/images/bg_identity.png'" alt="">

<!-- 替代方案 -->
<img v-if="IDcard" :src="IDcard" alt="">
<img v-else src="../../../static/images/bg_identity.png" alt="">
           

詳情頁跳轉舊資料不銷毀處理辦法

場景:從商品清單點選一件商品進詳情,傳回清單頁,選擇另一件商品進詳情,會出現上一件商品的資料後再渲染新商品的資料 
// 解決方案
onUnload () {
  Object.assign(this.$data, this.$options.data())
}
           
  • 在小程式的頁面解除安裝生命鈎子onUnload中添加以上代碼,可讓data對象裡的屬性重新初始化 

原生元件的層級問題

官方說明文檔原生元件說明
  • 舉例說明:如果想讓一個按鈕定位在canvas内容層級上面,直接使用z-index是無效的,
  • 解決辦法:使用小程式提供的cover-view 與 cover-image元件可覆寫在部分原生元件上面,
  • 實際例子:①button元件定位在canvas元件上面√;
  • 注意事項:①使用了cover-view元件後,cover-view容器内不能使用正常的div,a,span等等,可嵌套cover-view 、 cover-image和button√;②可覆寫的原生元件包括map、video、canvas、camera、live-player、live-pusher

onLoad與onShow的差別

頁面路由

onLoad:頁面加載時觸發。一個頁面隻會調用一次,可以在 onLoad 的參數中擷取打開目前頁面路徑中的參數。 
  • 例如從分享的消息卡片中帶參數到指定頁,如:pages/index/main?id=123
小程式系列(三)——踩坑(持續更新)
onLoad (e) {
  console.log(e.id) // 123
},

onShareAppMessage: function (res) {
  return {
    title: '邀請您填履歷',
    path: `/pages/index/main?id=${this.id}`
  }
}

           
onShow:頁面顯示/切入前台時觸發。不可帶參數,但是可以動态更新目前頁

textarea原生元件相關問題

解決textarea元件為原生元件層級最高,穿透彈窗或遮罩層。
<textarea v-model="desc" class="inp" placeholder="" auto-focus v-if="focusFlag" @blur="hideTextarea"></textarea>
<p v-else-if="!focusFlag && desc" class="textarea-replace" @click="showTextarea">{{desc}}</p>
<p v-else class="textarea-replace no-desc" @click="showTextarea">請介紹一下自己的性格特點、工作經曆,描述下自己擅長做的事情</p>
           
export default {
  data () {
    desc: '',
    focusFlag: true
  },
  methods: {
    hideTextarea () {
      this.focusFlag = false
    },
    showTextarea () {
      this.focusFlag = true
    }
  }
}
           
這裡解釋一下:
  • auto-focus很重要,不加的話,每次輸入文字都得聚焦(點選)兩次;
  • placeholder可以通過增減p标簽的class名來實作,即class="no-desc"
  • @blur事件是失去焦點時觸發

 new Date()設定日期在IOS的相容問題

new Date(date).getTime(),

用這個方法來擷取時間戳時,iphone手機上列印出的時間戳為NaN
  •  日期為2019-08-27 16:11:02時使用

    new Date(date).getTime()方法無法在iphone手機上擷取到對應的時間戳

  • 解決方案:
const time = '2019-08-27 16:11:02'
const newTime = new Date(time.replace(/-/g, '/')).getTime()
           
  •  安卓手機不管是‘-’還是‘/’都能正确轉成時間戳

關于小程式中計時器的正确使用

先看執行個體

小程式系列(三)——踩坑(持續更新)
小程式系列(三)——踩坑(持續更新)

講解:

  • 每個需求詳情對應一組倒計時
  • 每次進詳情頁,希望資料都是初始化的狀态
  • 離開頁面即銷毀資料,下次進詳情重新擷取新資料 

坑點

  • 每次進詳情頁都會生成一個計時器
  • 如果頁面銷毀時不手動清除計時器的話會導緻再次進入詳情頁會有兩個計時器在運作,重複動作,會有越來越多的計時器存在于詳情頁中
  • 如何銷毀,計時器如何定義?

解決方案

data () {
  return {
    timer: null
  }
},
onLoad (e) {
  this.demandId = e.id
  this.getDemandDetail()
},
onUnload () {
  clearInterval(this.timer)
  Object.assign(this.$data, this.$options.data())
},
methods: {
  getDemandDetail() {
    // axios請求拿到詳情資料後
    getDetail(this.demandId).then(res => {
      // 在接口中擷取到截止時間和伺服器的目前時間
      this.runTimer(res.data.deadline, res.data.systemDate)
    })
  },

  runTimer (deadline, systemDate) {
    deadline = deadline.replace(/-/g, '/')
    systemDate = systemDate.replace(/-/g, '/')
    let totalSeconds = parseInt((new Date(deadline).getTime() - new Date(systemDate).getTime()) / 1000)
    this.timer = setInterval(() => {
      const hours = parseInt(totalSeconds / 60 / 60) > 0 ? parseInt(totalSeconds / 60 / 60) : 0
      const minutes = parseInt((totalSeconds - hours * 3600) / 60) > 0 ? parseInt((totalSeconds - hours * 3600) / 60) : 0
      const seconds = parseInt(totalSeconds - hours * 3600 - minutes * 60) > 0 ? parseInt(totalSeconds - hours * 3600 - minutes * 60) : 0
      // 計算出時分秒并指派給顯示區域
      this.countTime.hours = hours < 10 ? '0' + hours : hours
      this.countTime.minutes = minutes < 10 ? '0' + minutes : minutes
      this.countTime.seconds = seconds < 10 ? '0' + seconds : seconds
      // 當秒數小于零時銷毀計時器,否則秒數-1
      if (totalSeconds <= 0) {
        this.countdownEnd = true
        clearInterval(this.timer)
        this.timer = null
      } else {
        totalSeconds--
      }
    }, 1000)
  }
}
           
  • 關鍵代碼
onUnload () {
  // 必須執行clearInterval操作才能銷毀計時器,簡單的null指派無法銷毀
  clearInterval(this.timer)
  // 前面有介紹過,負責頁面銷毀後再次回到頁面時初始化資料
  Object.assign(this.$data, this.$options.data())
},