当前位置:首页 > IT科技类资讯

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

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

和华为官方合作共建的定义鸿蒙技术社区

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)】

效果演示

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

主要知识点

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

实现思路

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

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

1、定义onTouch相关事件

只贴出了关键代码

 /**    * 触摸按下    */   onTouchStart(event) {        // 记录首次按下的侧滑菜单x坐标       this.pressX = event.touches[0].localX       // 记录上次的服务器托管x坐标       this.lastX = this.pressX .....   },   /**    * 触摸移动    */   onTouchMove(event) {      // 当前x坐标       let localX = event.touches[0].localX       // 计算与上次的x坐标的偏移量       let offsetX = this.lastX - localX;       // 记录上次的x坐标       this.lastX = localX       // 累计偏移量       this.offsetLeft -= offsetX       // 设置偏移量的范围       .....   } **    * 触摸抬起    */   onTouchEnd(event) {        ......       // 手指抬起,根据情况,判断toX的值,也就是判断关闭或开启菜单的情况       // 当移动偏移量大于菜单一半宽度,完全打开菜单,否则反之       if (this.offsetLeft > this.menuWidth / 2) {            toX = this.menuWidth       } else {            toX = 0       }       ......       // 开启动画         this.startAnimator(toX)         }   /**    * 开启动画    */   startAnimator(toX) {        // 设置动画参数       let options = {            duration: ANIMATOR_DURATION, // 持续时长           fill: forwards, // 启停模式:保留在动画结束状态           begin: this.offsetLeft, // 起始值           end: toX // 结束值       };       // 更新动画参数       this.animator.update(options)       // 监听动画值变化事件       this.animator.onframe = (value) => {            this.offsetLeft = value           this.changeMenuOffsetLeft()       }       // 开启动画       this.animator.play()   }, 

2、showStyle

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

初始化设置left偏移量

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

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

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

3、使用具名插槽封装

<div id="drawer-container" class="drawer-container" on:touchstart="onTouchStart"      on:touchmove="onTouchMove" on:touchend="onTouchEnd">     <div class="drawer-content" style="left : { {  showStyle == 0 ? offsetLeft : 0 }} px;             z-index : { {  zIndexContent }};" on:click="closeMenu">     <!--具名插槽,根据名称加入对应的插槽中-->         <slot name="content"></slot>     </div>     <stack class="drawer-menu" style="z-index : { {  zIndexMenu }};">         <div class="drawer-menu-background" style="opacity : { {  menuBgOpacity }};"></div>         <div style="width : { {  menuWidth }} px; height : 100%;                 left : { {  menuOffsetLeft }} px;" on:click="clickMenu">         <!--具名插槽,根据名称加入对应的插槽中-->             <slot name="menu"></slot>         </div>     </stack> </div> 

4、index页面使用

<!--引入自定义组件--> <element name=drawer src=../drawer/drawer.hml></element> <div class="container">     <!--通过传值设置样式-->     <drawer show-style="0">         <!--根据名称加入对应的插槽中-->         <div slot=content class="content-layout">             <div class="title-bar">                 <text>主页</text>             </div>             <div class="mainpage-content">                 <text class="content1">我是内容页面</text>                 <text class="content2">V1.0.0</text>                 <text class="content2">梁迪迪</text>             </div>         </div>         <div slot=menu class="menu-layout">             <div class="my-info">                 <image src="common/images/head_photo.png"></image>                 <text>登录 | 注册</text>             </div>             <div class="menu-content">                 <div for="{ {  listMenu }}" tid="{ {  $item.id }}" on:click="menuSkip({ {  $item.name }})">                     <image src="{ {  $item.icon }}"></image>                     <text>{ {  $item.name }}</text>                 </div>             </div>         </div>     </drawer> </div> 

结尾

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

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

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

https://harmonyos.51cto.com

分享到:

滇ICP备2023006006号-16