社区/学习指南/小程序云开发学习指南

点击事件

事件是视图层到逻辑层的通信方式,当我们点击 tap、触摸 touch、长按 longpress 小程序绑定了事件的组件时,就会触发事件,执行逻辑层中对应的事件处理函数。

小程序框架的视图层由 WXML 与 WXSS 来编写的,由组件来进行展示。将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

页面滚动

使用开发者工具新建一个 tapevent 的页面(直接在 app.json 的 pages 配置项第一行添加一个 tapevent 的页面,由于是第一项,这样就可以成为小程序的首页呈现出来),然后将以下代码输入到 tapevent.wxml 文件里:

<button type="primary" bindtap="scrollToPosition">滚动到页面指定位置</button>
<view class="pagetop" style="background-color:#333;width:100%;height:400px"></view>
<button type="primary" bindtap="scrollToTop">滚动到页面顶部(返回顶部)</button>
<view id="pageblock" style="background-color:#333;width:100%;height:400px"></view>

这里的type="primary"只是引入 weui 给 button 添加的样式。而函数名 scrollToPosition 和 scrollToTop 是可以自己定义的,然后我们再来在相应的 js 文件里要添加和函数名 scrollToPosition 和 scrollToTop 对应的事件处理函数。

在 tapevent.js 的Page({})里(也就是和 data:{}onLoad: function (options) { }等函数平级),输入以下代码:

  scrollToTop() {
    wx.pageScrollTo({
      scrollTop: 0,
      duration: 300
    })
  },

  scrollToPosition() {
    wx.pageScrollTo({
      scrollTop: 6000,
      duration: 300
    })
  },

当用户点击该 button 组件的时候会在该页面对应的 Page 中找到相应的事件处理函数。保存编译之后,看看是不是就有了页面滚动的效果了?原理是 scrollToTop()和 scrollToPosition()这两个函数实际上都是调用了同一个小程序的滚动 API wx.pageScrollTo(),关于该 API 的具体参数信息,我们可以查阅技术文档。

滚动 API 技术文档:wx.pageScrollTo(Object object)

在官方文档我们可以看到 wx.pageScrollTo()的作用是将页面滚动到目标位置,支持选择器和滚动距离两种方式定位

  • scrollTop 滚动到页面的目标位置,单位 px,值为 0 就是滚动到顶部;值为 600 就是
  • duration 是滚动动画的时长,单位为 ms,而 1 秒=1000 毫秒

那如何滚动到指定的选择器的位置呢?前面我们已经给 view 分别添加了 id 和 class 的选择器,只需要将之前的函数的配置信息修改为如下(注意哦,如果你是添加而不是修改,函数名会冲突的,或者你可以起其他的函数名):

  scrollToTop() {
    wx.pageScrollTo({
      duration: 3000,
      selector:".pagetop"
    })
  },

  scrollToPosition() {
    wx.pageScrollTo({
      duration: 300,
      selector:"#pageblock"
    })
  },

小任务:如果只是在组件上绑定了事件也就是只有 bindtap="scrollToPosition",但是并没有在 js 文件里写相应的事件处理函数 scrollToPosition,看一下控制台 Console 会报什么错?

不要误以为只有 button 组件才可以绑定事件哦,还记得我们小程序组件里看的技术文档小程序组件吗?在公共属性部分,可以看到所有组件都有以下属性 bind* / catch*,这个属性的类型是 EventHandler,bindtap 就是 bind* 的一个类型。也就是说小程序的所有组件都可以通过以上方法触发事件处理函数,达到滚动等效果。使用 button 为案例只是为了便于展示而已。

命名规范:JavaScript 的项目名、函数名、变量等都应该遵循简洁、语义化的原则。函数名推荐使用驼峰法来命名(camelCase),比如 scrollToTop、pageScrollTo,也就是由小写字母开始,后续每个单词首字母都大写,长得跟骆驼 🐫 的驼峰似的。

消息提示框 Toast

消息提示框是移动端 App、H5(WebApp)、小程序经常会使用到的一个交互界面。在 tapevent.wxml 输入代码:

<button type="primary" bindtap="toastTap">点击弹出消息对话框</button>

在 js 里输入以下代码:

  toastTap() {
    wx.showToast({
      title: '购买成功',
      icon: 'success',
      duration: 2000
    })
  },

消息提示技术文档:wx.showToast(Object object)

  • title:为必填,提示的内容
  • icon:只有三个选项,success、loading、none,大家可以自行测试一下三个不同取值的效果
  • duration:提示延迟的时间,默认为 1500 毫秒,也就是 1.5 秒

小任务:修改 title、icon 和 duration,以及添加 image 属性,看看会有什么样不同的表现形式,以及你在哪个 App 的何种场景下见过类似的消息提示信息?

模态对话框

为了让界面显示的更加简洁,你可以使用快捷键 Ctrl+/(Mac 为 Command+/)来将上面 wxml 里的代码注释掉,js 文件里面的函数就不用注释啦

使用开发者工具继续在 tapevent.wxml 文件里添加代码,这次我们会调用一下小程序的模态框(还是强调 modalTap 是你可以根据命名规范任意命名的,只需要在 js 里添加相应的事件处理函数就可以调用 API):

<button type="primary" bindtap="modalTap">显示模态对话框</button>

然后再在 tapevent.js 中输入以下代码:

  modalTap() {
    wx.showModal({
      title: '学习声明',
      content: '学习小程序的开发是一件有意思的事情,我决定每天打卡学习',
      showCancel: true,
      confirmText: '确定',
      success(res) {
        if (res.confirm) {
          console.log('用户点击了确定')
        } else if (res.cancel) {
          console.log('用户点击了取消')
        }
      }
    })
  },

保存编译之后,点击模拟器上的按钮,就可以显示出一个对话框,这个对话框我们称之为 Modal 模态对话框。

模态对话框技术文档:wx.showModal(Object object)

千变万化之 API

阅读 API 的技术文档,就要了解该 API 有哪些属性,属性代表得是什么含义,属性是什么类型(这一点非常重要),以及它的默认值是什么,可以有哪些取值。

  • title 属性不是必填,删除 title 的赋值,就不会显示标题啦;
  • content 属性也不是必填,为提示的内容;
  • showCancel 默认值就是 true,意思是默认显示取消按钮,改为 false 就不显示了
  • confirmText 默认值为确定,你可以改成别的试试

通过给 API 已有的属性赋不同的值,API 所展现的内容就会有很多种变化,而具体要怎么用,则需要你根据实际的小程序开发项目来使用了。

小任务:在哪些 App、小程序、H5(WebApp)你会看到模态框?这些模态框是在什么情况下出现的,它的作用是啥?你能模仿这些模态框写一下配置信息吗?

console.log 日志打印

点击模态框上面的取消、确定按钮,留意一下开发者工具调试器 Console 的日志打印信息:当我们点击取消按钮时,会打印“用户点击了取消”;当我们点击确定按钮时,会打印“用户点击了确定”,而这打印的结果是由上面的这段代码输出的:

success(res) {
  if (res.confirm) {
    console.log('用户点击了确定')
  } else if (res.cancel) {
    console.log('用户点击了取消')
  }
}

那这段代码到底怎么理解呢?除了 console.log('用户点击了确定'),这个之前接触过可以理解外,res 是什么?res.confirm、res.cancel 是什么,从哪里来的?我们可以使用 console.log()打印一下。将上面这段代码增加一些打印信息。

success(res) {
  console.log(res)
  if (res.confirm) {
    console.log(res)
    console.log("点击确认之后的res.confirm是:" + res.confirm)
    console.log("点击确认之后的res.cancel是:" + res.cancel)
  } else if (res.cancel) {
    console.log(res)
    console.log('用户点击了取消')
    console.log("点击取消之后的res.confirm是:" + res.confirm)
    console.log("点击取消之后的res.cancel是:" + res.cancel)
  }
}

再来编译之后点击模态框的取消和确定按钮,看打印出来什么结果。当点击确认时,res.confirm 的值为 true,就执行 if 分支里的语句;当 res.cancel 的值为 true,就执行 res.cancel 的语句。在模态对话框技术文档:wx.showModal(Object object)也有 object.success 回调函数的说明。

success、fail、complete 回调函数 在技术文档里可以看到属性里有 success 和 fail 两个回调函数,success 为接口调用成功的回调函数;fail 为接口调用失败的回调函数。关于这方面的知识大家可以阅读技术文档小程序 API,大致了解一下异步 API 与回调函数的参数,理解异步 API 的执行结果需要通过 Object 类型的参数中传入的对应回调函数获取。(不理解也没有关系)

手机振动

手机振动 API 分两种,一种是长振动,一种是短振动,两个 API 写法大致相同,为了体验效果,我们以长振动为例,在 tapevent.wxml 里输入以下代码,

<button type="primary" bindtap="vibrateLong">长振动</button>

然后再在 tapevent.js 里添加与之对应的事件处理函数:

  vibrateLong() {
    wx.vibrateLong({
      success(res) {
        console.log(res)
      },
      fail(err) {
        console.error(err)
      },
      complete() {
        console.log('振动完成')
      }
    })
  },

保存编译之后,点击预览,使用手机扫描来体验一下长振动的效果。

长振动技术文档:wx.vibrateLong()

在长振动技术文档里我们再次看到 API 里三个回调函数,success、fail、complete。在模拟器上点击按钮时,就可以看到打印日志。console.error 向控制台的 console 中打印 error 日志,如果不能调用长振动,那一般是手机权限的问题了。

小任务:参考长振动的代码以及短振动的技术文档,写一个短振动的案例,体验一下两者有什么不同。

弹出操作菜单

下面我们来了解一下操作操作,在 tapevent.wxml 输入以下代码

<button type="default" bindtap="actionSheetTap">弹出操作菜单</button>

然后再在 tapevent.js 里添加与之对应的事件处理函数:

  actionSheetTap() {
    wx.showActionSheet({
      itemList: ['添加照片', '删除照片', '更新照片', '查询更多'],
      success(e) {
        console.log(e.tapIndex)
      }
    })
  },

弹出菜单技术文档:wx.showActionSheet(Object object)

保存之后在模拟器体验,点击按钮就会弹出显示添加照片、删除照片、更新照片、查询更多等选项的操作菜单,当然我们点击操作菜单的选项之后是没有反应的,点击之后的反应还需要我们以后来写事件处理函数才行。

success 回调函数

当我们点击操作菜单的不同选项时,会返回不同的数字,这取决于 success 回调函数里的 e.tapIndex 的值。在官方文档里我们可以了解到,当用户点击的按钮序号,从上到下的顺序,从 0 开始,相当于对应着数组 itemList 的序号,这样就为我们以后根据不同的菜单选项来执行不同的操作提供了可能。

小任务:在 success(e){}回调函数里,添加 console.log(e)打印 e 以及 console.log(e.errMsg)打印 e 的 errMsg 对象看看是什么结果。

页面路由

页面路由是一个非常重要的概念,打开新页面、页面返回、Tab 页面切换、页面重定向等都是也能路由的不同方式。

关于页面路由,大家可以阅读一下页面路由技术文档,页面路由我们可以简单的理解为对页面链接的管理,根据不同的 url 链接来显示不同的内容和页面信息。在后面的章节我们还会具体讲一下页面路由的知识的,不必苛求一次性都搞明白。

在前面我们已经学习过 Navigator 组件,在 navigator 组件的技术文档里,我们可以看到 open-type 属性以及合法值。在小程序 API 左侧也可以看到 5 个不同的 API。它们之间的对应关系如下:

页面路由 API Navigator open-type 值 含义
redirectTo redirect 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
navigateTo navigate 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。
navigateBack navigateBack 关闭当前页面,返回上一页面或多级页面。
switchTab switchTab 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
reLaunch reLaunch 关闭所有页面,打开到应用内的某个页面

也就是说 Navigator 组件可以做到的事情,使用 JavaScript 调用小程序也能路由 API 也可以做到。Navigator 组件的内容是写死的,而 JavaScript 则可以提供动态的数据。

跳转到新页面与 Tab 页

我们可以在之前创建的 home.wxml 里输入以下代码:

<button bindtap="navigateTo">保留页面并跳转</button>
<button bindtap="switchTab">跳转到组件Tab页</button>
<button bindtap="redirectTo">关闭当前页面跳转</button>

然后在 home.js 文件里添加以下代码:

navigateTo() {
    wx.navigateTo({
        url: '/pages/home/imgshow/imgshow'
    })
},
switchTab() {
    wx.switchTab({
        url: "/pages/list/list",
    })
},
redirectTo() {
    wx.redirectTo({
        url: '/pages/home/imgshow/imgshow'
    })
},

保存之后在开发者工具的模拟器点击按钮,就实现了页面和 Tab 页的切换效果。在前面我们提到 bintap 是小程序所有组件的公有属性,只有 bintap 绑定了页面路由切换的事件处理函数,组件是不是 Navigator 也就不重要了,也就是链接跳转不再是 Navigator 组件的专利。

注意这里的 url 的路径,我们使用的是相对于小程序根目录的绝对路径。app.json 的 pages 配置项前面没有/是因为 app.json 本来就在根目录,所以可以使用相对路径以及这里的取值,以及 API 很多参数的字符串 String 类型的赋值,单引号和双引号都是没有影响的。

返回上一页

在 home 页面里的 imgshow 文件夹下的 imgshow.wxml(在小程序开发的第一部分建过这个页面,如果没有,你再创建也可以)输入以下代码:

<button bindtap="navigateBack">返回上一页</button>

在 imgshow.js 里添加以下代码

navigateBack() {
    wx.navigateBack({
        delta: 1
    })
},

点击保留页面跳转按钮以及返回上一页按钮,这样我们就可以在小程序里通过点击组件实现了页面的切换与页面的返回。而如果是使用 wx.redirectTo 跳转到新的页面就没法使用返回上一页了。

wx.navigateTo 是保留当前页面、跳转到应用内的某个页面,使用 wx.navigateBack 可以返回到原页面。对于页面不是特别多的小程序,且页面间存在经常切换时,推荐使用 wx.navigateTo 进行跳转, 然后返回,提高加载速度。

本文出自 李东bbsky