代码地址 : https://gitee.com/mtcarpenter/wechat-cloud.git
1 聊下云开发
1.1 从企业的角度
什么是小程序云开发,从前端解决后端的活。18 年以为很多大公司减员,小公司关闭,到底是互联网的寒冬时期,还是互联网换新时期,我认为是后者。小程序开发周期一般都相对比比较短,如果一个企业还是一个团队去开发一个博客、资讯、新闻这类的产品,支出的成本是还是相对大比较大的。其中可能大部分时间我们都用在联调这个事上了,代码的测试,数据校验,很大时间浪费在前后端相互对接等待等。像小程序这种无服务在以后会越来越多,只管写接口、写逻辑就好。总得来说,虽然你管的东西越来越少,但开发效率却越来越高,开发出来的轻应用、小程序却是具备高性能、高可用、高扩展的特性, 开发人员的较少必定资金和人力的需求可谓大大节省。
1.2 从开发者的角度
小程序云开发无疑是让前端开发者从前端开发到全栈开发,大前端目前是行业一个非常流行的趋势,这几年全栈的火爆主要有业务场景相对比较多,像之前那样前端只写静态页面,数据和模板都是通过后端来渲染,无法满足业务了,所以都出现前后端开始分离,前后两端是通过 API 的请求和返回去做一个数据交互,前端工程师比较贴近客户,所以他更能够去理解到一些业务逻辑,无论是业务的前台或是后台,交给前端工程师来做是更好的,所以现在很多公司选择使用 node.js ,做中台服务。企业的需要前端干的事越多,我们学习的东西就越多,掌握的技能就越多,如果在开发小程序的前端人员,在日常的闲暇时间了解下云开发,也是对自己后期做 node.js 做一个小小的铺垫,云开发无需自己在对环境的搭建,也能让我们不再额外购买服务器就能开发自己一个线上的作品。
1.3 什么是小程序云开发?
云开发是微信团队和腾讯云团队共同研发的一套小程序基础能力,简言之就是:云能力将会成为小程序的基础能力。
小程序云开发目前提供三大基础能力支持:
- 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写业务逻辑代码
- 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库
- 文件存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
小程序操作数据库可以在小程序端和服务端操作数据库,小程序本来相对于小,如果我们代码全部放在小程序端来操作,会占用不少的内存,另一方面就是直接在页面操作数据库安全性也无法得到保障,因此我们在对数据的操作就需要通过服务端操作,目前服务端要操作小程序我们就得通过云函数,云函数作为服务层对数据交互,在一定的层面保证了数据的安全性。
1.4 云开发项目搭建
1.4.1 准备工作
已经申请小程序,获取小程序 AppID 在小程序管理后台中, 设置的开发设置 下可以获取微信小程序 AppID 。
1.4.2 新建项目
进入云开发控制面板入口
进入控制面板,在左上角就是小程序云开发目前提供三大基础能力。
- 运营分析:资源使用是日常对云开发资源的使用的统计、用户访问是用户在小程序授权用户信息、监控图标是三大基础能力的请求统计。
- 右上角设置:小程序云开发支持两个环境,在设置可以切换环境,数据库、存储、云函数根据环境显示当前的资源信息。
将所有没有带云开发
标识的文件夹创建并部署,带有云开发标识
的才能调用服务器。
如果你之前没有玩过云开发,在这里上传云函数之后,就可以试着跟着官方的 demo 操作下,官方的数据库跟我们的 mongodb 数据库类似,把 demo 提供的功能练习下:
官方文档: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html
如果想要项目重命名,文件夹和 project.config.json
对应即可,如果无法直接修改就需要关闭项目修改了在打开项目。
这里我们已经不需要官方的模板,将其官方给的图片和模板删除。
2 灵活的自定义组件(插槽,behaviors,授权,自定义组件样式)
2.1 插槽(slot)
- 使用场景 小程序中多处使用同一个自定义组件,组件中部分样式灵活显示、隐藏。
- 使用方法 slot 标签定义在小程序自定义组件中,根据外部传入标签控制,动态的设置自定义组件的样式,在实际开发中提高了组件的复用性。
- 示例代码如下:
(1)封装组件,components/title-bar
代码语言:txt复制<!-- 自定义组件,添加插槽,插槽的name一定要设置,使用时name要相同-->
<!-- components/title-bar/index.wxml -->
<view class='container'>
<view class="left-container">
<view class='line'></view>
<text class='text'>{{title}}</text>
</view>
<view class="right-container">
<!-- slot 插槽 -->
<slot name="more"></slot>
</view>
</view>
(2)引入组件
代码语言:txt复制{
"usingComponents": {
"title-comp": "/components/title-bar/index"
}
}
(3)使用组件
代码语言:txt复制 <!-- 卡槽 -->
<title-comp title="没有插槽"></title-comp>
<title-comp title="使用插槽">
<!--里面的<text>标签就是传递给插槽的 text 中 slot 的值需跟组件的 name 保持一致-->
<text class="more" slot="more">更多</text>
</title-comp>
(4)运行效果
2.2 behaviors
- 使用场景 behaviors 是用于组件间代码共享的特性,例如商品基本信息在多处展示,布局不同,且有属性、数据、生命周期函数和方法。
- 使用方法
新建 behavior.js(名字可自定义) 文件中有共享的 properties ,data ,methods 等。在组件中引入并继承即可。
示例代码如下:
(1)新建 behavior.js 文件中有共享的 properties ,data,methods 等
代码语言:txt复制module.exports = Behavior({
<!--共享属性-->
properties: {
product: { // 属性名
type: Object,
// value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
observer: function (newValue, oldValue,path) {
console.log(newValue)
console.log(oldValue)
console.log(path)
}
}
},
//共享数据
data:{
},
// 共享方法
methods: {
// 商品详情
productDetails: function () {
// triggerEvent 组件间通信与事件
this.triggerEvent("productDetails", {
id: this.data.product.id
}, {})
}
}
})
组件间通信与事件:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html
(2)封装组件,components/product-column
代码语言:txt复制<!-- components/product-column/index.wxml -->
<view class='container'>
<view class="left-container">
<view class='line'></view>
<text class='text' bind:tap="productDetails">{{product.name}}</text>
</view>
<view class="right-container">
<text class="text">价格:¥{{product.price}}</text>
</view>
</view>
代码语言:txt复制// components/product-column/index.js
<!--引入behavior.js-->
let productBev = require("../behaviors/product.js")
Component({
<!--继承 behavior.js里面的 properties,data,methods-->
behaviors: [productBev],
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
(3)封装组件,components/product-row
代码语言:txt复制<!-- components/product-row/index.wxml -->
<view class='container'>
<view class="left-container">
<view class='line'></view>
<text class='text' bind:tap="productDetails">{{product.name}}</text>
</view>
<view class="right-container">
<text class="text">数量:{{product.num}}</text>
</view>
</view>
代码语言:txt复制// components/product-row/index.js
<!--引入behavior.js-->
let productBev = require("../behaviors/product.js")
Component({
<!--继承 behavior.js里面的 properties,data,methods-->
behaviors: [productBev],
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
(4)使用组件
代码语言:txt复制{
"usingComponents": {
"product-column-comp": "/components/product-column/index",
"product-row-comp": "/components/product-row/index",
}
}
代码语言:txt复制<!-- behaviors -->
<product-column-comp product="{{product}}"></product-column-comp>
<product-row-comp product="{{product}}" bind:productDetails="productDetails"></product-row-comp>
(4)运行效果
2.3 自定义授权组件
- 使用场景 解决微信开放能力 button 的复用性。
- 使用方法 通过动态的传递 open-type 在组件中实现授权。
- 示例代码如下: (1)封装组件,components/authorize-button
<!--components/authorize-button/index.wxml-->
<button bind:getuserinfo="onGetUserInfo" bind:tap="address" open-type="{{openType}}" plain="{{true}}" class="container" lang="zh_CN">
<slot name="share"></slot>
<slot name="address"></slot>
<slot name="info"></slot>
</button>
代码语言:txt复制// components/authorize-button/index.js
Component({
/**
* 组件的属性列表
*/
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
properties: {
// 授权开放能力 通过传递实现
openType: {
type: String
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
// 用户信息获取方法
onGetUserInfo(event) {
if (this.data.openType == "getUserInfo"){
console.log("-----------用户信息获取-----------")
console.log(event.detail)
}
},
// 地址信息的获取
address(event){
if (this.data.openType == "primary") {
console.log("-----------地址信息获取-----------")
this._addressInfo(event)
}
},
_addressInfo(event){
wx.chooseAddress({
success: (res) => { },
fail:(err) =>{},
complete:(e)=> {
console.log(e) // 用户授权和未授权都会执行
}
})
}
}
})
(2)使用组件
代码语言:txt复制{
"usingComponents": {
"authorize-comp": "/components/authorize-button/index"
}
}
代码语言:txt复制<!-- 授权 -->
<view class="authorize-item">
<authorize-comp class="authorize" open-type="getUserInfo">
<text slot="info">用户信息</text>
</authorize-comp>
<authorize-comp class="authorize" open-type="primary">
<text slot="address">获取地址</text>
</authorize-comp>
<authorize-comp class="authorize" open-type="share">
<text slot="share">分享</text>
</authorize-comp>
</view>
(3)运行效果
2.4 自定义组件样式
- 使用场景 在复用组件的时候,且样式想要不同。
- 使用方法 使用外部样式类可以让组件使用指定的组件外样式类,如果希望组件外样式类能够完全影响组件内部,可以将组件构造器中的 options.addGlobalClass 字段置为 true 。
- 示例代码如下: (1)封装组件,components/authorize-button
// components/class/index.js
Component({
// 定义外部样式类
externalClasses: ['box'],
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
代码语言:txt复制<!--components/class/index.wxml-->
<!--box 样式通过外部传递-->
<view class="container box"></view>
(2)使用组件
代码语言:txt复制{
"usingComponents": {
"class-comp": "/components/class/index"
}
}
代码语言:txt复制<!-- 自定义组件样式 -->
<view class="class-item">
<class-comp box="box1"></class-comp>
<class-comp box="box2"></class-comp>
<class-comp box="box3"></class-comp>
<class-comp box="box4"></class-comp>
</view>
代码语言:txt复制.box1 {
background-color: #ff3f34;
}
.box2 {
background-color: #fbbf00;
}
.box3 {
background-color: #44ac45;
}
.box4 {
background-color: #2f84d5;
}
(3)运行效果
3 wxs 的使用
WXS(WeiXin Script)是小程序的一套脚本语言,实现 wxml 数据的过滤。在使用的过程中需要需要结合官方文档,wxs 目前只是拥有部分 JavaScript 功能。官方给出的注意如下:
- WXS 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。
- WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。
- WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript
- 文件中定义的函数,也不能调用小程序提供的API。
- WXS 函数不能作为组件的事件回调。
- 由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。
常用的使用情况有两种引入后缀 wxs 和 直接在 wxml 文件中使用。
示例代码如下:
(1)新建 wxs 文件,common/wxs/filter.wxs
代码语言:txt复制var filters = {
// 定义方法
toFix: function (value) {
// 防止 wxs 渲染数据没有定义
if (value == 0 || !value) {
return 0
}
// toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
return parseFloat(value).toFixed(2)
}
// 多个方法使用逗号分隔
,
substr: function (value, length) {
if (!value) {
return ''
}
// 对数据进行长度限制
return value.substring(0, length) "..."
}
}
// 导出方法
module.exports = {
toFix: filters.toFix,
substr: filters.substr
}
(2)引入使用 wxs
代码语言:txt复制<!--引入 wxs 并指定标签的模块名-->
<wxs module="util" src="../../common/wxs/filter.wxs"></wxs>
<view class="wxs-container">
<view class="wxs-item">数字截取前:{{8.02231}}</view>
<view class="wxs-item">数字截取后:{{util.toFix(8.02231)}}</view>
<view class="wxs-item">订单状态页面直接引用:{{wUtil.orderStatus(1)}}</view>
</view>
module 属性 module 属性是当前 <wxs> 标签的模块名。在单个 wxml 文件内,建议其值唯一。有重复模块名则按照先后顺序覆盖(后者覆盖前者)。不同文件之间的 wxs 模块名不会相互覆盖。
module 属性值的命名必须符合下面两个规则:
首字符必须是:字母(a-zA-Z),下划线(_)
剩余字符可以是:字母(a-zA-Z),下划线(_), 数字(0-9)
(3)页面直接使用 wxs
代码语言:txt复制<view class="wxs-item">文字截取后:{{util.substr("这是一段超级长的文字需要截取",6)}}</view>
<view class="wxs-item">订单状态页面直接引用:{{wUtil.orderStatus(1)}}</view>
<!--当前页面直接使用 wxs, 通过 wxs 标签指定模块名-->
<wxs module="wUtil">
var orderStatus = function(num) {
var value = ""
switch (num) {
case 0:
value = "未支付"
break
case 1:
value = "已支付"
break
case 2:
value = "已发货"
break
case 3:
value = "已支付,但库存不足"
break
default:
value = "未知状态"
}
return value
}
<!--导出模块-->
module.exports = {
orderStatus: orderStatus
}
</wxs>
(4)运行效果
4 云上 tcb-router(koa 风格)
但是无数个得云函数,我们管理又有问题了,如果想要一个函数处理多个任务 ,目前解决这一问题就是 tcb-router 。
tcb-router 小程序云函数高级玩法,在掘金开发者大会上,提到得一种云函数的用法,我们可以将相同的一些操作,比如用户管理、支付逻辑,按照业务的相似性,归类到一个云函数里,这样比较方便管理、排查问题以及逻辑的共享。甚至如果你的小程序的后台逻辑不复杂,请求量不是特别大,完全可以在云函数里面做一个单一的微服务,根据路由来处理任务。
下面三幅图可以看出:
比如这里就是传统的云函数用法,一个云函数处理一个任务,高度解耦。
第二幅架构图就是尝试将请求归类,一个云函数处理某一类的请求,比如有专门负责处理用户的,或者专门处理支付的云函数。
最后一幅图显示这里只有一个云函数,云函数里有一个分派任务的路由管理,将不同的任务分配给不同的本地函数处理。
想实现成最后一幅图,我们的使用咱们腾讯云 Tencent Cloud Base 团队开发了 tcb-router,云函数路由管理库。大家点击 tcb-router 进去看看,如果之前做过 node koa 的同学应该很熟悉,后面我们也会有一个小得案例进一步讲解,官方例子如下:
代码语言:txt复制// 云函数的 index.js
const TcbRouter = require('./router');
exports.main = (event, context) => {
const app = new TcbRouter({ event });
// app.use 表示该中间件会适用于所有的路由
app.use(async (ctx, next) => {
ctx.data = {};
await next(); // 执行下一中间件
});
// 路由为数组表示,该中间件适用于 user 和 timer 两个路由
app.router(['user', 'timer'], async (ctx, next) => {
ctx.data.company = 'Tencent';
await next(); // 执行下一中间件
});
// 路由为字符串,该中间件只适用于 user 路由
app.router('user', async (ctx, next) => {
ctx.data.name = 'heyli';
await next(); // 执行下一中间件
}, async (ctx, next) => {
ctx.data.sex = 'male';
await next(); // 执行下一中间件
}, async (ctx) => {
ctx.data.city = 'Foshan';
// ctx.body 返回数据到小程序端
ctx.body = { code: 0, data: ctx.data};
});
// 路由为字符串,该中间件只适用于 timer 路由
app.router('timer', async (ctx, next) => {
ctx.data.name = 'flytam';
await next(); // 执行下一中间件
}, async (ctx, next) => {
ctx.data.sex = await new Promise(resolve => {
// 等待500ms,再执行下一中间件
setTimeout(() => {
resolve('male');
}, 500);
});
await next(); // 执行下一中间件
}, async (ctx)=> {
ctx.data.city = 'Taishan';
// ctx.body 返回数据到小程序端
ctx.body = { code: 0, data: ctx.data };
});
return app.serve();
}
tips: 小程序云函数的 node 环境默认支持 async/await 语法
小程序端
代码语言:txt复制// 调用名为 router 的云函数,路由名为 user
wx.cloud.callFunction({
// 要调用的云函数名称
name: "router",
// 传递给云函数的参数
data: {
$url: "user", // 要调用的路由的路径,传入准确路径或者通配符*
other: "xxx"
}
});
5 简单实现云开发服务端
(1)新建云函数 rubbish
(2)新建集合 rubbish
添加数据
代码语言:txt复制{"_id":"19b1e8b9-2662-471e-9a2d-dfda08b8b50d","goodsType":"湿垃圾","goodsName":"猕猴桃"}
{"_id":"72eb8a02-53a6-450a-9588-37a4408a3ff3","goodsType":"湿垃圾","goodsName":"苹果"}
(3)新建文件 utils/rubbish/ReturnUtil.js 用于对返回结果的处理
代码语言:txt复制/**
* 成功调用
* @param {*} ctx
* @retuen
*/
const success = ctx => {
return {
code: 0,
message: 'success',
data: ctx.data
}
}
/**
* 调用失败
* @param {*} ctx
* @param {*} msg
* @retuen
*/
const error = (ctx, msg) => {
return {
code: 400,
message: msg,
data: ctx.data
}
}
module.exports = {
success,
error
}
(4)加入 tcb-router 依赖
代码语言:txt复制npm install --save tcb-router
(5)rubbish/index.js
代码语言:txt复制// 云函数入口文件
const cloud = require('wx-server-sdk')
// 引入 tcb-router
const TcbRouter = require('tcb-router')
const returnUtil = require('utils/ReturnUtil.js')
// 初始化
cloud.init({
env: 'test-123'
})
// 获取数据库
const db = cloud.database();
// 操作 rubbish 集合公共部分
const rubbish_db = db.collection('rubbish');
// 云函数入口函数
exports.main = async (event, context) => {
const app = new TcbRouter({ event });
// app.use 表示该中间件会适用于所有的路由
app.use(async (ctx, next) => {
ctx.data = {};
await next(); // 执行下一中间件
});
/*************************** 垃圾分类 *****************************************/
// 获取单个垃圾分类信息
app.router('getRubbish', async (ctx, next) => {
console.log(event)
let data = JSON.parse(event.data)
ctx.data = await rubbish_db.where({ goodsName:data.name }).get();
ctx.body = await returnUtil.success(ctx)
await next();
})
return app.serve();
}
6 本地和服务器测试
6.1服务器测试
(1)打开云开发控制台 -> 云函数 ,点击 上面新建的 rubbish 的云端测试
(2)测试云函数
代码语言:txt复制{
// 路由
"$url": "getRubbish",
// 传递参数
"data":"{"name":"苹果"}"
}
6.2 本地调试
(1)打开本地调式
(2)点击 rubbish ,勾上开启本地调式 查看依赖是否安装
(3)安装依赖
如有依赖没有安装,在(1)步的界面中,点击在终端中打开 执行 npm install
。
(4)编写请求参数
代码语言:txt复制{
// 路由
"$url": "getRubbish",
// 传递参数
"data":"{"name":"苹果"}"
}
(5)调用云函数
7 Http 请求封装
网络请求的封装在小程中也能让代码更好修改,配置,维护。这里将进行网络请求和云开发请求的封装。
(1)新建 config.js
代码语言:txt复制// 配置请求公用参数
const config = {
// 网络请求
api_http_url: 'https://www.mxnzp.com/api',
// 云开发云函数
api_cloud_route:"rubbish"
}
// 导出配置文件
export { config }
(2)封装网络请求 utils/http-request.js
代码语言:txt复制import { config } from "../config.js"
class HTTP {
constructor() {
// 通过构造方法 实现 url 的赋值
this.api_http_url = config.api_http_url
}
//http请求
request(params) {
wx.request({
url: this.api_http_url params.url, // 接口地址拼装
method: params.method, // 接口类型 get/post/put/delete
data: params.data, // 传递给后台的参数
header: {
// 设置请求类型
'content-type': 'application/x-www-form-urlencoded'
},
success: (res) => {
let code = res.data.code.toString()
if (code.startsWith('1')) {
// 将请求的参数回调给上层
params.success(res)
}
},
fail: (error) => {
console.log(error)
},
complete: (res) => {
}
})
}
}
export {
HTTP
}
(3)封装云开发请求 utils/cloud-request.js
代码语言:txt复制// 导入配置文件
import { config } from "../config.js"
class CloudRequest{
constructor(){
this.api_cloud_route = config.api_cloud_route
}
request(params){
wx.cloud.callFunction({
// 要调用的云函数名称
name: this.api_cloud_route,
// 传递给云函数的参数
data: {
// 要调用的路由的路径,传入准确路径或者通配符*
$url: params.url,
// 请求参数
data: JSON.stringify(params.data)
},
success: res => {
// 结果回调
params.success(res)
},
fail: err => {
console.log(err)
}
})
}
}
export { CloudRequest }
下面我们将通过案例来分别使用我们的封装的请求。
8 客户端、服务端通信
8.1 网络请求
(1)自定义 model 层,models/IndexModel.js 类
代码语言:txt复制// 导入封装的 http 请求
import { HTTP } from '../utils/http-request.js'
// 继承 HTTP 直接调用其方法
class IndexModel extends HTTP {
/**
* 查询垃圾分类信息
* @param {*} callBack
*/
getRubbish(name,callback){
// http 请求
this.request({
url: "/rubbish/type", // 接口地址
data: {
name: name // 传递参数
},
// 接收 params.success(res) 回调参数
success: res => {
// 将数据再次回调
callback(res)
}
})
}
}
export { IndexModel }
在这里可能比较难得就是回调,回调。通过类进行请求的封装,在很大的使得代码更加简洁。model 层作为一个中间层来使用,无论是代码的复用和维护程度好了很多。
(2)实现 model 类
代码语言:txt复制// 第一步:导入
import { IndexModel } from '../../models/indexModel.js'
// 第二步:实例化
let indexModel = new IndexModel()
/ 第三步:调用方法,参数和方法中一一对应 res 接收callback回调参数
indexModel.getRubbish("苹果",res=>{
console.log(res)
this.setData({
httpItem:res.data.data.aim
})
})
代码语言:txt复制 <group-comp title="网络请求"></group-comp>
<view class="http-container ">
<view class="http-item">{{httpItem.goodsName}} : {{httpItem.goodsType}}</view>
</view>
(3)运行效果
8.2 云开发请求
(1)自定义 model 层,models/IndexCloudModel.js 类,其方法类似于 http
代码语言:txt复制// 导入封装的 http 请求
import { CloudRequest } from '../utils/cloud-request.js'
// 继承 CloudRequest 直接调用其方法
class IndexCloudModel extends CloudRequest {
/**
* 查询垃圾分类信息
* @param {*} callBack
*/
getRubbish(name,callBack) {
this.request({
url: "getRubbish",
data:{name:name},
success: res => {
callBack(res)
}
})
}
}
export { IndexCloudModel }
(2)实现 model 类
代码语言:txt复制// 第一步:导入
import { IndexCloudModel } from '../../models/indexCloudModel.js'
// 第二步:实例化
let indexCloudModel = new IndexCloudModel()
/ 第三步:调用方法,参数和方法中一一对应 res 接收callback回调参数
indexCloudModel.getRubbish("猕猴桃",res=>{
console.log(res)
this.setData({
cloudItem: res.result.data.data[0]
})
})
代码语言:txt复制<group-comp title="云函数请求" ></group-comp>
<view class="http-container ">
<view class="http-item">{{cloudItem.goodsName}} : {{cloudItem.goodsType}}</view>
</view>
(3)运行效果
在这里就封装了两种请求,这里封装的代码在多人开发和后期维护节省了不少时间,大家日常在开发也可以直接使用。
9 函数实现定时器
如果云函数需要定时 / 定期执行,也就是定时触发,我们可以使用云函数定时触发器。配置了定时触发器的云函数,会在相应时间点被自动触发,函数的返回结果不会返回给调用方,详情进入官方网址,比如:两小时后取消订单、定点定时推送商品信息等。
右击 cloud 选择 新建 Node.js 云函数
命名为 triggers
云函数创建触发器,必须建一个 config.json
文件,因为只有 config.json
才会有上传触发器选项。
- 一般 json 文件
- config.json
config.json 相比一般的 json 多出上传触发器和删除触发器 触发器也只有通过这样上传和删除后台才会执行。
config.json 解读
代码语言:txt复制{
// triggers 字段是触发器数组,目前仅支持一个触发器,即数组只能填写一个,不可添加多个
"triggers": [
{
// name: 触发器的名字,可以随意更改,规则见给出的官方链接
"name": "myTrigger",
// type: 触发器类型,目前仅支持 timer (即 定时触发器)
"type": "timer",
// config: 触发器配置,在定时触发器下,config 格式为 cron 表达式,规则见官方链接
"config": "0 0 2 1 * * *"
}
]
}
示例
下面展示了一些 Cron 表达式和相关含义的示例:
*/5 * * * * * *
表示每5秒触发一次0 0 2 1 * * *
表示在每月的1日的凌晨2点触发0 15 10 * * MON-FRI *
表示在周一到周五每天上午10:15触发0 0 10,14,16 * * * *
表示在每天上午10点,下午2点,4点触发0 */30 9-17 * * * *
表示在每天上午9点到下午5点内每半小时触发0 0 12 * * WED *
表示在每个星期三中午12点触发
接下来我们编写每十秒的触发器,进入 config.json
代码语言:txt复制{
"triggers": [
{
"name": "trigger",
"type": "timer",
"config": "*/10 * * * * * *"
}
]
}
注意:在创建触发器去掉触发器的注释 有注释上传在解析 json 会报错
编写 index.json
代码语言:txt复制// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
console.log("每十秒触发器执行一次测试。。。")
}
目前作为测试所以我们输出一句话测试下是否成功 因为云函数不会返回 所以 return 没有必要返回数据 。
编写云函数 triggers 下的 index.json 和 config.json ,点击 triggers 上传并部署:云端安装依赖,上传成功后,代有击 config.json 上传触发器,成功后我就在云开发后台去看下,选择云函数
函数名为 triggers 我们在日志控制面看可以看出输出时间是不是我们的触发时间,云函数的输出内容,如下图: