当前位置:   article > 正文

小程序嵌套H5的方式和技巧_小程序嵌入h5页面

小程序嵌入h5页面

文章内多次使用了关键字“壳”,首先先解释一下什么是壳

    壳: 小程序由原生的web-view组件形成的页面,页面只包含技术逻辑(如打开H5页面),不包含具体业务接口请求和业务逻辑处理

一、小程序嵌套H5的模式种类

    1.单壳内跳模式

        打开小程序后,进入入口页面(首页)后,其他跳转都是通过window.location.href跳转的

    2.单壳自跳模式

        小程序只有一个壳A,每次跳转都是由壳A跳转壳A,通过path里传递不同的参数,从而打开不同的H5页面

    3.主原从壳模式

        为了更好的用户体验和使用微信强大的能力,主要页面采用小程序原生开发,次要页面采用壳套H5页面开发。

        主要页面:拥有复杂的业务逻辑或用户交互。

        次要页面:主要是展示作用的页面,用户交互和数据交互很少或者没有。

    4.组合模式(没有金刚钻别揽瓷器活,不推荐用此模式)

        模式1+模式2+模式3有两种及两种以上的模式应用,所以叫组合模式

二、小程序嵌套H5后失去的优势

    1.更快的加载速度

        1)小程序的代码加载完成后,才会加载H5代码

        2)小程序的代码在手机上有缓存,H5代码不会被缓存(设置缓存除外)

        因此小程序嵌套H5后加载内容和展示页面的速度会更慢。

    2.更强大的能力

        小程序原生能力包含用户信息,支付,数据统计,广告平台,位置服务,与硬件交互的能力(蓝牙,Wifi,NFC),与系统的交互(文件,扫码,剪切板,电话)等,H5页面具备这些能力。

    3.原生APP的体验

        具体例子,前端开发少不了与input元素打交道。当input聚焦的一刹那(onfocus),使用小程序开发和H5开发有着截然不同的体验,如键盘弹起速度,弹起位置,键盘的种类等等,小程序有着原生APP的体验,而H5则体验较差。

三、小程序与H5的通信

    1.小程序向H5通信:

        目前只有一种方式,就是通过设置web-view组件里的src属性中的链接参数来传递数据,H5通过URL里的参数来获取小程序传递来的数据。

    2.H5向小程序通信:

        目前也只有一种方式,通过wx.miniProgram.postMessage来向小程序传递数据,小程序通过在web-view组件上bindmessage绑定回调事件来接收数据,注意:bindmessage绑定的事件不是实时能获取wx.miniProgram.postMessage传递的数据,而是特定的时机(小程序后退、组件销毁、分享)

  

四、刷新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,此时需求希望页面刷新。通常我们会这么写:

  1. wxml文件
  2.   <web-view src="{{src}}"></web-view>
  3. // 首页
  4. Page({
  5. data: {
  6. },
  7. onReady(){
  8. setTimeout(()=> {
  9. // 模拟点击页面跳转到活动页面A
  10. wx.navigateTo({
  11. url: '/pages/A/A'
  12. })
  13. }, 5000)
  14. }
  15. })
  16. // 页面A
  17. Page({
  18. /**
  19. * 页面的初始数据
  20. */
  21. data: {
  22. src: ""
  23. },
  24. /**
  25. * 生命周期函数--监听页面初次渲染完成
  26. */
  27. onReady: function () {
  28. setTimeout(()=>{
  29. // 模拟点击跳转到页面B
  30. wx.navigateTo({
  31. url: '/pages/B/B'
  32. })
  33. }, 5000)
  34. },
  35. /**
  36. * 生命周期函数--监听页面显示
  37. */
  38. onShow: function () {
  39. let t = +new Date();
  40. this.setData({
  41. src: `https://www.baidu.com?t=${t}`
  42. })
  43. }
  44. })
  45. // 页面B代码
  46. Page({
  47. /**
  48. * 页面的初始数据
  49. */
  50. data: {
  51. src: ""
  52. },
  53. /**
  54. * 生命周期函数--监听页面加载
  55. */
  56. onLoad: function (options) {
  57. this.setData({
  58. src: `https://developers.weixin.qq.com/community/homepage`
  59. })
  60. }
  61. })

   经过上面的描述流程后:首页→活动说明页A→活动详情页B→返回上一页,回到活动说明页A;此时我们点击左上角的返回按钮,我们预期的效果是回到首页,但是实际的效果是web-view嵌套的H5页面刷新了一下,并没有回退至首页。

     3)尝试修改问题,反而引发其他更严重问题

        尝试解决该问题,修改页面A的代码为

  1. <!--页面A的wxml-->
  2. <view wx:if="{{src}}">
  3. <web-view src="{{src}}"></web-view>
  4. </view>
  5. // 页面A
  6. Page({
  7. /**
  8. * 页面的初始数据
  9. */
  10. data: {
  11. src: ""
  12. },
  13. /**
  14. * 生命周期函数--监听页面初次渲染完成
  15. */
  16. onReady: function () {
  17. setTimeout(()=>{
  18. // 模拟点击跳转到页面B
  19. wx.navigateTo({
  20. url: '/pages/B/B'
  21. })
  22. }, 5000)
  23. },
  24. /**
  25. * 生命周期函数--监听页面显示
  26. */
  27. onShow: function () {
  28. let t = +new Date();
  29. this.setData({
  30. src: ``
  31. })
  32. this.setData({
  33. src: `https://www.baidu.com?t=${t}`
  34. })
  35. }
  36. })

修改代码后,再经过流程后:首页→活动说明页A→活动详情页B→返回上一页,回到活动说明页A;发现页面A空白且控制台报错:[渲染层错误] 一个页面只能插入一个 '<web-view />'

    4)功夫不负有心人,终于找到完美的解决方案

        经过多次尝试方案,发现在onHide里面隐藏web-view(卸载we-bview),是可行的,贴上所有文件的代码

  1. <!--首页的wxml-->
  2. <view class="container">
  3. </view>
  4. // 首页
  5. Page({
  6. data: {
  7. motto: '首页'
  8. },
  9. onReady(){
  10. setTimeout(()=> {
  11. // 模拟点击页面跳转到活动页面A
  12. wx.navigateTo({
  13. url: '/pages/A/A'
  14. })
  15. }, 5000)
  16. }
  17. })
  18. <!--页面A的wxml-->
  19. <view wx:if="{{src}}">
  20. <web-view src="{{src}}"></web-view>
  21. </view>
  22. // 页面A
  23. Page({
  24. /**
  25. * 页面的初始数据
  26. */
  27. data: {
  28. src: ""
  29. },
  30. /**
  31. * 生命周期函数--监听页面初次渲染完成
  32. */
  33. onReady: function () {
  34. setTimeout(()=>{
  35. // 模拟点击跳转到页面B
  36. wx.navigateTo({
  37. url: '/pages/B/B'
  38. })
  39. }, 5000)
  40. },
  41. /**
  42. * 生命周期函数--监听页面显示
  43. */
  44. onShow: function () {
  45. let t = +new Date();
  46. this.setData({
  47. src: `https://www.baidu.com?t=${t}`
  48. })
  49. },
  50. onHide: function () {
  51. this.setData({
  52. src: ``
  53. })
  54. }
  55. })
  56. <!-- 页面B的wxml -->
  57. <web-view src="{{src}}"></web-view>
  58. // 页面B代码
  59. Page({
  60. /**
  61. * 页面的初始数据
  62. */
  63. data: {
  64. src: ""
  65. },
  66. /**
  67. * 生命周期函数--监听页面加载
  68. */
  69. onLoad: function (options) {
  70. // 页面不需要刷新 所以写到onLoad生命周期里
  71. this.setData({
  72. src: `https://m.mi.com/`
  73. })
  74. }
  75. })

   web-view的页面刷新场景是非常常见的,也与我们后面的章节密不可分,因此讲的还是比较详细的,希望能帮助到其他的开发者。

     5)精益求精,精简代码

        结合我之前的文章,微信小程序如何重写Page方法?以及重写Page方法给开发者带来的好处 我们可以把代码做的更简洁:将Page方法重新,把onHide生命周期卸载web-view的代码提取出来,如果有很多的页面需要web-view刷新H5的话,这样会大大节省我们的工作量和代码量。

        首先我们需要先定义一下web-view的页面变量及其含义

        refreshSrc:如果页面的data里定义里这个变量,且用这个变量来渲染web-view,则每次打开页面都需要刷新页面;注意:不需要刷新的页面不要把渲染web-view的src属性定义成该变量名

        精简后的代码

  1. app.js
  2. // app.js
  3. (function(){
  4. // 小程序原来的Page方法
  5. let originalPage = Page;
  6. // 我们自定义的Page方法
  7. Page = function(config){
  8. // todo 在这里我们可以给配置对象进行加工
  9. // 将配置对象继续想下传递给小程序原来的Page方法
  10. config.onHide = function(){
  11. //如果页面定义了这个变量 且变量有值则在onHide生命周期将该值置空
  12. if(this.data.refreshSrc){
  13. this.setData({
  14. refreshSrc: ''
  15. })
  16. }
  17. }
  18. originalPage (config);
  19. }
  20. })();
  21. App({
  22. onLaunch() {
  23. },
  24. globalData: {
  25. }
  26. })
  27. <!--首页的wxml-->
  28. <view class="container">
  29. </view>
  30. // 首页
  31. Page({
  32. data: {
  33. motto: '首页'
  34. },
  35. onReady(){
  36. setTimeout(()=> {
  37. // 模拟点击页面跳转到活动页面A
  38. wx.navigateTo({
  39. url: '/pages/A/A'
  40. })
  41. }, 5000)
  42. }
  43. })
  44. <!--页面A的wxml-->
  45. <view wx:if="{{refreshSrc}}">
  46. <web-view src="{{refreshSrc}}"></web-view>
  47. </view>
  48. // 页面A
  49. Page({
  50. /**
  51. * 页面的初始数据
  52. */
  53. data: {
  54. refreshSrc: ""
  55. },
  56. /**
  57. * 生命周期函数--监听页面初次渲染完成
  58. */
  59. onReady: function () {
  60. setTimeout(()=>{
  61. // 模拟点击跳转到页面B
  62. wx.navigateTo({
  63. url: '/pages/B/B'
  64. })
  65. }, 5000)
  66. },
  67. /**
  68. * 生命周期函数--监听页面显示
  69. */
  70. onShow: function () {
  71. let t = +new Date();
  72. this.setData({
  73. refreshSrc: `https://www.baidu.com?t=${t}`
  74. })
  75. }
  76. })
  77. <!-- 页面B的wxml -->
  78. <web-view src="{{src}}"></web-view>
  79. // 页面B代码
  80. Page({
  81. /**
  82. * 页面的初始数据
  83. */
  84. data: {
  85. src: ""
  86. },
  87. /**
  88. * 生命周期函数--监听页面加载
  89. */
  90. onLoad: function (options) {
  91. // 页面不需要刷新 所以写到onLoad生命周期里
  92. this.setData({
  93. src: `https://m.mi.com/`
  94. })
  95. }
  96. })

这部分还是为了小程序中有很多页面需要刷新web-view嵌套的H5,如果小程序中类似于页面A的页面不多,这部分则可以忽略 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/123907
推荐阅读
相关标签
  

闽ICP备14008679号