- 微信小程序开发快速入门-列表页编写(3/5)
前言 看到很多同学留言,继续更新的系列文章 《微信小程序开发快速入门-小程序之开发前准备(1/5)》 《微信小程序开发快速入门-第一个页面编写(2/5)》上次是编写了一个简单的静态页面,今天升级下难度讲解下跳转页面以及列表页面编写。 如何从启动页去列表页? 上章完成了备忘录启动页面,下一个页面就是列表页面。 [图片] 我们先新建一个页面叫做list,新建完成之后list页面会自动配置到app.json。 [图片] 这个时候我们小程序加载默认还是index页面,那么如何让它去list页面呢?在这里就需要用到小程序的「路由」。我们看到下面有很多路由到方法,那么到底该用哪个呢? 路由 简单介绍一下: wx.switchTab:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 wx.reLaunch:关闭所有页面,打开到应用内的某个页面 wx.redirectTo:关闭当前页面,跳转到应用内的某个页面。 wx.navigateTo:保留当前页面,跳转到应用内的某个页面。(最常用) wx.navigateBack:关闭当前页面,返回上一页面或多级页面。 基于业务来看,我们需要跳转到列表页面,但是我们不需要再回来了。所以我们要使用的是 redirectTo 这个函数来。 [图片] 然后我们是需要通过点击首页的按钮一下启动按钮进行跳转,所以只是找到路由API还是不能完成跳转的,这个时候就需要在这个按钮上面绑定上一个「事件」。 事件 我们了解了路由和事件之后,接下来就需要在image组件上面添加一个 bindtap(点击事件)绑定index.js 里面的 toList(跳转页面的函数),然后在这个函数里面调用路由API。 index.wxml [代码]<view class="container"> <image src="/images/home_logo.png" class="logo" ></image> <image bindtap="toList" src="/images/home_btn.png" class="btn"></image> </view> [代码] index.js [代码]Page({ /** * 只贴了使用到的方法,其他方法省略 */ // 跳转到列表页面 toList() { // 只需要将你需要跳转的页面设置到url参数上即可 wx.navigateTo({ url: '../list/list', }) }, }) [代码] 导航 除此之外还有一种写法,不需要绑定事件,在wxml使用「导航」组件即可。 [代码]<view class="container"> <image src="/images/home_logo.png" class="logo"></image> <navigator url="/pages/list/list" open-type="redirect"> <image src="/images/home_btn.png" class="btn"></image> </navigator> </view> [代码] 这样写的话,我们会发现默认有个点击效果,有点影响美观程度。通常遇到这种情况我们可以查下相关文件可以如何去除掉。 [图片] 在这里再分享一个小技巧,鼠标悬浮到组件上面会会显示一个文档地址提示,直接点击就可以到指定文档了。 [图片] 查阅navigator文档,我们可以看到hover-class属性设置为“none”就可以去除掉点击效果。 通常这些常用的属性官方组件都会有解决方案,所以遇到问题先详细看看文档大部分的问题都可以得到答案。 [图片] [代码]<view class="container"> <image src="/images/home_logo.png" class="logo"></image> <navigator url="/pages/list/list" hover-class="none" open-type="redirect"> <image src="/images/home_btn.png" class="btn"></image> </navigator> </view> [代码] 加上这个属性完美解决! 如果是简单的跳转我建议使用导航组件来实现。通常绑定事件都是需要处理复杂处理业务逻辑或者处理数据处理,不是单纯的跳转逻辑。写代码要注重能简单体现就简单点,这样代码可读性更强一些。 到这里我们就做到了从启动页去到了列表页面。在这个小节学习到路由、事件、导航,简单总结下: 路由:用于页面之间的跳转、传参 事件:⽤于让⻚⾯组件监听⽤户交互 导航:组件版本的简单路由 备忘录列表页 我们好不容易来到了列表页,于是开始了我们的列表页的布局编写。在开始布局之前我们先做一件事情,这个事情可以让我们在编写布局过程中提升效率,这件事情是什么事情了? 将列表页面添加编译模式。因为在布局的过程中肯定涉及到反复编译当前页面样式,要不断写样式来看效果,如果不添加编译模式那么每次都需要从启动页点击跳转到列表页,这样就会很低效,并且这个是重复无效率的时间浪费。 [图片] 添加完成之后,小程序开发工具会自动选中这个页面模式,我们现在就可以开启我们的高效编码了。写布局的第一步,先分析布局结构。 [图片] 列表页面布局从上往下看,一共分成两个大块:一是头部欢迎语,二是内容部分:有备忘录数据提示。 在继续向下分析头部:一个气泡然后里面有个头像和欢迎语,内容:没有数据的时候显示空布局提示还有新建按钮。然后把大概的布局结构写出来,我们得到这样的布局代码 [代码]<view> <!-- 头部 --> <view> <view> <!-- 头像 --> <image></image> <!-- 问候语 --> <text>,你来了?</text> </view> </view> <!-- 内容部分 --> <view> <!-- 提示图 --> <image src="../../images/empty.png"></image> <!-- 提示语 --> <text>这里空空</text> <!-- 新建按钮 --> <view>+ 新建</view> </view> </view> [代码] 然后看下页面效果: [图片] 是不是有点看不下去?不过这个没关系,我们把大概的结构写好之后就让它一步一步的变得美丽起来。首先从头部开始,先设置一个背景图填充下头部。 [代码].head_bg{ width: 750rpx; height: 540rpx; background-image: url(../../images/head_bg.png); } [代码] 在页面使用这个样式的时候小程序会报错。 [图片] 解决方案可见《微信小程序如何设置背景图片?》 解决后效果如下: [图片] 接下来写一下问候语部分布局的样式,先看设计图: [图片] 先看下布局代码,从结构上有一点变化。 [代码]<view> <!-- 头部 --> <view class="head-bg"> <view class="head-bubble"> <!-- 头像 --> <image class="user-avatar" src="头像地址"> </image> <!-- 问候语 --> <text>,你来了?</text> </view> </view> <!-- 省略部分无关代码 --> </view> [代码] 再看看样式部分,气泡背景和头部背景布局原理一样。气泡布局用定位属性(position)定到了码仔的右边,气泡内的布局采用的是flex布局,然后里面做了下头像和欢迎语的外边距微调。 [代码].head-bg { width: 750rpx; height: 540rpx; background-image: url('https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/head_bg.png'); background-size: 100% 100%; } .head-bubble { width: 286rpx; height: 127rpx; background-image: url('https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/bubble.png'); background-size: 100% 100%; position: absolute; left: 38rpx; top: 230rpx; display: flex; flex-direction: row; } .user-avatar { width: 50rpx; height: 50rpx; border-radius: 50%; overflow: hidden; margin-left: 35rpx; margin-top: 23rpx; } .head-bubble text { margin-left: 10rpx; margin-top: 30rpx; color: #6A5100; font-size: 28rpx; } [代码] 头部布局已完成,接下来搞定内容部分。相对头部布局,内容部分就简单多了,先看设计图: [图片] 这个布局相对简单。 [代码]<view> <!-- 头部 --> <view class="head-bg"> <view class="head-bubble"> <!-- 头像 --> <image class="user-avatar" src="头像地址"> </image> <!-- 问候语 --> <text>,你来了?</text> </view> </view> <!-- 内容部分 --> <view class="content"> <!-- 提示图 --> <image src="../../images/empty.png"></image> <!-- 提示语 --> <text class="content-tip">这里空空如也</text> <!-- 新建按钮 --> <view class="content-btn">+ 新建</view> </view> </view> [代码] [代码]/* 头部样式 */ .head-bg { width: 750rpx; height: 540rpx; background-image: url('https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/head_bg.png'); background-size: 100% 100%; } .head-bubble { width: 286rpx; height: 127rpx; background-image: url('https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/bubble.png'); background-size: 100% 100%; position: absolute; left: 38rpx; top: 230rpx; display: flex; flex-direction: row; } .user-avatar { width: 50rpx; height: 50rpx; border-radius: 50%; overflow: hidden; margin-left: 35rpx; margin-top: 23rpx; } .head-bubble text { margin-left: 10rpx; margin-top: 30rpx; color: #6A5100; font-size: 28rpx; } /* 内容样式 */ .content { display: flex; flex-direction: column; align-items: center; } .content image { width: 380rpx; height: 313rpx; margin-top: 100rpx; } .content-tip { width: 162rpx; height: 25rpx; font-size: 26rpx; font-weight: 400; color: #CCCCCC; margin-top: 30rpx; margin-bottom: 40rpx; } .content-btn { width: 340rpx; height: 90rpx; background: #F8D300; border-radius: 20rpx; color: #FFFEFE; text-align: center; line-height: 90rpx; } [代码] 在这里再告诉大家一个小技巧,在微调样式的时候可以使用调试器的Wxml功能进行样式上的数值调整。举个例子,假如我们要调整这个界面上的“我来了”这个布局外边距的值可以用小鼠标选中这个组件后然后双击点击Styles下面的属性值进行修改,支持用键盘的上下键进行1rpx的微调。 [图片] 这里要注意的是在这里修改的值不会影响wxss文件里面的样式值,重新编译一下值就恢复成原来的值了,在这里只是便于让你调试看效果,调试好你需要的位置后,还是需要复制调整好的值再次去修改wxss里面的值才行。 从无到有 无数据状态的列表页已经完成,但是这个页面看起来有点小寂寞。为了让这个页面不那么寂寞,我们先写一些假数据把有数据状态的列表页做一下,后续等把添加功能做完直接替换数据源即可。 老规矩,先分析页面布局:头部一样,无需关注。内容部分成为多条备忘录内容,然后添加页面变成了一个悬浮按钮在右下角。 [图片] 先把wxml的布局结构写出来,分成两块一个是单条内容布局,一个是添加图标。 注:这里我写的是单条内容的布局,同样的布局都是通过数据循环遍历出来的,后续会讲解如何循环。 [代码]<!-- 内容部分 --> <view class="content"> <view> <view> <text>我的第一款小程序的诞生</text> <text>2018-07-28</text> </view> <view>在这里我将毫无保留的与你分享自己这一路上的血与泪,抛 开技术,来谈谈与技术同样重要的成长方法论,让你……</view> </view> </view> <!-- 添加icon --> <image src="../../images/write.png" ></image> [代码] 目前布局效果,同样无法直视!不过没关系,开始编写具体样式。 [图片] 对比下已完成的效果图 [图片] [代码]<view> <!-- 省略无关代码 --> <!-- 内容部分 --> <view class="content"> <!-- 提示图 --> <!-- <image src="../../images/empty.png"></image> --> <!-- 提示语 --> <!-- <text class="content-tip">这里空空如也</text> --> <!-- 新建按钮 --> <!-- <view class="content-btn">+ 新建</view> --> <!-- 内容列表 --> <view class="list" > <view> <text class="list-title">我的第一款小程序的诞生</text> <text class="list-date">2018-07-28 \n 00:00</text> </view> <view class="list-content">在这里我将毫无保留的与你分享自己这一路上的血与泪,抛开技术,来谈谈与技术同样重要的成长方法论,让你……</view> </view> </view> <!-- 添加icon --> <image class="write" src="../../images/write.png" ></image> </view> [代码] [代码]/* 省略无关代码 */ /* 内容列表样式 */ .list { padding: 30rpx; } .list-title { font-size: 32rpx; font-weight: 500; color: #2C2C2C; } .list-date { font-size: 24rpx; font-weight: 400; color: #CCCCCC; position: absolute; right: 30rpx; text-align: right; } .list-content { margin-top: 50rpx; font-size: 26rpx; font-weight: 400; color: #CCCCCC; } .write { width: 108rpx; height: 108rpx; position: fixed; right: 20rpx; bottom: 150rpx; } [代码] 基础布局已经完成,接下来需要用到 WXML 语法之列表渲染,把单条内容变成多条内容。上效果 [图片] [代码]<view class="list" wx:for="12" > <view> <text class="list-title">我的第一款小程序的诞生</text> <text class="list-date">2018-07-28 \n 00:00</text> </view> <view class="list-content">在这里我将毫无保留的与你分享自己这一路上的血与泪,抛 开技术,来谈谈与技术同样重要的成长方法论,让你……</view> </view> [代码] 主要运用到了wx:for控制属性,我写了两位数的字符串就遍历了两条。 数据绑定 在实际业务中数据肯定不是固定,所以还需用运用到 WXML 语法之数据绑定。数据绑定的数据来源自于js文件data对象,页面上数据绑定使用 Mustache 语法(双大括号)将变量包起来。 list.js 小程序data的数据格式为 json。这里是在list.js的data里面添加以下数据。 [代码]/** * 页面的初始数据 */ data: { list: [{ title: '我的第1款小程序', date: '2021-09-01', time: '10:10', content: '在这里我将毫无保留的与你分享自己这一路上的血与泪,抛 开技术……' }, { title: '我的第2款小程序', date: '2021-09-01', time: '10:10', content: '在这里我将毫无保留的与你分享自己这一路上的血与泪,抛 开技术,来谈谈与技术同样重要的成长方法论,让你……' }] }, [代码] 使用wx:for,数组当前项的变量名默认为 item. [代码]<view class="list" wx:for="{{list}}" > <view> <text class="list-title">{{item.title}}</text> <text class="list-date">{{item.date}} \n {{item.time}}</text> </view> <view class="list-content">{{item.content}}</view> </view> [代码] 显示效果: [图片] 数据绑定除了可以应用到for数组对象遍历,还可以应用到单个文本。举个例子把“你来了?”这个问候语改成动态的“你好吗?”。 [代码] data: { message:'你好吗?' }, [代码] [代码] <!-- 问候语 --> <text>,{{message}}</text> [代码] [图片] 数据动态从js里面获取了,接下来还有个功能就是通过数据是否为空来控制不同的布局展示。在这里我们要应用到 WXML 语法之条件渲染。 Wxml 通过判断 isEmpty 这个变量来控制显示的布局,我们来看下 isEmpty 是在 js 里面如何定义的。 [代码]<!-- 无数据提示 --> <view wx:if="{{isEmpty}}" class="content"> <!-- 提示图 --> <image src="../../images/empty.png"></image> <!-- 提示语 --> <text class="content-tip">这里空空如也</text> <!-- 新建按钮 --> <view class="content-btn">+ 新建</view> <!-- 内容列表 --> </view> <!-- 有数据列表 --> <block wx:else> <view class="list" wx:for="{{list}}"> <view> <text class="list-title">{{item.title}}</text> <text class="list-date">{{item.date}} \n {{item.time}}</text> </view> <view class="list-content">{{item.content}}</view> </view> </block> [代码] isEmpty根据判断list数组的长度来控制显示,如果数组长度大于0就是false,否则就是true。这里用到了setData函数,这个函数用于设置data数据,因为很多数据并不是一开始就已经定义好了,大部分数据都是通过数据逻辑处理或者从其他数据源才能获得的,所以setData使用频率非常高。绑定isEmpty变量后就直接可以直接影响页面的显示结果了。 [代码]// pages/list/list.js Page({ /** * 页面的初始数据 */ data: { message:'你好吗?', list: [{ title: '我的第1款小程序', date: '2021-09-01', time: '10:10', content: '在这里我将毫无保留的与你分享自己这一路上的血与泪,抛 开技术……' }, { title: '我的第2款小程序', date: '2021-09-01', time: '10:10', content: '在这里我将毫无保留的与你分享自己这一路上的血与泪,抛 开技术,来谈谈与技术同样重要的成长方法论,让你……' }] }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ isEmpty:!this.data.list.length>0 }) }, }) [代码] 只要我们动态的改变data中的list内容就可以控制显示列表还是空布局了。 有数据状态: [图片] 无数据状态: [图片] 在这里有人肯定会说,为了看个效果还需要删除数据改变代码再编译,好麻烦,能不能简单点?可以!在这里我们需要用到调试器之AppData。 [图片] 在AppData数据区域可以随意修改数据,修改过程中页面实时渲染界面上的数据显示。这里修改的数据不影响实际数据,只用于调试看效果。这句话是不是有点似曾相识?没错就是和之前说过的调试器的Wxml调试样式一样一样的。一个样式调试神器一个数据调试神器,这两个调试工具也是小程序开发过程中最常用的。 到这里,数据列表页面也就完成了90%,还有10%就是替换成动态数据源。 [图片] 上面4个也没按,我们已经完成3个了,接下来还剩下一个添加备忘录页面了。今天 的教程就到此结束了。 最后 这一章节带大家完成了备忘录列表页面,学习了: 路由:用于页面/小程序之间的跳转 导航:可以理解成组件版本的路由 事件:用于组件与用户之间的交互 云存储使用:存储图片获取在线地址 调试器之Wxml样式调试与AppData数据调试 WXML语法:数据绑定、列表渲染、条件渲染 以上都是小程序开发常用技术,大家一定要自己实践多次加深印象。
2023-01-12 - vscode 上安装量最大的小程序开发插件
微信相关的 vscode 插件安装详情: [图片]
2018-11-21 - 云开发快速入门
如果你想免费、快速的开发出一个完整的项目,用小程序的云开发可能是最好的选择。小程序的云开发所用到的主要是前端开发的知识。 注册微信小程序 小程序的注册非常方便,打开小程序注册页面,按照要求填入个人的信息,验证邮箱和手机号,扫描二维码绑定你的微信号即可,3 分钟左右的时间即可搞定。 注册页面:小程序注册页面 https://mp.weixin.qq.com/ 注册小程序时不能使用注册过微信公众号、微信开放平台的邮箱哦,也就是需要你使用一个其他邮箱才行。 当我们注册成功后,就可以自动登入到小程序的后台管理页面啦,如果你不小心关掉了后台页面,也可以点击小程序后台管理登录页进行登录。 后台管理页:小程序后台管理登录页 https://mp.weixin.qq.com/ 小程序和微信公众号的登录页都是同一个页面,他们会根据你的不同的注册邮箱来进行跳转。 进入到小程序的后台管理页后,点击左侧菜单的开发进入设置页,然后再点击开发设置,在开发者 ID 里就可以看到 AppID(小程序 ID),这个待会我们有用。 注意小程序的ID(AppID)不是你注册的邮箱和用户名,你需要到后台查看才行哦~ 必备工具与云开发文档 大家可以根据自己的电脑操作系统来下载相应的版本,注意要选择稳定版 Stable Build 的开发者工具。 开发者工具:小程序开发者工具下载地址 和学习任何编程一样,官方技术文档都是最值得阅读的参考资料。技术文档大家先只需要花五分钟左右的时间了解大致的结构即可,先按照我们的教学步骤学完之后再来看也不迟哦。 技术文档:云开发官方文档 由于小程序的云开发在不断新增功能,更新非常频繁,所以要确保自己的开发者工具是最新的哦(不然会报很多奇奇怪怪的错误),比如你之前下载过要先同步到最新才行~ 体验云开发模板小程序 安装完开发者工具之后,我们使用微信扫码登录开发者工具,然后使用开发者工具新建一个小程序的项目: 项目名称:这个可以根据自己的需要任意填写;目录:大家可以先在电脑上新建一个空文件夹,然后选择它;AppID:就是之前我们找到的 AppID(小程序 ID)(也可以下拉选择 AppID)开发模式为小程序(默认),后端服务选择小程序·云开发点击新建确认之后就能在开发者工具的模拟器里看到云开发 QuickStart 小程序,在编辑器里看到这个小程序的源代码。 接下来,我们点击开发者工具的工具栏里的预览图标,就会弹出一个二维码,使用微信扫描这个二维码就能在手机里看到这个小程序啦。 如果你没有使用微信登录开发者工具,以及你的微信不是该小程序的开发者是没法预览的哦。 在手机里(或模拟器)操作这个小程序,把小程序里的每个按键都点一遍,看看会有什么反应。我们会发现很多地方都会显示“调用失败”等,这非常正常,我们接下来会通过一系列的操作让小程序不报错。 开通云开发服务 点击微信开发者工具的“云开发”图标,在弹出框里点击“开通”,同意协议后,会弹出创建环境的对话框。这时会要求你输入环境名称和环境 ID,以及当前云开发的基础环境配额(基础配额免费,而且足够你使用哦)。 建议你环境名称可以使用 xly、环境ID自动生成即可,当你的云开发环境出现问题的时候,你可以提供你的环境ID,云开发团队会有专人为你解答。 按照对话框提示的要求填写完之后,点击创建,会初始化环境,环境初始化成功后会自动弹出云开发控制台,这样我们的云开发服务就开通啦。大家可以花两分钟左右的时间熟悉一下云开发控制台的界面。 找到云开发的环境 ID 点击云开发控制台窗口里的设置图标,在环境变量的标签页找到环境名称和环境 ID。 当云开发服务开通后,我们可以在小程序源代码 cloudfunctions 文件夹名看到你的环境名称。如果在 cloudfunctions 文件夹名显示的不是环境名称,而是“未指定环境”,可以鼠标右键该文件夹,选择“更多设置”,然后再点击“设置”小图标,选择环境并确定。 指定小程序的云开发环境 在开发者工具中打开源代码文件夹 miniprogram 里的 app.js,找到如下代码: wx.cloud.init({ // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 env: 'my-env-id', traceUser: true, }) 在 env: 'my-env-id'处改成你的环境 ID,如 env: 'xly-snoop' 下载 Nodejs NodeJS 是在服务端运行 JavaScript 的运行环境,云开发所使用的服务端环境就是 NodeJS。npm 是 Node 包管理器,通过 npm,我们可以非常方便的安装云开发所需要的依赖包。 npm是前端开发必不可少的包(模块)管理器,它的主要功能就是来管理包package,包括安装、卸载、更新、查看、搜索、发布等,其他编程语言也有类似的包管理器,比如Python的pip,PHP的composer、Java的maven。我们可以把包管理器看成是windows的软件管理中心或手机的应用中心,只是它们用的是可视化界面,包管理器用的是命令行Command Line。 下载地址:Nodejs 下载地址 大家可以根据电脑的操作系统下载相应的 NodeJS 安装包并安装(安装时不要修改安装目录,啥也别管直接 next 安装即可)。打开电脑终端(Windows 电脑为 cmd 命令提示符,Mac 电脑为终端 Terminal),然后逐行输入并按 Enter 执行下面的代码: node --version npm --version 如果显示为 v10.15.0 以及 6.11.3(可能你的版本号会有所不同),表示你的 Nodejs 环境已经安装成功。 学编程要仔细,一个字母,一个单词,一个标点符号都不要出错哦。注意输上面的命令时node、npm的后面有一个空格,而且是两个短横杠–。 部署并上传云函数 部署并上传云函数 cloudfuntions 文件夹图标里有朵小云,表示这就是云函数根目录。展开 cloudfunctions,我们可以看到里面有 login、openapi、callback、echo 文件夹,这些就是云函数目录。而 miniprogram 文件夹则放置的是小程序的页面文件。 cloudfunctions里放的是云函数,miniprogram放的是小程序的页面,这并不是一成不变的,也就是说你也可以修改这些文件夹的名称,这取决于项目配置文件project.config.json里的如下配置项: "miniprogramRoot": "miniprogram/", "cloudfunctionRoot": "cloudfunctions/", 但是你最好是让放小程序页面的文件夹以及放云函数的文件夹处于平级关系且都在项目的根目录下,便于管理。 使用鼠标右键其中的一个云函数目录比如 login,在右键菜单中选择在终端中打开,打开后在终端中输入以下代码并按 Enter 回车执行: npm install 如果显示“npm不是内部或外部命令”,你需要关闭微信开发者工具启动的终端,而是重新打开一个终端窗口,并在里面输入 cd /D 你的云函数目录进入云函数目录,比如 cd /D C:\download\tcb-project\cloudfunctions\login进入login的云函数目录,然后再来执行npm install命令。 这时候会下载云函数的依赖模块,下载完成后,再右键 login 云函数目录,点击“创建并部署:所有文件”,这时会把本地的云函数上传到云端,上传成功后在 login 云函数目录图标会变成一朵小云。 在开发者工具的工具栏上点击“云开发”图标会打开云开发控制台,在云开发控制台点击云函数图标,就能在云函数列表里看到我们上传好的“login”云函数啦。 上传所有云函数 接下来我们按照这样的流程把其他所有云函数(如 openapi)都部署都上传,也就是要执行和上面相同的步骤,总结如下: 右键云函数目录,选择在终端中打开,输入 npm install命令下载依赖文件; 然后再右键云函数目录,点击“创建并部署:所有文件” 在云开发控制台–云函数–云函数列表查看云函数是否部署成功。 login、openapi、echo、callback这些云函数在后面都会用到的哦,一定要确定自己部署上传成功,不然后面会报错的哦。 npm 包管理器与依赖模块 为什么要在云函数目录执行 npm install,而不是其他地方?这是因为 npm install 会下载云函数目录下的配置文件 package.json 里的 dependencies,它表示的是当前云函数需要依赖的模块。package.json 在哪里,就在哪里执行 npm install,没有 package.json,没有 dependencies,就没法下载啊。 执行 npm install 命令下载的依赖模块会放在 node_modules 文件夹里,大家可以在执行了 npm install 命令之后,在电脑里打开查看一下 node_modules 文件夹里下载了哪些模块。 既然 npm install 是下载模块,那它是从哪里下载的呢?就以 wx-server-sdk 为例,我们可以在以下链接看到 wx-server-sdk 的情况: https://www.npmjs.com/package/wx-server-sdk 为什么 package.json 里依赖的是一个模块 wx-server-sdk,但是 node_modules 文件夹里却下载了那么多模块?这是因为 wx-server-sdk 也依赖三个包 tcb-admin-node、protobuf、jstslib,而这三个包又会依赖其他包,子子孙孙的,于是就有了很多模块。 node_modules 文件夹这么大(几十 M~几百 M 都可能),会不会影响小程序的大小?小程序的大小只与 miniprogram 文件夹有关,当你把云函数都部署上传到服务器之后,你把整个 cloudfuntions 文件夹删掉都没有关系。相同的依赖(比如都依赖 wx-server-sdk)一旦部署到云函数之后,你可以选择不上传 node_modules 时,因为已经上传过了。 获取 openid 与云函数 login 当我们把云函数 login 部署上传成功后,就可以在模拟器以及手机(需要重新点击预览图标并扫描二维码)里点击获取 openid 了。 点击获取 openid openid 是小程序用户的唯一标识,也就是每一个小程序用户都有一个唯一的 openid。点击“点击获取 openid”,在用户管理指引页面如果显示“用户 id 获取成功”以及一串字母+数字,那么表示你 login 云函数部署并上传成功啦。如果获取 openid 失败,你则需要解决 login 云函数的部署上传,才能进行下面的步骤哦。 调用云函数的解读 小程序的首页是”pages/index/index”,我们可以从 app.json 的配置项或者模拟器左下角的页面路径可以看出来。在 index.wxml 里有这段代码: <button class="userinfo-nickname" bindtap="onGetOpenid">点击获取 openid</button> 也就是当点击“点击获取 openid”按钮时,会触发 bindtap 绑定的事件处理函数 onGetOpenid,在 index.js 里可以看到 onGetOpenid 事件处理函数(在 index.js 里找到事件处理函数 onGetOpenid 对比理解)调用了 wx.cloud.callFunction()接口(打开技术文档对比理解) 技术文档:调用云函数 wx.cloud.callFunction 调用云函数的方法很简单,只需要填写云函数的名称 name(这里为 login),以及需要传递的参数(这里并没有上传参数),就可以进行调用。在 success 回调函数里添加以下代码打印 res 对象: console.log('调用login云函数返回的res',res) 添加完成之后记得保存代码哦,文件修改没有保存会在标签页有一个小的绿点。可以使用快捷键(同时按)Ctrl和S来保存(Mac电脑为Command和S)。 编译之后,再点击“点击获取 openid”按钮,就能看到完整的 res 对象,res 对象有三个参数: requestID:云函数执行 ID,可用于在云开发控制台查找日志,打开云开发控制台–云函数–日志,可以在这里根据云函数函数名以及 requestID 来筛选查看云函数的调用日志(含返回结果);result:云函数返回的结果,login 云函数返回的结果里包含 appid、event 对象,我们可以通过 res.result.appid 以及 res.result.event 访问它们;errMsg:显示云函数是否调用成功事件处理函数 onGetOpenid 调用云函数成功之后,干了三件事情: 使用 console.log 打印 openid,可以在点击按钮触发云函数在控制台看到该打印结果;把获取到的 appid 赋值给 app.js 文件里的 globalData 全局对象;跳转到 userConsole 页面;而 userConsole 页面就只是从 globalData 里将 openid 取出来通过 setData 渲染到页面。 小任务:你明白为啥wx.cloud.callFunction()是小程序端的API了么?思考一下为啥云开发会有小程序端的API和服务端API的区别?能理解多少是多少,不清楚也没有关系,后面会有更多内容助你理解。 云函数 login 解读 为什么调用云函数 login 返回的 res 的 result 对象里会包含 event 对象、appid、userInfo 这些结果?这就取决于云函数是怎么写的了。使用开发者工具打开 login 云函数(在 cloudfuntions 文件夹里)的 index.js。 exports.main = (event, context) => {} 这是一个箭头函数的写法,其中 event 和 context 是参数。我们将两个打印日志修改为以下代码,相当于备注一下到底打印到哪里去了: console.log('服务端打印的event',event) console.log('服务端打印的context',context) 保存之后,右键点击 index.js 文件,选择云函数增量上传:(更新文件),更新 login 云函数,我们再来点击“点击获取 openid”按钮,打印的结果在哪里呢?在云开发控制台的云函数日志里面(注意不是开发者工具的控制台)。打开云开发控制台–云函数–日志,按函数名筛选,选择 login 云函数,可以看到云函数被调用的日志记录,我们可以在日志里发现: event 对象包含程序用户的 openid 和小程序的 appid,而 openid 就相当于用户的身份证,我们可以根据 openid 获取到用户的昵称、头像等信息(后面会说明);而 context 对象则是云函数的调用信息和运行状态。在返回结果里我们可以看到 return 返回的数据小任务:比较一下云开发控制台的云函数日志打印的结果和开发者工具控制台打印的结果,深入了解 event 对象、context 对象、result 对象与返回结果,这是云函数的比较重要的知识点。云函数的打印日志会显示在云开发控制台的日志里面,这一点非常重要,要多加利用。只要是打印日志,无论是显示在开发者工具控制台还是显示在云开发控制台的就没有不重要的。 getWXContext() getWXContext()API 是云开发服务端的工具类 API,会返回小程序用户的 openid、小程序 appid、小程序用户的 unionid 等。说这么多不如直接打印,在下面添加一行打印信息: const wxContext = cloud.getWXContext() console.log('getWXContext返回的结果',wxContext) 保存之后,右键点击 index.js 文件,选择云函数增量上传:(更新文件),更新 login 云函数,我们再来点击“点击获取 openid”按钮,然后去云开发控制台的云函数日志里看到底返回了什么结果。 技术文档:getWXContext() 对照技术文档来理解返回的结果。 注意小程序用户 unionid只有在开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用才能获得。 return return 语句是终止函数的执行,并返回一个指定的值给函数调用者。这里返回了 4 个值,而前面我们就调用过 login 云函数,就是函数的调用者,所以我们打印的事件处理函数 onGetOpenid 的回调函数的 res 对象正是这个 return 返回的结果。那既然如此,我们在 return 多加一些内容看看,比如我们之前的一些数据结构案例,将 return 函数改为如下代码: let lesson = "云开发技术训练营"; let enname = "CloudBase Camp"; let x = 3, y = 4, z = 5.001, a = -3, b = -4, c = -5; let now = new Date(); return { movie: { name: "霸王别姬", img: "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p1910813120.webp", desc: "风华绝代。" }, movielist:["肖申克的救赎", "霸王别姬", "这个杀手不太冷", "阿甘正传", "美丽人生"], charat: lesson.charAt(4), concat: enname.concat(lesson), uppercase: enname.toUpperCase(), abs: Math.abs(b), pow: Math.pow(x, y), sign: Math.sign(a), now: now.toString(), fullyear: now.getFullYear(), date: now.getDate(), day: now.getDay(), hours: now.getHours(), minutes: now.getMinutes(), seconds: now.getSeconds(), time: now.getTime(), event, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } 保存之后,右键点击 index.js 文件,选择云函数增量上传:(更新文件),更新 login 云函数,我们再来点击“点击获取 openid”按钮,然后去云开发控制台的云函数日志里看到底返回了什么结果。 这里我们多次反复提及更新了index.js文件之后就要选择云函数增量上传:(更新文件),更新login云函数,希望大家平时的时候注意,这也是小程序云开发服务端和小程序端一个非常大的区别。 新建云函数 鼠标右键 cloudfunctions 云函数根目录,在弹出的窗口选择新建 Node.js 云函数,比如输入 sum,按 Enter 确认后,微信开发者工具会在本地(你的电脑)创建出 sum 云函数目录,同时也会在线上环境中创建出对应的云函数(也就是自动部署好了,可以到云开发控制台云函数列表里看到) 打开 sum 云函数目录下的 index.js,添加 sum:event.a+event.b,到 return 函数里(把多余的内容可以删掉了),然后记得选择云函数增量上传:(更新文件),更新 sum 云函数。 return { sum:event.a+event.b, } 这个 a 和 b 是变量,但是和前面不一样的是,在服务端我们并没有声明 a 和 b 啊,这是因为我们可以在小程序端声明变量。 点击开发者工具模拟器的“快速新建云函数”,会跳转到 addFunction 页面,打开 addFunction.wxml,我们看到测试云函数绑定的是 testFunction 事件处理函数。 <view class="list-item" bindtap="testFunction"> <text>测试云函数</text> </view> 我们去看 addFunction.js 里的 testFunction,看变量 a 和 b 这两个小程序端的变量是怎么和服务端的变量关联起来的,而又是如何把结果渲染到页面的。testFunction 调用云函数 sum 同样是通过 wx.cloud.callFunction,不同的是在 data 里有 a 和 b: data: { a: 1, b: 2 }, data 里填写的是传递给云函数的参数,也就是先把小程序端的参数传递给云函数,然后云函数处理之后再返回 res 对象,我们可以在 success 回调函数里打印 res 对象: console.log("sum云函数返回的对象",res) 编译之后,我们再点击测试云函数,在控制台就能看到打印的结果,res.result.sum 就是 3。直接把 res.result.sum 通过 setData 赋值到 result 就能渲染出数字,那这个 res.result 是什么?JSON.stringify()又是什么? result: JSON.stringify(res.result) 我们可以打印一下 res.result,以及 JSON.stringify(res.result) console.log("res.result是啥", res.result) console.log("JSON.stringify(res.result)是啥", JSON.stringify(res.result)) res.result 是对象,而 JSON.stringify(res.result)是 json 格式, JSON.stringify() 方法是将一个 JavaScript 值(对象或者数组)转换为一个 JSON 字符串,因为对象如果直接渲染到页面是会显示 [object Object]的。 小任务:将小程序的参数传递给云端,有没有一点wx.request的感觉?相当于我们通过云函数写好了一个数据API,然后在小程序端调用。新建一个云函数,把各种数学运算都部署到云端,然后通过传递参数,调用这些算法,并将结果渲染到页面。 体验上传图片 上传图片到云存储 使用模拟器以及手机端点击云开发 QuickStart 小程序的上传图片按钮,选择一张图片并打开,如果在文件存储指引页面显示上传成功和文件的路径以及图片的缩略图,说明你的图片就上传到云开发服务器里啦。 点击云开发控制台的存储图标,就可以进入到存储管理页查看到你之前上传的图片啦,点击该图片名称可以看到这张图片的一些信息,如:文件大小、格式、上传者的 OpenID 以及存储位置、下载地址和 File ID。复制下载地址链接,在浏览器就能查看到这张图片啦。 值得注意的是由于QuickStart小程序将“上传图片”这个按钮上传的所有图片都命名为my-image,所以上传同一格式的图片就会被覆盖掉,也就是无论你上传多少张相同格式的图片,只会在后台里看到最后更新的那张图片。以后我们会教大家怎么修改代码,让图片不会被覆盖。 组件支持 我们可以把下载地址作为图床来使用的,也就是你可以把图片的下载地址放到其他网页图片是可以显示的。云存储的图片还有一个 FileID(既云文件 ID,以 cloud://开头)则只能用于小程序的特定场景,也只有部分组件的部分属性支持,把链接粘贴到浏览器也是打不开的。 技术文档:组件支持 比如我们在 index 页面的 index.wxml 里输入以下代码,在 image 组件的 src 属性里输入你的云存储图片的 FileID,它是可以显示出来的。 <image src="你的图片的FileID"></image> 但是如果你退出登录开发者工具,图片就不会显示,而且还会报错,所以不要把图片的 FileID 当做图床用,FileID 另有它用。 体验云调用之服务端调用 重新点击开发者工具的预览图标,然后用手机扫描二维码,在手机端点击云开发 QuickStart 的云调用里的服务端调用,就可以发送模板消息和获取小程序码。 点击获取小程序码,如果显示调用失败,说明你的 openapi 云函数没有部署成功,需要你先部署成功才行哦。调用成功,就能获取到你的小程序码啦,这个小程序码也会保存到云开发的存储里。 发送模板消息,只能在手机微信里预览测试哦,使用微信开发者工具是发送不了模板消息,而且控制台还会报错 点击发送模板消息,你的微信就会收到一则服务通知,该通知是由你的小程序发出的购买成功通知。这就是微信的模板消息啦,很多微信公众号、小程序都会有这样的功能,使用小程序云开发,我们也可以轻松定制自己的服务通知(后面会教大家如何定制)。 体验前端操作数据库 点击微信开发者工具的云开发图标,打开云开发控制台,点击数据库图标进入到数据库管理页,点击集合名称右侧的+号图标,就可以创建一个数据集合了,这里我们只需要添加一个 counters 的集合(不需添加数据)即可。 在开发者工具的编辑器里展开 miniprogram 文件夹,打开 pages 文件下 databaseGuide 里的 databaseGuide.js 文件,在这里找到 onAdd: function (){}、 onQuery: function (){}、 onCounterInc: function (){}、 onCounterDec: function (){}、 onRemove: function (){}分别选中绿色的代码块,然后同时按快捷键 Ctrl 和/(Mac 电脑的快捷键为 Command 和/),就可以批量取消代码的注释。 //是前端编程语言JavaScript的单行注释,位于 // 这一行的代码都不会执行,我们使用快捷键就是批量取消这些代码的注释,让整段代码生效。之所以显示为绿色,是微信开发者工具为了让我们看得更清晰而做的语法高亮。 前端操作数据库的页面逻辑 以上的函数是在小程序的前端页面来操作数据库,点击开发者工具模拟器云开发 QuickStart 里的前端操作数据库, 在第1步(数据库指引有标注),我们会获取到用户的openid,也就是说你没有获取到openid是没法通过小程序的前端来操作数据库的哦 第2步,需要我们在云开发控制台里的数据库管理页创建一个counters的集合(不需添加数据); 第3步,点击按钮页面的按钮“新增记录”(按钮就在这个页面的第4条与第5条之间,看起来不是那么明显),这时会调用 onAdd方法,往counters集合新增一个记录(之前手动添加有木有很辛苦?),我们可以去云开发控制台的数据库管理页查看一下counters集合是不是有了一条记录;大家可以多点击几下新增记录按钮,然后去云开发控制台看数据库又有什么变化。也就是小程序前端页面通过 onAdd方法,在数据库新增了记录。 第4步,点击按钮查询记录,这时调用的是 onQuery方法就能在小程序里获取到第3步我们存储到数据库里的数据啦 第5步,点击计数器按钮+号和-号,可以更新count的值,点击+号按钮会调用 onCounterInc方法,而点击-号 onCounterDec方法,比如我们点击加号到7,再去数据库管理页查看最新的一条记录(也就是最后一条),它的count由原来的1更新到了7(先点刷新按钮),我们再点击-号按钮到5,再来数据库管理页查看有什么变化变化(先点刷新按钮) 第6步,点击删除记录按钮,会调用 onRemove方法,这时会删掉数据库里最新的记录(也就是第5步里的那一条记录)。 通过实战我们了解到,databaseGuide.js 文件里的 onAdd、 onQuery、 onCounterInc、 onCounterDec、 onRemove 可以实现小程序的前端页面来操作数据库。 这些函数大家可以结合 databaseGuide.js 文件和云开发技术文档关于数据库的内容来理解。(关于前端是如何操作数据库的,我们之后还会深入讲解,这里只需要了解大致的逻辑即可) 在前面JavaScript的章节里我们了解到数据以及数据的存储是非常重要的,而有了数据库,用函数生成的数据能够比缓存存储的更加持久,而且在上面我们实现了对数据进行增(添加)、删(删除)、改(修改、更新)、查(查询并渲染到页面),不仅如此,缓存的容量也比较有限,最多不过10M,而数据库可以存几百G以上,可见它的重要性。 开始一个新的云开发项目 基于云开发 QuickStart 模板小程序 云开发 QuickStart 模板小程序有很多多余的页面,这个我们只需要把 miniprogram 文件夹下的 pages、images、components、style 文件夹里的文件清空,以及 app.json 的 pages 配置项里的页面删除,把 app.wxss 里的样式代码都删掉就是一个全新的开始啦。这是方法之一,也可以使用下面的方法(推荐学习时使用下面的方法)。 基于没有使用云开发的项目改造 当然我们也可以把前面章节没有使用云开发的项目改造成使用云服务,首先在小程序的根目录下新建一个文件夹,比如 cloudfunctions,然后在 project.config.json 添加云函数文件夹的路径配置即可, "cloudfunctionRoot": "cloudfunctions/", 然后新建一个 miniprogram 文件夹,把小程序除了 project.config.json 以外的其他文件,比如 pages、utils、images、app.js、app.json 等文件都放到 miniprogram 文件夹里,再在 project.config.json 添加 miniprogramRoot 配置: "cloudfunctionRoot": "cloudfunctions/", "miniprogramRoot":"miniprogram/", 值得一提的是,云函数部署上传成功,我们就可以一直调用,只要你的小程序的appid以及环境ID没有变,你创建再多的小程序项目,都可以直接调用部署好的云函数,比如前面的login、echo、callback、sum等云函数。也就是说云函数一旦部署成功,它就一直在云端服务器里,哪怕你把小程序本地的云函数都删掉也没有关系。 当新建了并配置了云函数根目录为 cloudfunctions 文件夹之后,云函数根目录里并没有云函数,我们可以右键点击云函数根目录 cloudfunctions 文件夹选择同步云函数列表,可以把所有云端的云函数列表都列举出来(这只是列举了列表),而要修改云函数里面的内容,我们可以右键点击其中的一个云函数目录选择下载云函数即可。 除此之外,我们需要小程序的 app.js 的生命周期函数 onLaunch 里使用 wx.cloud.init()来初始化云开发能力: onLaunch: function () { if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力') } else { wx.cloud.init({ env: '你的环境ID', traceUser: true, }) } }, 云开发能力全局只需要初始化一次即可,这里的 traceUser 属性设置为 true,会将用户访问记录到用户管理中,在云开发控制台的运营分析—用户访问里可以看到访问记录。 基础库与 wx.cloud 在小程序端初始化云开发能力的代码里,涉及到 wx.cloud 以及基础库版本的知识。关于 wx.cloud,我们可以和之前在控制台了解 wx 对象一样,直接在开发者工具的控制台里输入: wx.cloud 来了解对象有哪些属性与方法。我们可以看到有如下方法: CloudID: ƒ () //用于云调用获取开放数据 callFunction: ƒ () //调用云函数 database: ƒ () //获取数据库的引用 deleteFile: ƒ () //从云存储空间删除文件 downloadFile: ƒ () //从云存储空间下载文件 getTempFileURL: ƒ () //用云文件 ID 换取真实链接 init: ƒ () //初始化云开发能力 uploadFile: ƒ () //上传文件至云存储空间 而关于基础库,有三个地方需要注意它的存在,平时开发的时候需要留意开发者工具的project.config.json里有这样一个属性libVersion,这个也可以在开发者工具工具栏右上角的详情里的本地设置里的调试基础库,建议切换到最新,切换后libVersion的值也会修改到切换的版本; 官方文档基础库的更新日志,小程序更新非常频繁,而更新的核心就是基础库:所以基础库更新日志要经常留意每个API,技术文档都会标明它的基础库支持的最低版本,而小程序·云开发 SDK是2.2.3以上的基础库才开始支持的。
2021-09-10