小程序嵌套H5的方式和技巧(二)


文章接上文,小程序嵌套H5的方式和技巧(一)

四、刷新wev-view嵌套的H5頁面

   1)我們為什么要刷新wev-view嵌套的H5頁面?

        很多的業務場景都需要開發者每次打開頁面都更新一下頁面的數據。原生小程序更新頁面的數據就比較簡單了,通常在onshow里處理就可以了,每次進入onshow生命周期直接調用接口來刷新數據就可以了,而小程序用web-view組件嵌套H5來刷新頁面數據可就沒那么簡單了。下面我來用實際場景來舉例。
        我們用三個頁面:首頁,頁面A和頁面B,三個頁面都有不同的殼,嵌套的不同的H5頁面。
        首頁:頁面元素包含banner圖,點擊banner圖會進入活動說明頁A
        活動說明頁A:頁面的元素包括參與活動需要滿足的條件,獲得獎勵的人數限制,獲得獎勵的參與人員列表,去參加活動的按鈕
        活動詳情頁B:頁面的元素包括活動的主頁面,返回上一頁的按鈕

    2)常規方法有回退兩次的問題
        用戶從頁面A進入到頁面B,用戶在B參與活動后返回上一頁到頁面A,此時需求希望頁面刷新。通常我們會這么寫:

wxml文件
  <web-view src="{{src}}"></web-view>

//
首頁 Page({ data: { }, onReady(){ setTimeout(()=> { // 模擬點擊頁面跳轉到活動頁面A wx.navigateTo({ url: '/pages/A/A' }) }, 5000) } }) // 頁面A Page({ /** * 頁面的初始數據 */ data: { src: "" }, /** * 生命周期函數--監聽頁面初次渲染完成 */ onReady: function () { setTimeout(()=>{ // 模擬點擊跳轉到頁面B wx.navigateTo({ url: '/pages/B/B' }) }, 5000) }, /** * 生命周期函數--監聽頁面顯示 */ onShow: function () { let t = +new Date(); this.setData({ src: `https://www.baidu.com?t=${t}` }) } }) // 頁面B代碼 Page({ /** * 頁面的初始數據 */ data: { src: "" }, /** * 生命周期函數--監聽頁面加載 */ onLoad: function (options) { this.setData({ src: `https://developers.weixin.qq.com/community/homepage` }) } })

 

        經過上面的描述流程后:首頁→活動說明頁A→活動詳情頁B→返回上一頁,回到活動說明頁A;此時我們點擊左上角的返回按鈕,我們預期的效果是回到首頁,但是實際的效果是web-view嵌套的H5頁面刷新了一下,並沒有回退至首頁。

     3)嘗試修改問題,反而引發其他更嚴重問題

        嘗試解決該問題,修改頁面A的代碼為

<!--頁面A的wxml-->
<view wx:if="{{src}}">
  <web-view src="{{src}}"></web-view>
</view>
// 頁面A
Page({

  /**
   * 頁面的初始數據
   */
  data: {
    src: ""
  },
  /**
   * 生命周期函數--監聽頁面初次渲染完成
   */
  onReady: function () {
    setTimeout(()=>{
      // 模擬點擊跳轉到頁面B
      wx.navigateTo({
        url: '/pages/B/B'
      })
    }, 5000)
  },

  /**
   * 生命周期函數--監聽頁面顯示
   */
  onShow: function () {
    let t = +new Date();
    this.setData({
      src: ``
    })
    this.setData({
      src: `https://www.baidu.com?t=${t}`
    })
  }
})

        修改代碼后,再經過流程后:首頁→活動說明頁A→活動詳情頁B→返回上一頁,回到活動說明頁A;發現頁面A空白且控制台報錯:[渲染層錯誤] 一個頁面只能插入一個 '<web-view />'

 

 

    4)功夫不負有心人,終於找到完美的解決方案

        經過多次嘗試方案,發現在onHide里面隱藏web-view(卸載we-bview),是可行的,貼上所有文件的代碼

<!--首頁的wxml-->
<view class="container">
</view>
// 首頁
Page({
  data: {
    motto: '首頁'
  },
  onReady(){
    setTimeout(()=> {
      // 模擬點擊頁面跳轉到活動頁面A
      wx.navigateTo({
        url: '/pages/A/A'
      })
    }, 5000)
  }
})

<!--頁面A的wxml-->
<view wx:if="{{src}}">
  <web-view src="{{src}}"></web-view>
</view>
// 頁面A
Page({

  /**
   * 頁面的初始數據
   */
  data: {
    src: ""
  },
  /**
   * 生命周期函數--監聽頁面初次渲染完成
   */
  onReady: function () {
    setTimeout(()=>{
      // 模擬點擊跳轉到頁面B
      wx.navigateTo({
        url: '/pages/B/B'
      })
    }, 5000)
  },

  /**
   * 生命周期函數--監聽頁面顯示
   */
  onShow: function () {
    let t = +new Date();
    this.setData({
      src: `https://www.baidu.com?t=${t}`
    })
  },
  onHide: function () {
    this.setData({
      src: ``
    })
  }
})

<!-- 頁面B的wxml -->
<web-view src="{{src}}"></web-view>
// 頁面B代碼
Page({

  /**
   * 頁面的初始數據
   */
  data: {
    src: ""
  },

  /**
   * 生命周期函數--監聽頁面加載
   */
  onLoad: function (options) {
    // 頁面不需要刷新 所以寫到onLoad生命周期里
    this.setData({
      src: `https://m.mi.com/`
    })
  }
})

        web-view的頁面刷新場景是非常常見的,也與我們后面的章節密不可分,因此講的還是比較詳細的,希望能幫助到其他的開發者。

     5)精益求精,精簡代碼

        結合我之前的文章,微信小程序如何重寫Page方法?以及重寫Page方法給開發者帶來的好處 我們可以把代碼做的更簡潔:將Page方法重新,把onHide生命周期卸載web-view的代碼提取出來,如果有很多的頁面需要web-view刷新H5的話,這樣會大大節省我們的工作量和代碼量。

        首先我們需要先定義一下web-view的頁面變量及其含義

        refreshSrc:如果頁面的data里定義里這個變量,且用這個變量來渲染web-view,則每次打開頁面都需要刷新頁面;注意:不需要刷新的頁面不要把渲染web-view的src屬性定義成該變量名

        精簡后的代碼

        

app.js
// app.js
(function(){
  // 小程序原來的Page方法
  let originalPage = Page;
  // 我們自定義的Page方法
  Page = function(config){
    // todo 在這里我們可以給配置對象進行加工
    // 將配置對象繼續想下傳遞給小程序原來的Page方法
    config.onHide = function(){
      //如果頁面定義了這個變量 且變量有值則在onHide生命周期將該值置空
      if(this.data.refreshSrc){
        this.setData({
          refreshSrc: ''
        })
      }
    }
    originalPage (config);
  }
})();
App({
  onLaunch() {
  },
  globalData: {
  }
})

<!--首頁的wxml-->
<view class="container">
</view>
// 首頁
Page({
  data: {
    motto: '首頁'
  },
  onReady(){
    setTimeout(()=> {
      // 模擬點擊頁面跳轉到活動頁面A
      wx.navigateTo({
        url: '/pages/A/A'
      })
    }, 5000)
  }
})

<!--頁面A的wxml-->
<view wx:if="{{refreshSrc}}">
  <web-view src="{{refreshSrc}}"></web-view>
</view>
// 頁面A
Page({

  /**
   * 頁面的初始數據
   */
  data: {
    refreshSrc: ""
  },
  /**
   * 生命周期函數--監聽頁面初次渲染完成
   */
  onReady: function () {
    setTimeout(()=>{
      // 模擬點擊跳轉到頁面B
      wx.navigateTo({
        url: '/pages/B/B'
      })
    }, 5000)
  },

  /**
   * 生命周期函數--監聽頁面顯示
   */
  onShow: function () {
    let t = +new Date();
    this.setData({
      refreshSrc: `https://www.baidu.com?t=${t}`
    })
  }
})

<!-- 頁面B的wxml -->
<web-view src="{{src}}"></web-view>
// 頁面B代碼
Page({
  /**
   * 頁面的初始數據
   */
  data: {
    src: ""
  },
  /**
   * 生命周期函數--監聽頁面加載
   */
  onLoad: function (options) {
    // 頁面不需要刷新 所以寫到onLoad生命周期里
    this.setData({
      src: `https://m.mi.com/`
    })
  }
})

    這部分還是為了小程序中有很多頁面需要刷新web-view嵌套的H5,如果小程序中類似於頁面A的頁面不多,這部分則可以忽略

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM