zoukankan      html  css  js  c++  java
  • 微信小程序:事件绑定

    小程序中绑定事件,通过bind关键字来实现。如bindinput,bindtap(绑定点击事件)bindchange等。

    什么是事件

    • 事件是视图层到逻辑层的通讯方式。
    • 事件可以将用户的行为反馈到逻辑层进行处理。
    • 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
    • 事件对象可以携带额外信息,如 id, dataset, touches

    事件的使用方式

    1、在组件中绑定一个事件处理函数。

    bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。

    <view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>

    2、在相应的Page定义中写上相应的事件处理函数,参数是event。

    Page({
      tapName: function(event) {
        console.log(event)
      }
    })

    可以看到log出来的信息大致如下:注意view标签的id属性值为e.currentTarget.id,自定义属性hi值为:e.currentTarget.dataset.hi,

    {
      "type":"tap",
      "timeStamp":895,
      "target": {
        "id": "tapTest",
        "dataset":  {
          "hi":"Weixin"
        }
      },
      "currentTarget":  {
        "id": "tapTest",
        "dataset": {
          "hi":"Weixin"
        }
      },
      "detail": {
        "x":53,
        "y":14
      },
      "touches":[{
        "identifier":0,
        "pageX":53,
        "pageY":14,
        "clientX":53,
        "clientY":14
      }],
      "changedTouches":[{
        "identifier":0,
        "pageX":53,
        "pageY":14,
        "clientX":53,
        "clientY":14
      }]
    }

    事件分类:

    事件分为冒泡事件和非冒泡事件:

    1. 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
    2. 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。

    WXML的冒泡事件列表:

    touchstart:手指触摸动作开始

    touchmove:手指触摸后移动

    touchcancel:手指触摸动作被打断,如来电提醒,弹窗

    touchend:手指触摸动作结束

    tap:手指触摸后马上离开

    longpress:手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发

    longtap:手指触摸后,超过350ms再离开(推荐使用longpress事件代替)

    transitionend:会在 WXSS transition 或 wx.createAnimation 动画结束后触发

    animationstart:会在一个 WXSS animation 动画开始时触发

    animationiteration:会在一个 WXSS animation 一次迭代结束时触发

    animationend:会在一个 WXSS animation 动画完成时触发

    touchforcechange:在支持 3D Touch 的 iPhone 设备,重按时会触发

    注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(详见各个组件)

    一、绑定输入事件bindinput

    1、 需要给input标签绑定input事件,这个事件bindinput在当值改变时就会触发

    2、 编写input事件的执行逻辑。

    3、 通过事件源对象(e)来获取输入框中的值(e.detail.value),然后赋值给num.

     

     

    把输入框的值赋值给data当中使用setData方法

    获取输入框的值(e.detail.value)自定义属性(e.currentTarget.dataset .xxx)都是从事件源对象(e)获取的。

    获取data数据模型中的值是通过this.data.xx来获取的。注意:微信小程序中获取数据模型中的值和给数据模型中的属性赋值都与vue中的不一样。

    二、绑定单击事件bindtap

    绑定事件的时候不能直接进行传参,否则会将方法名连同参数一起当作方法名。只能通过自定义属性的方式传参

    自定义属性 operation,

     

     获取输入框的值:e.detail.value;获取自定义属性的值:e.currentTarget.dataset.xxx;给data中的属性赋值:this.setData();获取data数据模型中的值:this.data.xxx;

     绑定事件时不能带参数,不能带括号。事件传值通过自定义属性的方式。在事件触发时获取数据。

     三、绑定手指触摸动作开始bindtouchstart和结束bindtouchend

    touches:数组,触摸事件,当前停留在屏幕中的触摸点信息的数组;touches 是一个数组,每个元素为一个 Touch 对象(canvas 触摸事件中携带的 touches 是 CanvasTouch 数组)。 表示当前停留在屏幕上的触摸点。

    changedTouches:数组,触摸事件,当前变化的触摸点信息的数组;changedTouches 数据格式同 touches。 表示有变化的触摸点,如从无变有(touchstart),位置变化(touchmove),从有变无(touchend、touchcancel)。

    index.wxml中代码:

    外层循环显示一级菜单,点击一级菜单时触发isOpen函数并传递id,且刚开始时,二级菜单时隐藏的状态;一开始时数据模型中的hidden属性为true,即一级菜单右侧显示的都是扩展的图标,

    1、点击一级菜单时,先获取被点击菜单的id,获取数据模型中的menuList,遍历menuList,如果某个菜单的id等于当前被点击的菜单的id,则将给菜单item的hidden属性值取反,即由原来的隐藏改为显示,另外一级菜单右侧的扩展图标改为collapse图标

    内层循环显示二级菜单,点击二级菜单时,触发menuClick函数并传递name.

    1、点击二级菜单时先获取当前被点击菜单的name,如果当前被点击的菜单的name值为“企业信息管理,则通过wx.relaunch()方法跳转到该页面”

    <view class="leftMenu" bindtouchstart='touchStart' bindtouchend="touchEnd" animation="{{animation}}">
      <view class="item"  wx:for="{{menuList}}" wx:for-index="idx" wx:for-item="item" wx:key="idx">
          <view bindtap="isOpen" class="menu" data-id="{{item.id}}">
              <view>
                  <image class="img" src="/static/menu.png" mode="aspectFill"/><text class="name">{{item.name}}</text>
              </view>
              <view>
                 <image class="icon_img" src="{{item.hidden ? '/static/expand.png' : '/static/collapse.png'}}" mode="aspectFill"/>
              </view>
          </view>
          <view hidden="{{item.hidden}}">
              <block wx:for="{{item.children}}"  wx:for-index="index" wx:for-item="items" wx:key="index">
                  <view class="submenu" bindtap="menuClick" data-name="{{items.name}}">
                      <view>
                          <text class="name">{{items.name}}</text>
                      </view>
                  </view>
              </block>
          </view>
      </view>
    </view>

    index.js中的代码:

    bindtouchstart事件给触摸点的定位赋值,bindtouchend将触摸点现在的定位和原来的定位进行比较,从而确定是左滑还是右滑,进而控制菜单是否显示。

    1、小程序加载时即从后台获取了menuList,

    2、首页(index)页面加载时(onLoad),先从storage中获取menuList,在循环遍历,

    先通过父id为0且菜单名称不为首页来过滤得到所有的一级菜单,再将所有的一级菜单的children属性置空,给每个item都添加hidden属性,且值为true。

    再对menuList中所有的item进行遍历,如果父id为当前item的id,则将菜单放入当前item的children数组中,再讲当前菜单放入menuList中。最后将menuList赋值个数据模型中的menuList,这样打开首页时,menuList就是已经过滤掉首页的menuList。

    3、创建一个动画实例animation

    4、将数据模型中的hidden属性置为false,这样,一开始时二级菜单为隐藏状态。

    //index.js
    //获取应用实例
    const app = getApp()
    
    Page({
      data: {
        hidden:true,
        menuList:[]
      },
      touchStart:function(e){
        this.setData({
            "touch.x": e.changedTouches[0].clientX,
            "touch.y": e.changedTouches[0].clientY
        });
      },
      touchEnd:function(e){
          let x = e.changedTouches[0].clientX;
          let y = e.changedTouches[0].clientY;
        var turn = this.getTouchData(x,y,this.data.touch.x,this.data.touch.y);
        if(turn == 'left'){
            this.animation.translateX(-220).step();    //  在x轴平移-220px,即向左平移220px,调用实例的step()方法来描述动画
            this.setData({ animation: this.animation.export() })  // 最后通过动画实例的 export 方法导出动画数据传递给组件的 animation
        }else if(turn == 'right'){
            this.animation.translateX(0).step();
            this.setData({ animation: this.animation.export() })
        }
      },
      getTouchData:function(endX, endY, startX, startY){
        let turn = "";
        if (endX - startX > 20 && Math.abs(endY - startY) < 30) {      //右滑
            turn = "right";
        } else if (endX - startX < -20 && Math.abs(endY - startY) < 30) {   //左滑
            turn = "left";
        }
          return turn;
      },
      isOpen:function(e){
        var id = e.currentTarget.dataset.id;   // 点击一级菜单时,先获取被点击菜单的id,
        var menuList = this.data.menuList;   // 获取数据模型中的menu,
        menuList.forEach((item,index) => {   // 遍历menuList,如果某个菜单的id等于当前被点击的菜单的id,则将给菜单item的hidden属性值取反,即由原来的隐藏改为显示。
            var id2 = item.id;
            if(id2 == id){
                item.hidden = !item.hidden;
            }else{
                item.hidden = true;
            }
        });
        this.setData({menuList:menuList});
      },
      menuClick:function(e){
          var name = e.currentTarget.dataset.name;  // 点击二级菜单时先获取当前被点击菜单的name
          if(name == '企业信息管理'){     // 如果当前被点击的菜单的name值为“企业信息管理,则跳转到该页面”
              wx.reLaunch({
                url: '/pages/demo/index/index'
              })
          }
      },
      getMenuList:function(list){
        var menuList = [];
        list.forEach((item,index) => {
            var id = item.id;
            var name = item.name;
            var parentId = item.parentId;
            if(parentId == 0 && name != '首页'){//过滤平台的首页
                //第一层级
                item.children = [];
                item.hidden = true;
                list.forEach((jtem,jndex) => {
                    var parentId2 = jtem.parentId;
                    if(parentId2 == id){  // 如果父id为当前item的id,则将菜单放入当前item的children数组中
                        //第二层级
                        item.children.push(jtem);
                    }
                });
                menuList.push(item);
            }
        });
        this.setData({
          menuList: menuList
        })
      },    
      onLoad: function () {
        if(app.globalData.token){
            //代表从页面跳转过来
            var menuList = wx.getStorageSync('menuList');
            this.getMenuList(menuList);
            this.animation = wx.createAnimation();  // 创建一个动画实例animation
            this.setData({hidden: false});    // 将数据模型中的hidden属性置为false
        }else{
            //代表第一次加载
            wx.showLoading({
              title: '加载中'
            })
            // 由于 checkBind 是网络请求,可能会在 Page.onLoad 之后才返回
            // 所以此处加入 callback 以防止这种情况
            app.checkBindCallback = res => {
                wx.hideLoading();
                if(res.data.code == 1){
                    var menuList = wx.getStorageSync('menuList');
                    this.getMenuList(menuList);
                    this.animation = wx.createAnimation();
                    this.setData({hidden: false});
                }
            }
        }
      }
    })

  • 相关阅读:
    MySQL 分库分表方案
    MySQL高性能优化实战总结
    MySQL太慢?试试这些诊断思路和工具
    Get MySQL这5个优化技巧
    一次MySQL两千万数据大表的优化过程,三种解决方案
    MySQL 常用30种SQL查询语句优化方法
    掌握 MySQL 这 19 个骚操作,效率至少提高3倍
    分分钟解决 MySQL 查询速度慢与性能差
    总结 | 慢 SQL 问题经验总结
    MySQL主从延时这么长,要怎么优化?
  • 原文地址:https://www.cnblogs.com/zwh0910/p/13983526.html
Copyright © 2011-2022 走看看