codecamp

云开发 点击事件

事件是视图层到逻辑层的通信方式,当我们点击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组件与页面路由API

在前面我们已经学习过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进行跳转, 然后返回,提高加载速度。

云开发 JavaScript入门
云开发 页面渲染
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }