小程序单页面应用,解决跳转10层问题

问题背景

小程序存在10层爆栈问题,在开发中因为流程过长,且存在其他页面跳转当前流程的问题,如何确保跳转不超过10层?

解决思路

将当前完整流程做一个单页面应用,每一个步骤作为一个组件,控制其显示隐藏来实现。

需要解决的问题

1、共用一个页面需要自定义导航头,各手机兼容定位;
2、如何控制页面的前进和后退,保证页面顺序正常;
3、一个页面内,如何使页面重复渲染;
4、返回上一页,如何保留之前选中的数据;
5、父子组件传值问题;
6、部分方法在子组件内如何使用问题(如触底监听等)

内容实现

初始页面布局

layout.wxml(主页面模版)

<!-- 顶部导航 -->
<nav></nav>

<!-- 内容 -->
<view class="content">
  <!-- 子组件 -->
  <child1></child1>
  <child2></child2>
</view>   

<!-- 底部按钮 -->
<bottom-btn></bottom-btn>

layout.json

{
  "usingComponents": {
    "nav": "../../components/navigation/navigation",
    "bottom-btn": "../../components/bottomBtn/bottomBtn",
    "child1": "../../components/child1/index",
    "child2": "../../components/child2/index",
  },
  "navigationStyle": "custom", //开启自定义导航头
  "navigationBarTitleText": ""
}

自定义导航头

navigation.wxml

<!-- 控制导航距顶高度 -->
<cover-view class="nav" style="height:{{navheight}}px">
    <cover-view class="content" scroll-top="0">
    	<!-- 回退按钮处理 -->
        <cover-view class="left" bindtap="bindNav">
            <cover-image class="ico" src="../../resources/arrow-left.png" mode="widthFix">
            </cover-image>
        </cover-view>
        <!-- 动态修改标题 -->
        <cover-view class="title" wx:if="{{title}}">
            {{title}} 
        </cover-view>
    </cover-view>
</cover-view>

navigation.js

const app = getApp();
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    title: String //外部传入的标题
  },

  lifetimes: {
    attached: function() {
      // 在组件实例进入页面节点树时执行
      this.isSupportNav()
    },
    detached: function() {
      // 在组件实例被从页面节点树移除时执行
    }
  },
  // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
  attached: function() {
    // 在组件实例进入页面节点树时执行
    this.isSupportNav()
  },
  detached: function() {
    // 在组件实例被从页面节点树移除时执行
  },

  /**
   * 组件的初始数据
   */
  data: {
    statusBarHeight: 0,
    navheight: 0
  },

  /**
   * 组件的方法列表
   */
  methods: {
  	// 回退按钮控制
    bindNav: function(){
      this.triggerEvent('nav', {})
    },
    /**
     * 是否支持自定义导航,计算距顶高度
     */
    isSupportNav: function(){
      const res = wx.getSystemInfoSync()
      // 判断是否是安卓操作系统 (标题栏苹果为44px,安卓为48px)
      let titleH;
      if(res && res['system']){
        if(res['system'].indexOf('Android')>0){
          titleH = 48
        }else{
          titleH = 44
        }
        const navheight = titleH + res['statusBarHeight']
        this.setData({
          navheight
        })
        //将高度传入主页面,确定页面内容距顶部高度
        this.triggerEvent('nh', navheight)
      }
    }
  }
})

控制页面显隐

参数说明

wx:if 控制页面初次加载
hidden 保留页面会退数据
this.onShow() 促使页面重新渲染
pageStack:[] 页面栈
pageCtrl 页面层级

父页面
layout.wxml

<!-- 顶部导航 -->
<nav title="{{title}}" bind:nav="bindNav" bind:nh="getTopHeight"></nav>

<!-- 内容 -->
<view class="content">
  <!-- 子组件 -->
  <child1 wx:if="{{pageCtrl>=1}}" hiddenFlag="{{pageStack.length==1}}" bind:handleLogic="handleLogic" bind:setPageTitle="setPageTitle" bind:handleLogic="handleLogic"></child1>
  <child2 wx:if="{{pageCtrl>=2}}" hiddenFlag="{{pageStack.length==2}}" bind:handleLogic="handleLogic" bind:setPageTitle="setPageTitle"></child2>
</view>   

<!-- 底部按钮 -->
<bottom-btn></bottom-btn>

layout.js

Page({
  /**
   * 页面的初始数据
   */
  data: {
    pageStack: [{}], // 页面栈
    pageCtrl: 1
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {},
  onShow: function(){
    if(typeof this.data.pageStack == 'number'){
      const len = this.data.pageStack
      const arr = []
      for(let i = 0; i < len; i++){
        arr.push({})
      }
      this.setData({
        pageStack: arr
      })
    }
  },
  /**
   * 自定义导航,返回上一页
   */
  bindNav: function(){ 
    if(this.data.pageStack.length>1){
      const len = this.data.pageStack.length - 1
      const pageCtrl = this.data.pageCtrl - 1
      this.setData({
        pageStack: len,
        pageCtrl
      })
      this.onShow()
      return;
    }
    wx.navigateBack({
      delta: 1
    })
  },
  /**
   * 修改顶部标题
   */
  setPageTitle: function(e){
    this.setData({
      title: e.detail
    })
  },
  /**
   * 自定义底部按钮跳转,页面栈加一
   */
  handleLogic: function(){
    const pageCtrl = this.data.pageCtrl + 1
    this.setData({
      pageStack: this.data.pageStack.push({}),
      pageCtrl
    })
    this.onShow()
  },
  // 获取导航头传过来的高度
  getTopHeight: function(e){
    this.setData({
      navheight: e.detail
    })
  }
})

子页面
child1.wxml

<view class="child1" hidden="{{!hiddenFlag}}">
  <view class="content">子页面内容</view>
  <!-- 触发跳转下一页按钮 -->
  <bottom-btn bindtap="nextPage"></bottom-btn>
</view>

child1.js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    hiddenFlag: {
      type: Boolean
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
      
  },
  attached: function(){
    this.getInitInfo()
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 获取页面初始配置信息
    getInitInfo(){
      
    },
    // 跳转相关逻辑
    nextPage(){
    	this.triggerEvent('handleLogic');
    }
  }
})

左滑回退

layout.html

<view class="content" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd">
</view>

layout.js

//获取应用实例
const app = getApp();
var startX, endX;
var moveFlag = true;// 判断执行滑动事件

Page({
  touchStart: function (e) {
    startX = e.touches[0].pageX; // 获取触摸时的原点
    moveFlag = true;
  },
  // 触摸移动事件
  touchMove: function (e) {
    endX = e.touches[0].pageX; // 获取触摸时的原点
    if (moveFlag) {
      if (endX - startX > 50) {
        // 右滑逻辑
        moveFlag = false;
      }
      if (startX - endX > 50) {
        // 左滑逻辑
        moveFlag = false;
      }
    }
  },
  // 触摸结束事件
  touchEnd: function (e) {
    moveFlag = true; // 回复滑动事件
  }
})

子组件上拉加载问题(父组件调用子组件方法)

小程序主页面的onReachBottom方法可以监听到页面是否到底部,然后调用接口可实现上拉加载的功能。但是该方法在组件中无效,接口调用又在子组件中,所以需要在父页面的onReachBottom方法中调用子页面的方法。
组件调用定义id,通过id调用子组件方法
layout.html

<child id="search"></child>

layout.js

// 上拉加载
onReachBottom: function () {
  if(this.data.pageStack.length===3){
    this.selectComponent('#search').getList()//后台获取新数据并追加渲染
  }
}

存在问题

1、ios手机右滑自动回退上一页,目前无法禁止

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值