|
|
|
|
公众号矩阵

HarmonyOS ArkUI之自定义组件侧滑菜单(JS)

鸿蒙这次API7更新除了新增TS声明式开发之外,还有JS开发也增加了很多API,JS开发自定义组件越来越方便了。本文介绍最新出的插槽用法,实现侧滑菜单、支持两种风格、支持快速滑动打开关闭。

作者:梁青松来源:鸿蒙社区|2021-11-24 10:02

想了解更多内容,请访问:

51CTO和华为官方战略合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

前言

鸿蒙这次API7更新除了新增TS声明式开发之外,还有JS开发也增加了很多API,JS开发自定义组件越来越方便了。

本项目基于ArkUI中JS扩展的类Web开发范式,关于语法和概念直接看官网官方文档地址:

基于JS扩展的类Web开发范式1 基于JS扩展的类Web开发范式2

本文介绍最新出的插槽用法,实现侧滑菜单、支持两种风格、支持快速滑动打开关闭。

ArKUI系列文章

  • 【HarmonyOS ArkUI之仿微信朋友圈图片预览】
  • 【HarmonyOS ArkUI之仿微信图片选择】
  • 【HarmonyOS ArkUI之自定义组件侧滑菜单(JS)】

效果演示

风格一:内容页在菜单上面风格二:内容页在菜单下面

HarmonyOS ArkUI之自定义组件侧滑菜单(JS)-鸿蒙HarmonyOS技术社区HarmonyOS ArkUI之自定义组件侧滑菜单(JS)-鸿蒙HarmonyOS技术社区

主要知识点

触摸事件、自定义组件父子组件传递参数、api=7新出的slot插槽

实现思路

自定义组件的逻辑都在此目录下:entry/js/default/pages/drawer

主要使用onTouch相关事件,滑动改变菜单布局或内容布局的left偏移量,手指抬起使用动画完成偏移量

1、onTouch相关事件

只贴出了关键代码

  1.  /** 
  2.    * 触摸按下 
  3.    */ 
  4.   onTouchStart(event) { 
  5.       // 记录首次按下的x坐标 
  6.       this.pressX = event.touches[0].localX 
  7.       // 记录上次的x坐标 
  8.       this.lastX = this.pressX 
  9. ..... 
  10.   }, 
  11.   /** 
  12.    * 触摸移动 
  13.    */ 
  14.   onTouchMove(event) { 
  15.     // 当前x坐标 
  16.       let localX = event.touches[0].localX 
  17.       // 计算与上次的x坐标的偏移量 
  18.       let offsetX = this.lastX - localX; 
  19.       // 记录上次的x坐标 
  20.       this.lastX = localX 
  21.       // 累计偏移量 
  22.       this.offsetLeft -= offsetX 
  23.        
  24.       // 设置偏移量的范围 
  25.       ..... 
  26.   } 
  27.  
  28. ** 
  29.    * 触摸抬起 
  30.    */ 
  31.   onTouchEnd(event) { 
  32.        
  33.       ...... 
  34.        
  35.       // 手指抬起,根据情况,判断toX的值,也就是判断关闭或开启菜单的情况 
  36.       // 当移动偏移量大于菜单一半宽度,完全打开菜单,否则反之 
  37.       if (this.offsetLeft > this.menuWidth / 2) { 
  38.           toX = this.menuWidth 
  39.       } else { 
  40.           toX = 0 
  41.       } 
  42.        
  43.       ...... 
  44.        
  45.       // 开启动画 
  46.         this.startAnimator(toX)       
  47.        
  48.   } 
  49.   /** 
  50.    * 开启动画 
  51.    */ 
  52.   startAnimator(toX) { 
  53.       // 设置动画参数 
  54.       let options = { 
  55.           duration: ANIMATOR_DURATION, // 持续时长 
  56.           fill: 'forwards', // 启停模式:保留在动画结束状态 
  57.           begin: this.offsetLeft, // 起始值 
  58.           end: toX // 结束值 
  59.       }; 
  60.       // 更新动画参数 
  61.       this.animator.update(options) 
  62.       // 监听动画值变化事件 
  63.       this.animator.onframe = (value) => { 
  64.           this.offsetLeft = value 
  65.           this.changeMenuOffsetLeft() 
  66.       } 
  67.       // 开启动画 
  68.       this.animator.play() 
  69.   }, 

2、showStyle

0 第一种样式下,解决设置z-index之后菜单界面在内容下面,但点击事件却还在内容上面的问题。

初始化设置left偏移量

动画结束,判断菜单是否关闭,关闭直接设置菜单偏移量为负的菜单宽度

注意:目前使用插槽之后,预览器不走生命周期方法:onShow。

  1. export default { 
  2.     // 使用外部传入 
  3.     props: ['showStyle'],// 显示样式:0菜单在下面,1菜单在上面 
  4.       ...... 
  5.   } 
  6. ** 
  7.    * 界面显示 
  8.    */ 
  9.   onShow() { 
  10.       ..... 
  11.     // 设置菜单偏移量为负的菜单宽度,为了解决z-index设置后,菜单界面到内容下面, 
  12.       // 事件还停留到内容上面,导致点击菜单区域,响应的还是菜单点击事件 
  13.       this.menuOffsetLeft = -this.menuWidth 
  14.   } 

3、使用具名插槽封装

  1. <div id="drawer-container" class="drawer-container" on:touchstart="onTouchStart" 
  2.      on:touchmove="onTouchMove" on:touchend="onTouchEnd"
  3.  
  4.     <div class="drawer-content" style="left : {{ showStyle == 0 ? offsetLeft : 0 }} px; 
  5.             z-index : {{ zIndexContent }};" on:click="closeMenu"> 
  6.  
  7.     <!--具名插槽,根据名称加入对应的插槽中--> 
  8.         <slot name="content"></slot> 
  9.          
  10.     </div> 
  11.  
  12.     <stack class="drawer-menu" style="z-index : {{ zIndexMenu }};"
  13.         <div class="drawer-menu-background" style="opacity : {{ menuBgOpacity }};"></div> 
  14.         <div style="width : {{ menuWidth }} px; height : 100%; 
  15.                 left : {{ menuOffsetLeft }} px;" on:click="clickMenu"> 
  16.  
  17.         <!--具名插槽,根据名称加入对应的插槽中--> 
  18.             <slot name="menu"></slot> 
  19.  
  20.         </div> 
  21.     </stack> 
  22.  
  23. </div> 

4、index页面使用

  1. <!--引入自定义组件--> 
  2. <element name='drawer' src='../drawer/drawer.hml'></element> 
  3. <div class="container"
  4.     <!--通过传值设置样式--> 
  5.     <drawer show-style="0"
  6.         <!--根据名称加入对应的插槽中--> 
  7.         <div slot='content' class="content-layout"
  8.             <div class="title-bar"
  9.                 <text>主页</text> 
  10.             </div> 
  11.             <div class="mainpage-content"
  12.                 <text class="content1">我是内容页面</text> 
  13.                 <text class="content2">V1.0.0</text> 
  14.                 <text class="content2">梁迪迪</text> 
  15.             </div> 
  16.         </div> 
  17.  
  18.         <div slot='menu' class="menu-layout"
  19.             <div class="my-info"
  20.                 <image src="common/images/head_photo.png"></image> 
  21.                 <text>登录 | 注册</text> 
  22.             </div> 
  23.             <div class="menu-content"
  24.                 <div for="{{ listMenu }}" tid="{{ $item.id }}" on:click="menuSkip({{ $item.name }})"
  25.                     <image src="{{ $item.icon }}"></image> 
  26.                     <text>{{ $item.name }}</text> 
  27.                 </div> 
  28.             </div> 
  29.         </div> 
  30.     </drawer> 
  31. </div> 

结尾

每天进步一点点、需要付出努力亿点点。

想了解更多内容,请访问:

51CTO和华为官方战略合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

【编辑推荐】

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区
  2. 打造一款定制化鸿蒙发行版
  3. 鸿蒙开源第三方组件—SwipeCaptcha_ohos3.0旋转验证组件
  4. OpenHarmony源码解析之安全子系统 (应用权限管理)
  5. HarmonyOS自定义组件之分页功能组件封装实例
  6. HarmonyOS Sample之AI能力之NLU引擎服务
【责任编辑:jianghua TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

带你轻松入门 RabbitMQ

带你轻松入门 RabbitMQ

轻松入门RabbitMQ
共4章 | loong576

58人订阅学习

数据湖与数据仓库的分析实践攻略

数据湖与数据仓库的分析实践攻略

助力现代化数据管理:数据湖与数据仓库的分析实践攻略
共3章 | 创世达人

14人订阅学习

云原生架构实践

云原生架构实践

新技术引领移动互联网进入急速赛道
共3章 | KaliArch

42人订阅学习

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO官微