微信小程序|开发实战篇之五-slide-view滑动菜单组件

前言

实战篇内容参考:
1、Lin Ui开源组件源码分析。https://doc.mini.talelin.com/
2、开发过程遇到问题。

1、微信小程序操作dom元素

操作dom元素需要JavaScript基础,因此学习之。

先介绍一些微信小程序的API函数:
参考文档:https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.in.html

1)wx.createSelectorQuery()2)wx.createSelectorQuery().in(this) // 存在自定义组件使用该创建搜索器函数3)SelectorQuery.select(string selector)4)NodesRef.boundingClientRect(function callback)5)SelectorQuery.exec(function callback)

(1)返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替。
(2)将选择器的选取范围更改为自定义组件 component 内。(初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点)。
(3)在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息。
(4)添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery
回调函数,在执行 SelectorQuery.exec 方法后,节点信息会在 callback 中返回。
(5)执行所有的请求。请求结果按请求次序构成数组,在callback的第一个参数中返回。

1.1 slide-view组件的wxml骨架文件

滑动组件slide-view没有滑动的初始样式为:
在这里插入图片描述
向左滑动的样式为:
在这里插入图片描述

1.1.1 涉及movable-view组件属性

因为class和style样式文件对于js逻辑而言不重要,因此删去以免影响js的阅读。

<!--components/slide-view/index.wxml-->
<movable-area class="" style="">
  <movable-view direction="horizontal" class=""
  out-of-bounds="{{out}}" damping="20" disabled="{{disabled}}"
  x = "{{x}}" style="" 
  intertia bindtouchend="onTouchEnd" bindtouchstart="onTouchStart" bindchange="onChange">
    <view class="" style="">
      <slot name="left"></slot>
    </view>
    <view class="" mut-bind:tap="onRightTap" style="">
      <slot name="right"></slot>
    </view>
  </movable-view>
</movable-area>
  1. 首先最外层是movable-area表示中间的元素移动的范围。开发者使用时可以对其widthheight进行设置。
  2. 子节点是movable-view表示可移动的视图容器,在页面中可以拖拽滑动。movable-view必须在 movable-area 组件中,并且必须是直接子节点,否则不能移动。(1)direction设置移动方向—水平移动;(2)out-of-bounds表示是否允许移动出范围—false表示不允许;(3)damping表示阻尼系数,值越大表示;(4)disabled表示是否禁用移动模块—true的就是禁用移动;(5)x,y属性表示各方向上的移动—定义x轴方向的偏移,如果x的值不在可移动范围内,会自动移动到可移动范围;改变x的值会触发动画;(6)intertia表示滑块movable-view是否带有惯性;(7)bindtouchstartbindtouchend表示手指触摸动作开始(手指放上去开始直到结束)、手指触摸动作结束(手指拿开)。bind属于事件参考【小程序事件详情】;(8)两个view中包裹slot插槽,用来插入开发者需要显示的组件。
    更多movable-view信息,详细参考:【小程序的movable-view】

1.2 slide-view组件的js文件

1.2.1 js中相关参数解释

外部传入的数据列表properties:

// 单位px
const _windowWidth = wx.getSystemInfoSync().windowWidth;
 /**
   * 组件的属性列表
   */
  properties: {
  
    // 组件显示区域的上边距
    top: {
      type: Number,
      value: 0
    },
    // 组件显示区域的上边距
    bottom: {
      type: Number,
      value: 0
    },
    // 组件显示区域的宽度,默认按全屏宽度
    width: {
      type: Number,
      value: _windowWidth
    },
    // 组件显示区域的高度
    height: {
      type: Number,
      value: 100
    },
    // 组件显示滑动区域的宽度,默认不能滑动
    slideWidth: {
      type: Number,
      value: 0
    },
    // 滑动的阈值 单位px
    threshold: {
      type: Number,
      value: 0
    },
    // 禁用移动
    disabled: {
      type: Boolean,
      value: false
    },
    // 自动关闭
    autoClose: {
      type: Boolean,
      value: false
    }
  },

使用x的值来控制movable-view的滑动距离。

/**
   * 组件的初始数据
   */
  data: {
    // 默认是组件的宽度 单位rpx
    viewWidth: _windowWidth,
    // movable-view偏移量
    x: 0,
    // movable-view是否可以出界
    out: false
  },

  ready() {
    this.updateRight();
  },

1.2.2 updateRight()方法分析

该方法是在组件生命周期的ready()方法中直接调用。主要是组件在页面布局之后调用。
updateRight()方法的作用:

获取右侧滑动区域宽度 viewWidth(不同机型的单位px转换成rpx)、并指定一个滑动阈值_threshold(一个私有变量)。

在这里插入图片描述

// 获取右侧滑动区域宽度、并指定一个滑动阈值。
updateRight() {

    const me = this;
    // 创建节点查询器,并且将选择器选取范围更改在component组件内
    const query = wx.createSelectorQuery().in(this);
    // 在当前组件下名叫right的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息
    query.select('.right').boundingClientRect(function(res){
       me._slideWidth = res.width;
       // 右侧区域小于50px就按自身宽度,大于则按50px
       let width = res.width <= 50 ? res.width : 50;
       // 滑动阈值如果设定就按设定的,没有就按width的长度
       me._threshold = me.properties.threshold ? me.properties.threshold : width;
       // 不同机型的px换算为rpx
       me._viewWidth = me.data.width + res.width * (750 / _windowWidth);
       me.setData({
         viewWidth: me._viewWidth
       });
      
      })).exec()
    },

1.2.3 onTouchEnd()方法分析

  • 关于const { title} = this写法是ES6的赋值语句简写,等同于const title = this.propeties.title;当然参数名称是需要一致的,都必须为title。
// ES6的写法
const {
        _endX,
        _startX,
        _threshold
      } = this;
      
// 等同于一般写法
const _endX = this._endX;
const _startX = this._startX;
const _threshold = this._threshold;

(1)onTouchStart()是将当前x坐标赋值给私有变量_startX,保存x起点坐标。
(2)onTouchEnd()是考虑各种滑动情况,然后自动完成滑动操作。
主要考虑是以下几个逻辑:

  • 当向右滑动的距离差超过阈值时,直接关闭right;
  • 向左滑动距离差超过阈值时,打开right部分;
  • 考虑一些细节情况:right没有打开,向左滑动小距离,这时right不需要打开;
  • 考虑一些细节情况:right已经打开,向右滑动小距离,这时right打开;
  • 考虑一些细节情况:right已经打开,向右滑动大距离,这时right关闭;

当right已经打开,仍然向左滑动这时使用onChange()方法来设置movable-view的出界情况:

// 根据滑动的范围设定是否运行movable-view出界
    onChange(e) {
      if (!this.data.out && e.detail.x < -this._threshold) {
        this.setData({
          out: true
        });
      } else if (this.data.out && e.detail.x >= -this._threshold) {
        this.setData({
          out: false
        });
      }
    },
// 设置点击起始x的坐标
    onTouchStart(e) {
      this._startX = e.changedTouches[0].pageX;
    },

    // 滑动范围超过阈值则自动完成剩余滑动
    onTouchEnd(e) {

      if(this.properties.disabled) return; // 禁止滑动

      this._endX = e.changedTouches[0].pageX;
      this._length = this._endX - this._startX;

      const {
        _endX,
        _startX,
        _threshold
      } = this;

      // 不管right有无打开,往右滑超过阈值,都关闭right
      if(this._length > _threshold) {
        this.setData({
          popup: false,
          x: 0
        });
        this.onCloseTap();
      }

      // 向左滑动超过阈值,就自动打开right
      if(_startX - _endX >= _threshold) {
        this.setData({
          x: -this._slideWidth,
          popup: true
        });
        this.onOpenTap();
      }else if (_startX - _endX < _threshold && _startX - _endX > 0 && this.data.popup != true) { // 没有打开right,左滑小距离
        this.setData({
          x: 0
        });
        this.onCloseTap();

      } else if (_endX - _startX >= _threshold) { // 已经打开right,往右滑大距离
        this.setData({
          x: 0
        });
        this.onCloseTap();

      }else if (_endX - _startX < _threshold && _endX - _startX > 0) { // 已经打开right,还往右滑小距离
        this.setData({
          x: -this._slideWidth
        });
        this.onOpenTap();

      }

    },

1.2.4 onRightTap()方法分析

// 点击 右边区域
    onRightTap() {
     let detail = 'click right';
     let option = { bubbles: true, composed: true };
     // 如果自动关闭
     if (this.properties.autoClose) {
      this.setData({
        popup: false,
        x: 0
      });
      this.onCloseTap();
     }

     this.triggerEvent('slidetap', detail, option)
    },

点击右边的不同text我采用了一种比较笨的办法,后续有改进方法再替换:
我给每个text绑定tap方法,绑定数据text,然后在rightClick方法中设置页面变量text的值,从slidetap方法中获取页面中变量text的值。

<text class="like" bind:tap="rightClick" data-text="{{like}}">{{like}}</text>
<text class="share" bind:tap="rightClick" data-text="{{share}}">{{share}}</text>
<text class="del" bind:tap="rightClick" data-text="{{del}}">{{del}}</text>
slideTap(event){
    console.log(event.currentTarget.dataset.id);
    console.log(this.data.text);
 },

rightClick(event){
 	this.data.text = event.currentTarget.dataset.text;
},
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值