1. 开始

项目要在多个页面上加自定义导航栏,还要有渐变效果,就是随着页面上滑,导航栏透明度由0逐渐变为1。这里面有几个基本点需要注意下。

2. page的样式

page 不能是height: 100%,可以设置height: auto,这样才可以触发 onPageScroll。

3. onPageScroll

只有 page 才有 onPageScroll 事件。试验发现,mixin 和页面内都写了 onPageScroll 的话,都会触发。

如果把它放在 mixin 中,写成下面这样,可能会有问题:

data() {
  return {
    pageScrollTop: 0,
  };
},
onPageScroll({ scrollTop }) {
  this.pageScrollTop = scrollTop || 0;
},

因为自定义导航栏不一定要在页面级组件上,很多页面都是写在子组件里,而 mixin 是各个组件各自维护了一份data,所以无法传递。这也是Vue组件和小程序组件的不同之处。

解决方法有多个:

  • 将 onPageScroll 写在页面级组件上,然后获取到 scrollTop 后传给子组件,这种方法太麻烦
  • onPageScroll 依然写在 mixin 中,保存 scrollTop 到 vuex 的 state 中,然后在页面或者组件中获取这个 state

4. 性能问题

这里面还有两个性能相关的点要注意下:

  • 只有页面级组件或者个别组件需要用的数据,不要放在 mixin 的 data/computed 中。因为 mixin 是所有组件的混入,并且 uni-app 中所有 data 和 computed 都会作为渲染依赖(不管用没用到),可能会引起很多性能开销。
  • onPageScroll 中不要做复杂逻辑,不要频繁调用 setData,在 uni-app 中就是不要频繁更新 data。因为小程序是双线程通信,逻辑层更改数据要先到 native层,再传到渲染层,中间可能还有 JSON.stringify 等操作。

5. 方案

综上,目前采用的方案是:

  • mixin中,监听 onPageScroll,因为这个在只会在当前页面触发,子组件会被忽略,所以写在这里并不影响性能。

  • vuex 中保存 pageScrollTop、mpHeaderHeight,及一个衍生变量 mpHeaderBg。

  • 然后,需要使用 mpHeaderBg 的页面,去引用 vuex 中的变量。

  • 如果想要在一个新页面加上渐变导航,只需要引用 vuex 中的 mpHeaderBg 即可。

6. 代码

// 某个页面
<template>
  <MatchHeaderMp
    :header-bg="mpHeaderBg"
  />
</template>
<script>
computed: {
  mpHeaderBg() {
    // getMpHeaderBg 方法来自于 mixin
    return this.getMpHeaderBg();
  },
}
</script>
// mixin
export const uniSystemInfoMixin = {
  data() {
    return {
      // page-meta上设置的根标签字体大小
      mixinRootFontSize: 50,
    };
  },
  mounted() {
    // 设置根字体大小
    this.onSetFontSize();
  },
  onPageScroll({ scrollTop }) {
    const mpHeaderHeight = this.$store.state.wxHeader.mpHeaderHeight || 44;
    const pageScrollTop =  this.$store.getters.['wxHeader/pageScrollTop'] || 44;
    const parsedScrollTop = scrollTop > mpHeaderHeight ? mpHeaderHeight : scrollTop;

    // 如果滑动值大于 mpHeaderHeight,就不再更新 data
    if (parsedScrollTop === mpHeaderHeight && pageScrollTop === mpHeaderHeight) {
      return;
    }
    this.$store.commit('wxHeader/setPageScrollTop', parsedScrollTop);
  },
  beforeDestroy() {
    if (this.mpType === 'page') {
      this.$store.commit('wxHeader/setPageScrollTop', 0);
    }
  },
  methods: {
    getMpHeaderBg() {
      const pageScrollTop = this.getMpPageScrollTop();
      const mpHeaderHeight = this.$store.state.wxHeader.mpHeaderHeight || 44;
      return `rgba(255, 255, 255, ${Math.min(1, pageScrollTop / mpHeaderHeight)})`;
    },
    getMpPageScrollTop() {
      const curPageName = this.getCurPageName();
      const pageScrollTopMap = this.$store.state.wxHeader.pageScrollTopMap || {};
      return pageScrollTopMap[curPageName] || 0;
    },
    getCurPageName() {
      const pages = getCurrentPages();
      return pages[pages.length - 1].route;
    },
    onSetFontSize() {
      // 宽度 375 时(iphone6),rootFontSize为50,则一份为 375/50=7.5
      const screenNumber = 7.5;
      const that = this ;

      if (that.mpType === 'page') {
        // 窗体改变大小触发事件
        uni.onWindowResize((res) => {
          if (res.size.windowWidth) {
            that.mixinRootFontSize = parseFloat(res.size.windowWidth) / screenNumber;
          }
        });

        // 打开获取屏幕大小
        uni.getSystemInfo({
          success(res) {
            const fontsize = res.screenWidth / screenNumber;
            that.mixinRootFontSize = fontsize;
            const mpHeaderHeight = res.statusBarHeight   44;
            that.$store.commit('wxHeader/setMpHeaderHeight', mpHeaderHeight);
          },
        });
    }
    },
  },
};
// store/modules/wx-header.js
const wxHeaderStore = {
  namespaced: true,
  state: () => ({
    // 存放多个页面的pageScrollTop
    pageScrollTopMap: {},
    // 状态栏高度
    mpHeaderHeight: 44,
  }),
  mutations: {
    setPageScrollTop(state, pageScrollTop = 0) {
      const curPageName = getCurPageName();
      state.pageScrollTopMap = {
        ...state.pageScrollTopMap,
        [curPageName]: pageScrollTop,
      };
    },
    setMpHeaderHeight(state, mpHeaderHeight) {
      state.mpHeaderHeight = mpHeaderHeight;
    },
  },
};

7. 注意事项

  • 不要多个页面共享同一个变量,会存在多个页面互相影响的可能。
  • 小程序重新进入某个页面,都会重新回到顶部,包括page和所有scroll view,所以要在beforeDestroy中重置pageScrollTop

总结

到此这篇关于uni-app小程序沉浸式导航实现的文章就介绍到这了,更多相关uni-app小程序沉浸式导航内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

uni-app小程序沉浸式导航实现的全过程的更多相关文章

  1. angular实现导航菜单切换

    这篇文章主要为大家详细介绍了angular实现导航菜单切换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. 微信小程序实现页面导航的方法详解

    这篇文章主要为大家详细介绍一下微信小程序实现页面导航的几种方法以及帮助大家掌握如何使用页面之间的导航跳转,感兴趣的可以了解一下

  3. uni-app分包项目实战总结

    在使用uniapp开发过程中,随着我们的代码工程越来越大,必然会面临一个问题,就是打出来的包会越来越大,下面这篇文章主要给大家介绍了关于uni-app分包项目实战的相关资料,需要的朋友可以参考下

  4. js+css实现三级导航菜单

    这篇文章主要为大家详细介绍了js+css实现三级导航菜单,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. Android Studio 全屏沉浸式透明状态栏效果的实现

    这篇文章主要介绍了Android Studio 全屏沉浸式透明状态栏效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. 详解iOS应用中自定义UIBarButtonItem导航按钮的创建方法

    这篇文章主要介绍了iOS应用中自定义UIBarButtonItem导航按钮的创建方法,文中举了一个自定义图片的UIBarButtonItem实例,比较具有代表性,需要的朋友可以参考下

  7. vue2.0实现选项卡导航效果

    这篇文章主要为大家详细介绍了vue2.0实现选项卡导航效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  8. iOS App开发中导航栏的创建及基本属性设置教程

    这篇文章主要介绍了iOS App开发中导航栏的创建及基本属性设置教程,即用UINavigationController来编写navigation,示例代码为Objective-C语言,需要的朋友可以参考下

  9. CSS3 media queries结合jQuery实现响应式导航

    这篇文章主要为大家详细介绍了CSS3 media queries结合jQuery实现响应式导航,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. jQuery实现简单的下拉菜单导航功能示例

    这篇文章主要介绍了jQuery实现简单的下拉菜单导航功能,涉及jQuery针对页面元素的遍历与节点修改相关操作技巧,需要的朋友可以参考下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部