零、文章目录
微信小程序05-常用API下
1、案例:罗盘动画
(1)案例分析
-
需求:在微信小程序中,开发者根据项目需求,可以在页面中添加一些动画效果,例如旋转、缩放、移动等,通过这些动画效果可以提高用户体验。
-
"罗盘动画"微信小程序分为图片区域和按钮区域,实现了对图片的一系列动画操作,包括旋转、缩放、移动、倾斜等。
(2)知识储备-动画API
-
动画API
- 在微信小程序中添加动画效果,可以让页面中的内容动起来。动画效果对浏览者的视觉冲击力远远高于静态画面,更能吸引浏览者。
- 在微信小程序中,使用动画API即可完成动画效果的制作。动画API的使用方法是,先通过wx.createAnimation()方法获取Animation实例,然后调用Animation实例的方法实现动画效果。
jsvar animation = wx.createAnimation(Object object)
- wx.createAnimation()方法的常用选项如下
- timingFunction有多个合法值,timingFunction的合法值如下
- Animation实例可以调用一些方法来实现动画效果,调用结束会返回自身,支持链式写法。Animation实例的常用方法如下
-
代码演示
- 在pages/index/index.wxml文件中编写页面结构。
html<!--index.wxml--> <view animation="{{ move }}">hello world</view> <button bindtap="translate">动画</button>
- 在pages/index/index.js文件的Page({})中实现动画效果。
js// index.js Page({ data: { move: {} }, translate: function () { var animation = wx.createAnimation({ duration: 4000, timingFunction: 'ease' }) animation.translate(50, 70).step() this.setData({ move: animation.export() }) } })
(3)案例实现
-
准备工作
- ①创建项目。在微信开发者工具中创建一个新的微信小程序项目,项目名称为"罗盘动画",模板选择"不使用模板"。
- ②配置页面。项目创建完成后,在app.json文件中配置一个compass页面。
- ③配置导航栏。在pages/compass/compass.json文件中配置页面导航栏。
- ④配置页面样式和准备图片。在pages/index/index.wxss文件中配置页面样式。在images文件夹中准备图片。
-
**实现页面结构:**在pages/compass/compass.wxml文件中编写"罗盘动画"微信小程序的页面结构。
html
<!--pages/compass/compass.wxml-->
<!-- 图片区域 -->
<view class="anim-pic">
<image src="/images/img.png" animation="{{ animation }}" />
</view>
<!-- 按钮区域 -->
<view class="anim-btns">
<button bindtap="rotate">旋转</button>
<button bindtap="scale">缩放</button>
<button bindtap="translate">移动</button>
<button bindtap="skew">倾斜</button>
<button class="btn-two" bindtap="rotateAndScale">旋转并缩放</button>
<button class="btn-two" bindtap="rotateThenScale">旋转后缩放</button>
<button class="btn-two" bindtap="all">同时展示全部</button>
<button class="btn-two" bindtap="allOrder">按顺序展示全部</button>
<button class="btn-reset" bindtap="reset">回到原始状态</button>
</view>
- **实现页面逻辑:**在pages/compass/compass.js文件的Page({})中编写页面数据和事件处理函数,实现点击"旋转""缩放"等不同按钮操作罗盘的功能。
js
// pages/compass/compass.js
Page({
data: {
animation: {}
},
onReady: function () {
this.animation = wx.createAnimation({
duration: 1000,
timingFunction: 'ease',
})
},
// 实现从原点随机旋转某一个角度
rotate: function () {
this.animation.rotate(Math.random() * 720 - 360).step()
this.setData({
animation: this.animation.export()
})
},
// 实现图片随机缩放的效果
scale: function () {
this.animation.scale(Math.random() * 2).step()
this.setData({
animation: this.animation.export()
})
},
// 实现平移变换的效果
translate: function () {
this.animation.translate(Math.random() * 100 - 50, Math.random() * 100 - 50).step()
this.setData({
animation: this.animation.export()
})
},
// 实现对x、y轴坐标进行随机倾斜
skew: function () {
this.animation.skew(Math.random() * 90, Math.random() * 90).step()
this.setData({
animation: this.animation.export()
})
},
// 实现同时进行旋转和缩放
rotateAndScale: function () {
this.animation.rotate(Math.random() * 720 - 360)
this.animation.scale(Math.random() * 2).step()
this.setData({
animation: this.animation.export()
})
},
// 实现旋转之后在缩放
rotateThenScale: function () {
this.animation.rotate(Math.random() * 720 - 360).step()
this.animation.scale(Math.random() * 2).step()
this.setData({
animation: this.animation.export()
})
},
// 实现同时展示全部动画
all: function () {
this.animation.rotate(Math.random() * 720 - 360)
this.animation.scale(Math.random() * 2)
this.animation.translate(Math.random() * 100 - 50, Math.random() * 100 - 50)
this.animation.skew(Math.random() * 90, Math.random() * 90).step()
this.setData({
animation: this.animation.export()
})
},
// 实现按顺序展示全部动画
allOrder: function () {
this.animation.rotate(Math.random() * 720 - 360).step()
this.animation.scale(Math.random() * 2).step()
this.animation.translate(Math.random() * 100 - 50, Math.random() * 100 - 50).step()
this.animation.skew(Math.random() * 90, Math.random() * 90).step()
this.setData({
animation: this.animation.export()
})
},
// 实现回到初始状态
reset: function () {
this.animation.rotate(0).scale(1).translate(0, 0).skew(0, 0).step({
duration: 0
})
this.setData({
animation: this.animation.export()
})
}
})
- 页面实现效果
2、案例:用户登录
(1)案例分析
- 需求:在日常生活中,需要用户登录的场景有很多,例如,当用户在手机中浏览文章想要收藏时、在线上购买商品时、进入软件查询个人信息时,只有用户登录自己的账号以后,才可以进一步使用这些功能。
- 涉及登录相关功能如下
- 点击默认头像可以选择用微信头像来作为小程序头像;
- 点击"请输入昵称"输入框可以手动填写昵称或使用微信昵称作为昵称;
- 点击"获取用户的积分"按钮时
- 如果用户已登录,则会显示对应的积分,
- 如果用户未登录,则会显示"用户不存在,或未登录"。
(2)知识储备-登录流程时序
-
登录流程时序
- 企业在开发网站和移动应用软件时,通常会开发登录功能,用于辨别用户的身份信息。
- 在微信小程序中,也可以开发登录功能,通过微信官方提供的登录功能可以方便地获取微信提供的用户身份标识,从而使开发者服务器能够识别每个微信小程序用户。
- 微信小程序官方文档提供的登录流程时序如下
- 用户登录流程需要小程序、开发者服务器和微信接口服务3个角色的参与
- 小程序:用户使用的客户端,即微信小程序。
- 开发者服务器:微信小程序的后端服务器,用于为微信小程序用户提供服务。
- 微信接口服务:微信为开发者服务器提供的接口。
- 登录流程详细讲解
- **微信小程序获取临时登录凭证code:**通过wx.login()方法获取临时登录凭证code,code由微信小程序内部自动生成,每次调用wx.login()方法获得的code都不同。code有效期为5分钟,且被微信接口服务验证一次后就会失效。
- **微信小程序将code发送给开发者服务器:**在获取code后,使用wx.request()方法将code发送给开发者服务器。
- 开发者服务器通过微信接口服务校验登录凭证
- 开发者服务器将appid(微信小程序的唯一标识,即AppID)、appsecret(微信小程序的密钥,即AppSecret)和code发送给微信接口服务进行登录凭证校验,如果校验成功,微信接口服务会返回session_key、openid、unionid等信息。
- appid和appsecret用于辨别微信小程序开发者身份;
- session_key是用户的会话密钥,用于对用户数据进行加密签名;session_key需要存储在开发者服务器中,当调用获取用户信息等微信接口时,需要用session_key解密相关数据。
- openid是用户唯一标识,同一个微信用户在不同AppID的微信小程序中的openid是不同的;
- unionid是用户在微信开放平台账号下的唯一标识,若当前微信小程序已绑定到微信开放平台账号会返回此信息。
- 开发者服务器自定义登录态
- 自定义登录态是指由开发者自己决定如何维持用户的登录状态。
- 通常的做法是,在开发者服务器中为登录成功的用户生成一个token,然后通过验证token的有效性来识别用户的登录状态。
- 在用户登录成功时,开发者服务器需要保存用户的openid和session_key,然后生成一个对应的token响应给微信小程序。
- 微信小程序下次请求时,需要携带token。当开发者服务器收到请求后,需要使用当前请求携带的token查询对应用户的openid和session_key,如果能查询到,说明用户已登录,如果没有查询到,则说明用户未登录。
(2)知识储备-登录API
- 登录API
- 微信小程序提供了登录API,其使用方法是,调用wx.login()方法获取用户登录凭证code,然后,将它发送给开发者服务器。
- wx.login()方法的常用选项如下
- 代码演示
js
wx.login({
success: res => {
if (res.code) { // res.code为登录获取的code
// 登录成功之后发起网络请求
wx.request({
url: 'http://127.0.0.1:3000/login',
method: 'post',
data: {
code: res.code // 设置参数,把code传递给服务器
}
})
} else {
// 登录失败,在控制台输出错误信息
console.log('登录失败!' + res.errMsg)
}
}
})
(2)知识储备-数据缓存API
-
数据缓存API
- 在微信小程序中,有时需要保存一些临时数据,例如,将用户登录后获取到的token保存下来,从而在用户下次打开微信小程序时维持登录状态,或者将一些经常需要从服务器中下载的数据在微信客户端中缓存起来,以提高微信小程序下次打开时的加载速度。
- 在微信小程序中,利用数据缓存API可以实现数据的缓存,从而加快读取数据的速度。
- 常见的数据缓存方法如下:需要注意的是,单个key允许存储的最大数据长度为1MB,所有数据存储上限为10MB。
- wx.setStorage()方法的常用选项如下:
- wx.setStorage()方法和wx.setStorageSync()方法均可以实现缓存数据,区别就在于同步和异步。方法名以Sync结尾的都是同步方法
- 同步方法和异步方法的区别是
- 异步方法不会阻塞当前任务,而同步方法直到处理完之后才能继续向下执行。
- 异步方法需要通过传入回调函数获取结果,而同步方法是通过返回值获取结果。
- 如果发生错误,异步方法会执行fail()回调函数返回错误,而同步方法则通过try...catch捕获异常来获取错误信息。
- wx.getStorage()方法的常用选项如下
-
代码演示
js
// 存储缓存数据
wx.setStorage({
key: 'key', // 本地缓存中指定的key
data: 'value', // 需要存储的内容(支持对象或字符串)
success: res => {}, // 接口调用成功的回调函数
fail: res => {} // 接口调用失败的回调函数
})
// 获取缓存数据
wx.getStorage({
key: 'key', // 本地缓存中指定的key
success: res => { // 接口调用成功的回调函数
console.log(res.data)
},
fail: res => {} // 接口调用失败的回调函数
})
(2)知识储备-头像昵称填写
-
头像昵称填写
- 在微信小程序中,当用户登录后,可以在页面中展示用户的头像和昵称。
- 微信小程序不允许开发者在未获得用户同意的情况下展示用户的头像和昵称,当需要展示时,应使用微信小程序的头像昵称填写功能。
- 头像选择:将button组件的open-type属性值设置为chooseAvatar,当用户选择头像之后,可通过bindchooseavatar绑定的事件处理函数获取头像信息的临时路径。
- 昵称填写:将input组件的type属性值设置为nickname,当用户在此input组件进行输入时,键盘上方会展示用户的微信昵称,用户可以使用该昵称,也可以手动填写昵称。
-
代码演示
- ①在pages/index/index.wxml文件中编写页面结构。
html<button class="avatar-wrapper" open-type="chooseAvatar" bindchooseavatar="onChooseAvatar"> <image class="avatar" src="{{ avatarUrl }}" /> </button> <input type="nickname" class="nickname" placeholder="请输入昵称" />
- ②在pages/index/index.js文件中编写页面所需的数据。
jsconst defaultAvatar = '/images/avatar.png' Page({ data: { avatarUrl: defaultAvatar }, onChooseAvatar: function (e) { const { avatarUrl } = e.detail this.setData({ avatarUrl }) } })
- ③在pages/index/index.wxss文件中编写样式。
css.avatar-wrapper { width: 160rpx; height: 160rpx; padding: 0; background: none; } .avatar { width: 160rpx; height: 160rpx; border-radius: 20rpx; } .nickname { width: 80%; height: 100rpx; margin: 20px auto; border: 1px solid #000000; text-align: center; }
(2)知识储备-App()函数
- 在微信小程序中,若要在微信小程序启动、显示、隐藏时执行某些操作,或者在各个页面中需要共享一些数据时,可以通过App()函数来实现。
- App()函数用于注册一个微信小程序,该函数必须在app.js文件中调用,且只能调用一次。
- App()函数的参数是一个对象,通过该对象可以指定应用生命周期回调函数和保存一些共享数据。
- 应用生命周期函数是指微信小程序"启动→运行→销毁"期间依次调用的函数。应用生命周期回调函数如下。
- 在页面的JS文件中,通过getApp()函数可以获取微信小程序全局唯一的App实例。
- 通过getApp()函数获取App实例之后,可以访问App实例的属性或调用App实例的方法。
- 定义在App()函数的参数{}中的方法,可以直接使用this关键字获取App实例,不必使用getApp()函数。
js
const app = getApp()
(3)案例实现
-
准备工作
- ①创建项目。在微信开发者工具中创建一个新的微信小程序项目,项目名称为"用户登录",模板选择"不使用模板"。
- ②配置导航栏。在pages/index/index.json文件中配置页面导航栏.
- ③配置页面样式和准备图片。在pages/index/index.wxss文件中配置页面样式。在images文件夹中准备图片。
- ④启动服务器。切换工作目录到nodejs服务程序目录,打开命令提示符,然后在命令提示符中执行如下命令,启动服务器。
bashnode index.js
-
**实现用户登录:**在app.js文件的App({})中编写代码,实现微信小程序启动时自动执行登录操作。
js
// app.js
App({
onLaunch: function () {
this.checkLogin(res => {
console.log('is_login: ', res.is_login)
if (!res.is_login) {
this.login()
}
})
},
login: function () {
wx.login({
success: res => {
console.log('login code: ' + res.code)
wx.request({
url: 'http://127.0.0.1:3000/login',
method: 'post',
data: {
code: res.code
},
success: res => {
console.log('token: ' + res.data.token)
// 将token保存为公共 数据,用于在所有页面中共享token
this.globalData.token = res.data.token
// 将token保存到数据缓存
wx.setStorage({
key: 'token',
data: res.data.token
})
}
})
}
})
},
checkLogin: function (callback) {
var token = this.globalData.token
if (!token) {
// 从数据缓存中获取token
token = wx.getStorageSync('token')
if (token) {
this.globalData.token = token
} else {
callback({ is_login: false })
return
}
}
wx.request({
url: 'http://127.0.0.1:3000/checklogin',
data: { token: token },
success: res => {
callback({ is_login: res.data.is_login })
}
})
},
// 定义页面所需的数据
globalData: {
token: null // 保存token
}
})
- **实现页面结构:**在pages/index/index.wxml文件中编写页面结构。
html
<!--index.wxml-->
<button class="avatar-wrapper" open-type="chooseAvatar" bindchooseavatar="onChooseAvatar">
<image class="avatar" src="{{ avatarUrl }}"></image>
</button>
<input type="nickname" class="nickname" placeholder="请输入昵称" />
<button bindtap="credit">获取用户的积分</button>
- **实现页面逻辑:**在pages/index/index.js文件中编写逻辑代码。
js
// index.js
const app = getApp()
const defaultAvatar = '/images/avatar.png'
Page({
data: {
avatarUrl: defaultAvatar,
},
credit: function () {
wx.request({
url: 'http://127.0.0.1:3000/credit',
data: {
token: app.globalData.token
},
success: res => {
console.log(res.data)
}
})
},
onChooseAvatar: function (e) {
console.log(e)
const { avatarUrl } = e.detail
this.setData({ avatarUrl })
},
})
- 页面实现效果
3、案例:查看附近美食餐厅
(1)案例分析
- 需求:信息化时代,人们仅通过手机即可了解到周边的娱乐、餐饮等信息,即使到了人生地不熟的地方,也可以通过手机地图快速了解周围的环境。
- "查看附近美食餐厅"微信小程序打开后,会显示一个地图组件,并提供一些功能按钮。
- 页面上方有个banner图,用于显示优惠券领取信息。
- 地图左下角有一个定位按钮,点击此按钮可以将地图中心点设为当前定位的位置。
- 点击banner图会跳转到优惠券页面。
(2)知识储备-腾讯地图SDK
-
腾讯地图SDK是一套为开发者提供多种地理位置服务的工具,可以使开发者在自己的应用中加入地图相关的功能,轻松访问腾讯地图服务和数据,更好地实现微信小程序的地图功能。
-
腾讯地图SDK的使用步骤1:申请开发者密钥
- 打开腾讯位置服务网站,注册账号,登录。
- 点击开发文档下拉菜单选择"微信小程序JavaScript SDK"。
- 点击"申请秘钥"链接进入"我的应用"页面。
- 单机"+创建应用"按钮,会弹出"创建应用"悬浮框。"创建应用"悬浮框中填写"应用名称"和"应用类型",应用名称为"map",应用类型为"餐饮"。填写完成后单击"创建"按钮。
- 点击"添加Key"链接,会弹出"添加key到「map」应用"悬浮框。
- Key名称"可以填写为"地图组件";"描述"可以根据需求填写;
- "启用产品"中勾选"WebServiceAPI""SDK""微信小程序"复选框,勾选后还需要根据提示填写相关信息。
- 最后根据图片填写验证码,完成后单击"添加"按钮,会提示"创建key成功"
-
腾讯地图SDK的使用步骤2:下载腾讯地图SDK
-
腾讯地图SDK根据不同的开发场景提供了多种版本,针对微信小程序开发,应使用"微信小程序JavaScript SDK",它可以在微信小程序中调用腾讯位置服务的POI检索、关键词输入提示、地址解析、逆地址解析、行政区划和距离计算等数据服务。
-
点击开发文档下拉菜单选择"微信小程序JavaScript SDK"。点击"JavaScriptSDK v1.1"下载qqmap-wx-jssdk1.1.zip压缩包。该压缩包中有qqmap-wx-jssdk.js和qqmap-wx-jssdk.min.js这两个文件,两者功能相同,区别是后者代码经过压缩,故体积小。
- 将qqmap-wx-jssdk.js文件存放到项目中使用即可,通常将其放到libs目录下,该目录的名称可以自己命名。
-
-
腾讯地图SDK的使用步骤3:登录微信小程序管理后台添加合法域名
- 登录微信小程序管理后台,进入"管理→开发管理→开发设置→服务器域名"页面,设置"request合法域名"
-
腾讯地图SDK的使用步骤4:在微信小程序中声明权限
- 微信小程序在获取当前的地理位置时,需要开发者在app.json文件中对permission和requiredPrivateInfos进行声明
- permission用于对微信小程序接口权限进行设置。
- requiredPrivateInfos用于向用户申请隐私信息。
json1 "permission": { 2 "scope.userLocation": { 3 "desc": "你的位置信息将用于小程序位置接口的效果展示" 4 } 5 }, 6 "requiredPrivateInfos": [ 7 "getLocation" 8 ],
- 微信小程序在获取当前的地理位置时,需要开发者在app.json文件中对permission和requiredPrivateInfos进行声明
-
腾讯地图SDK的使用步骤5:使用腾讯地图SDK
- 腾讯地图SDK的使用方法是,首先引入SDK核心类,通过new QQMapWX()构造函数创建QQMapWX实例,然后通过该实例的相关属性和方法实现地点搜索等功能。
- QQMapWX实例有个search()方法搜索周边兴趣点(Point of Interest,POI)信息,例如"酒店""餐饮""学校"等。search()方法的常用选项如下。
-
代码演示:在pages/index/index.js文件中使用腾讯地图SDK
js
// 引入SDK核心类,js文件的位置可自行放置
const QQMapWX = require('../../libs/qqmap-wx-jssdk.js')
// 创建QQMapWX实例
const qqmapsdk = new QQMapWX({
key: '填写自己申请的开发者密钥'
})
Page({
onShow: function () {
// 搜索信息
qqmapsdk.search({
keyword: '酒店',
success: res => {
console.log(res)
},
fail: res => {
console.log(res)
}
})
}
})
(2)知识储备-map组件
-
map组件
- 在微信小程序中,若想为用户提供地图功能,可以通过map组件来实现。
- map组件可以在页面中显示地图,并且支持移动、缩放、添加标记点等功能。
html<map></map>
- map组件的常用属性如下
- markers用于在地图上显示标记的位置,它是数组类型,数组中的每一项为一个表示标记点的marker对象。
- marker对象的属性如下
-
代码演示
- 在pages/index/index.wxml文件中为map组件添加markers属性。
html<map id="myMap" markers="{{ markers }}" scale="3"></map>
- 在pages/index/index.wxss文件中编写样式。
cssmap { width: 100%; height: 100%; position: absolute; }
- 在pages/index/index.js文件中定义数据。
jsdata: { markers: [{ id: 1, iconPath: '/images/gps.png', longitude: 113.324520, latitude: 23.099994 }] },
(2)知识储备-地图API
-
地图API
- 使用map组件在页面中创建地图后,若想在JS文件中对地图进行控制,需要通过地图API来完成。
- 地图API的使用方法是,先通过wx.createMapContext()方法创建MapContext(Map上下文)实例,然后通过该实例的相关方法来操作map组件。
jsconst mapCtx = wx.createMapContext('myMap')
- MapContext实例的常用方法如下
- getCenterLocation()方法的常用选项如下
- moveToLocation()方法的常用选项如下
-
代码演示
js
mapCtx.getCenterLocation({
success: res => {
const longitude = res.longitude
const latitude = res.latitude
console.log(longitude, latitude)
}
})
(2)知识储备-位置API
-
位置API
- 在日常生活中,通过地图软件可以实时定位自己或者朋友的位置,方便出行。
- 微信小程序为我们提供了位置API,用于实现获取当前地理位置的功能。位置API的使用方法是,调用wx.getLocation()方法,通过该方法的success回调函数获取定位结果。
- 若想使用位置API,需要在微信小程序管理后台的"开发管理---接口设置"页面中申请开通,并且还需要在app.json文件中添加请求用户隐私信息的声明。
- wx.getLocation()方法的常用选项如下
- success()回调函数的参数是一个对象,该对象的属性如下
-
代码演示
js
wx.getLocation({
type: 'gcj02',
success: res => {
const longitude = res.longitude
const latitude = res.latitude
console.log(longitude, latitude)
}
})
(2)知识储备-路由API
-
路由API用于实现页面跳转,常用的路由API方法有3个
- wx.navigateTo():用于跳转到另一个页面,跳转后原来的页面会保留,并在导航栏左侧提供一个返回按钮,用户可以返回到之前的页面。微信小程序中的页面栈最大限制为10层。该方法不能用于标签页切换。
- wx.redirectTo():用于关闭当前页面,跳转到一个新页面。该方法不能用于标签页切换。
- wx.switchTab():用于跳转到某个标签页,并关闭其他所有非标签页的页面。
- 以上3个方法的选项类似。路由API方法的常用选项如下
- wx.navigateTo()方法还有一个object类型的events选项,它是页面间通信接口,用于监听被打开页面发送到当前页面的数据。通过url选项传递的参数可以在跳转的目标页面中通过onLoad()函数的参数获取。
-
代码演示
- 在pages/index/index.wxml文件中编写一个按钮,实现点击按钮时触发navigateTo()函数。
html<button bindtap="navigateTo">路由</button>
- 在app.json文件中创建pages/list/list页面。
- 在pages/index/index.js文件中编写navigateTo()函数,实现跳转到pages/list/list页面。
jsPage({ navigateTo: function () { wx.navigateTo({ url: '/pages/list/list?id=1', success: () => { console.log('跳转成功') }, fail: () => { console.log('跳转失败') }, complete: () => { console.log('跳转完成') } }) }, onLoad: function(options) { console.log(options) } })
(3)案例实现
-
准备工作
- ①创建项目。在微信开发者工具中创建一个新的微信小程序项目,项目名称为"查看附近美食餐厅",模板选择"不使用模板"。
- ②配置页面。在app.json文件中配置两个页面。
json"pages": [ "pages/map/map", "pages/coupon/coupon" ],
-
③配置导航栏。
- 在pages/map/map.json文件中配置页面导航栏。
json{ "navigationBarTitleText": "查看附近美食餐厅", "navigationBarBackgroundColor": "#d9362c", "navigationBarTextStyle": "white" }
- 在pages/coupon/coupon.json文件中配置页面导航栏。
json{ "navigationBarTitleText": "优惠券", "navigationBarBackgroundColor": "#d9362c", "navigationBarTextStyle": "white" }
-
④配置素材。
-
pages/map/map.wxss文件,该文件中保存了"查看附近美食餐厅"页面的样式素材。
-
pages/coupon/coupon.wxss文件,该文件中保存了"优惠券"页面的样式素材。
-
libs文件夹,该文件夹保存了微信小程序JavaScript SDK。
-
images文件夹,该文件夹保存了本项目所用的图片素材。
-
- **获取初始数据:**在pages/map/map.js文件中编写页面所需的数据。
js
// pages/map/map.js
const key = '7DCBZ-N5P64-AFSUR-DLNYJ-MQ2YK-VCFP3'
const QQMapWX = require('../../libs/qqmap-wx-jssdk.js')
const qqmapsdk = new QQMapWX({
key
})
Page({
data: {
scale: 18, // 缩放
longitude: 0, // 地图中心点经度
latitude: 0, // 地图中心点纬度
markers: [] // 标记点
},
mapCtx: null,
onReady: function () {
this.mapCtx = wx.createMapContext('myMap')
},
onLoad: function () {
wx.getLocation({
type: 'gcj02',
success: res => {
this.setData({
longitude: res.longitude,
latitude: res.latitude,
})
}
})
},
getFood: function (longitude, latitude) {
// 调用接口
qqmapsdk.search({
// 搜索关键词
keyword: '餐厅',
location: {
longitude: longitude,
latitude: latitude
},
success: res => {
var markers = []
// 为附近的美食餐厅设置标记点
for (let i in res.data) {
markers.push({
iconPath: '/images/food.png',
id: markers.length,
latitude: res.data[i].location.lat,
longitude: res.data[i].location.lng,
width: 30,
height: 30
})
}
markers.push({
iconPath: '/images/center.png',
id: res.data.length,
latitude: latitude,
longitude: longitude,
width: 15,
height: 40
})
// 将搜索结果显示在地图上
this.setData({
markers
})
}
})
},
regionChange: function (e) {
if (e.type === 'end') {
this.mapCtx.getCenterLocation({
success: res => {
this.getFood(res.longitude, res.latitude)
}
})
}
},
bannerTap: function () {
wx.navigateTo({
url: '/pages/coupon/coupon'
})
},
controlTap: function (e) {
this.mapCtx.moveToLocation()
}
})
- **在页面中显示地图:**在pages/map/map.wxml文件中编写页面结构。
html
<!--pages/map/map.wxml-->
<map id="myMap" bindcontroltap="controlTap" bindregionchange="regionChange" longitude="{{ longitude }}" latitude="{{ latitude }}" markers="{{ markers }}" scale="{{ scale }}" show-location></map>
<view class="controls">
<image class="banner" mode="widthFix" src="/images/banner.png" bindtap="bannerTap" />
<image class="gps" src="/images/gps.png" bindtap="controlTap" />
</view>
- **声明接口:**在app.json文件中声明其需调用的地理位置相关接口。
json
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"requiredPrivateInfos": [
"getLocation"
]},
- **实现优惠券页面:**在pages/coupon/coupon.wxml文件中编写优惠券页面的页面结构。
html
<!--pages/coupon/coupon.wxml-->
<view class="coupon">
<image src="/images/couponone.png" />
</view>
<view class="coupon">
<image src="/images/coupontwo.png" />
</view>
- 页面实现效果
4、案例:在线聊天
(1)案例分析
- 需求:一些购物平台经常会通过人工客服或机器客服来为用户提供服务,及时解答用户提出的问题,提高用户的使用体验。对于这类需求,可以通过在微信小程序中开发在线聊天功能来实现。
- "在线聊天"微信小程序,页面底部的输入框中输入"我来自微信小程序端"文本后,点击"发送"按钮,该页面就会将用户输入的内容发送给服务器,并将用户输入的内容显示在聊天界面的右侧。当服务器收到消息后,会自动回复一条消息"自动回复",显示在聊天界面的左侧。
(2)知识储备-WebSocket API
-
WebSocket API
- 在微信小程序中,虽然通过wx.request()方法可以向服务器发送请求,但这种方式有个缺点:不能实现服务器端主动向微信小程序发送消息。为此,微信小程序官方提供了WebSocket API,允许服务器主动向微信小程序发送消息。
- 微信小程序中的WebSocket与HTML5中的WebSocket基本相同。WebSocket是一种在单个TCP连接上进行全双工通信的协议,它会在客户端与服务器之间专门建立一条通道,使客户端与服务器之间的数据交换变得简单。客户端与服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。
- 需要注意的是,WebSocket协议是以ws或wss开头的(类似于http和https的关系),在微信小程序中,正式项目必须使用以wss开头协议,在开发模式下可以使用以ws开头协议。
- 通过wx.connectSocket()方法可以创建一个WebSocket连接。wx.connectSocket()方法的常用选项如下
-
代码演示
js
wx.connectSocket({
url: 'ws://127.0.0.1:3000' // 服务器地址
})
(2)知识储备-SocketTask
- 当项目中同时存在多个WebSocket的连接时,使用wx对象的方法可能会出现一些与预期不一致的情况,此时可以使用SocketTask管理WebSocket连接,使每一条链路的生命周期都更可控。
- wx.connectSocket()方法的返回值是一个SocketTask实例。
js
const ws1 = wx.connectSocket({
url: 'ws://127.0.0.1:3000'
})
- SocketTask实例的常用方法如下
- send()方法的常用选项如下
- close()方法的常用选项如下
- onClose()方法的参数为WebSocket连接关闭事件的回调函数,onClose()方法的属性如下
- onOpen()方法的参数为WebSocket连接打开事件的回调函数,onOpen()方法的属性如下
- onError()方法的参数为WebSocket错误事件的回调函数,属性为errMsg,表示错误信息。onMessage()方法的参数为WebSocket连接接收到服务器消息事件的回调函数,属性为data,表示服务器返回的消息。
- 代码演示:在pages/index/index.js文件中编写onLoad()函数,实现在页面加载完成时打开WebSocket连接。
js
onLoad: function () {
const ws1 = wx.connectSocket({ // 创建WebSocket连接
// 本地服务器地址
url: 'ws://127.0.0.1:3000',
success: resConnect => { // 连接成功
console.log(resConnect)
},
fail: resConnectError => { // 连接失败
console.log(resConnectError)
}
})
ws1.onOpen(res => { // 监听WebSocket连接打开事件
ws1.send({
data: JSON.stringify({
number: '123',
}),
success: resSend => {
console.log(resSend)
},
fail: resSendError => {
console.log(resSendError)
}
})
})
ws1.onMessage(data => { // 监听WebSocket连接接收到服务器的消息事件
console.log(data.data)
})
},
(3)案例实现
-
准备工作
- ①创建项目。在微信开发者工具中创建一个新的微信小程序项目,项目名称为"在线聊天",模板选择"不使用模板"。
- ②配置导航栏。在pages/index/index.json文件中配置页面导航栏。
- ③配置页面样式和准备图片。在pages/index/index.wxss文件中配置页面样式。在images文件夹中准备图片。
- ④启动服务器。切换工作目录到nodejs服务程序目录,打开命令提示符,然后在命令提示符中执行如下命令,启动服务器。
bashnode index.js
- **实现页面结构:**在pages/index/index.wxml文件中编写页面结构。
html
<!--index.wxml-->
<view class="chat">
<!-- 消息列表 -->
<scroll-view scroll-y scroll-into-view="item_{{ lastId }}">
<view wx:for="{{ list }}" wx:key="id" class="chat-message chat-message-{{ item.role }}" id="item_{{ item.id }}">
<view class="chat-content"><view>{{ item.content }}</view></view>
<image class="chat-avatar" src="/images/{{ item.role }}.png"></image>
</view>
</scroll-view>
</view>
<view class="message">
<input type="text" bindinput="input" placeholder="请输入聊天内容..." value="{{ content }}" />
<button type="primary" bindtap="send" size="small">发送</button>
</view>
- **实现WebSocket连接:**在pages/index/index.js文件中实现链接和发送数据。
js
// index.js
Page({
data: {
content: '',
list: [],
lastId: ''
},
message: '',
ws: null,
onLoad: function () {
const ws = wx.connectSocket({
url: 'ws://127.0.0.1:3000',
success: resConnect => {
console.log(resConnect)
},
fail: resConnectError => {
console.log(resConnectError)
}
})
ws.onMessage(msg => {
// console.log(msg)
const data = JSON.parse(msg.data)
const list = this.data.list
const lastId = list.length
list.push({
id: lastId,
content: data.content,
role: 'server'
})
this.setData({
list,
lastId
})
})
ws.onClose(res => {
console.log(res)
})
this.ws = ws
},
// 关闭WebSocket连接
onUnload: function () {
this.ws.close()
},
input: function (e) {
this.message = e.detail.value
},
// 点击"发送"按钮时将message中的内容发送到服务器
send: function () {
// 判断发送内容是否为空
if (!this.message) {
wx.showToast({
title: '消息不能为空',
icon: 'none',
duration: 2000
})
return
}
this.ws.send({
data: this.message
})
const list = this.data.list
const lastId = list.length
list.push({
id: lastId,
content: this.message,
role: 'me'
})
this.setData({
list,
lastId,
content: ''
})
this.message = ''
}
})
- 页面实现效果