openid与云开发
总结一下,用户在小程序里有着独一无二的openid,相同的用户在不同的小程序openid也不同,因此我们完全可以用openid来区分用户,而且openid贯穿于小程序端、云存储、云函数、数据库等之中:
- 使用云开发时,用户在小程序端上传文件到云存储,这个openid会被记录在文件信息里;
- 添加数据到数据库这个openid会被保存在_openid的字段里;
- 我们还可以使用云函数的Cloud.getWXContext()来获取用户的openid;
获取小程序用户信息
从小程序端调用云函数时,开发者可以在云函数内使用 wx-server-sdk 提供的 getWXContext 方法获取到每次调用的上下文(appid、openid 等),无需维护复杂的鉴权机制,即可获取天然可信任的用户登录态(openid)。可以写这么一个云函数进行测试:
// index.js
const cloud = require('wx-server-sdk')
exports.main = async (event, context) => {
// 这里获取到的 openId、 appId 和 unionId 是可信的,注意 unionId 仅在满足 unionId 获取条件时返回
let { OPENID, APPID, UNIONID } = cloud.getWXContext()
return {
OPENID,
APPID,
UNIONID,
}
}
假设云函数命名为 test,本地调试/上传并部署该云函数后,可在小程序中测试调用:
wx.cloud.callFunction({
name: 'test',
complete: res => {
console.log('callFunction test result: ', res)
}
})
会在调试器看到输出的 res 为如下结构的对象:
{
"APPID": "xxx",
"OPENID": "yyy",
"UNIONID": "zzz", // 仅在满足 unionId 获取条件时返回
}
使用onGetUserInfo来获取用户信息和 wx.getUserInfo的区别:
使用onGetUserInfo来获取用户信息的作用和 wx.getUserInfo API基本效果是一样的,区别在于wx.getUserInfo 这种方式最好是在用户允许获取公开信息(也就是res.authSetting[‘scope.userInfo’]的值为true)之后再调用,如果用户拒绝了授权就不会再有弹窗(除非用户删掉了你的小程序再使用),调用就会失败,而使用组件的方式是用户主动点击,用户即使拒绝了,再点击仍会弹出授权弹窗。所以推荐先使用组件来获取用户授权,然后再来使用wx.getUserInfo来获取用户信息。
微信小程序新建页面的两种方法
方法一
使用开发者工具在pages文件夹下新建页面。首先选中pages文件夹,然后点击上方的**+**号文件夹或鼠标右键,新建目录,然后输入目录名为post,然后再选中post文件夹,新建页面,页面名也为post,新建之后看看pages配置项的变化。
方法二
通过app.json新建页面
pages配置项是设置页面的路径,也就是我们在小程序里写的每一个页面都需要填写在这里。使用开发者工具打开app.json文件,在pages配置项里新建一个home页面(页面名称可以是任意英文名),代码如下:
"pages/home/home",
"pages/index/index",
"pages/logs/logs"
大家再来看看小程序的文件夹结构,是不是在pages文件夹下面多了一个home的文件夹?而且这个文件夹还自动新建了四个页面文件。
WXSS书写技巧
.desc,.item-desc{
color: #333;
}
大家注意,我们这里有两个选择器,一个是desc,一个是item-desc,当我们希望两个不同的选择器有相同的css代码时,可以简化一起写,然后用逗号,隔开。
navigator的src的两种写法:
一、
<navigator url="./../home/imgshow/imgshow" class="item-link">让小程序显示图片</navigator>
二、
url="/pages/home/imgshow/imgshow"
相对路径与绝对路径
大家注意我们之前使用的路径基本都是相对路径,相对路径使用“/”字符作为目录的分隔字符,
./ 代表当前目录 <img src=”./img/icon.jpg” /> 等同于<img src=”img/icon.jpg” />
../ 代表上一级目录
/ 指的是当前根目录,是相对目录;<img src=”/img/icon.jpg” />
那什么是绝对路径呢?网络链接比如 :
https://hackwork.oss-cn-shanghai.aliyuncs.com/lesson/weapp/4/weapp.jpg
这个就是绝对路径,还有C:\Windows\System32
,这种从盘符开始的路径也是绝对路径。通常相对路径用的会比较多一些。
列表渲染
<view wx:for="{{newstitle}}" wx:key="*this">
{{item}}
</view>
这里wx:for=”{{newstitle}}”,也就是在数组newstitle里进行循环,*this 代表在 for 循环中的 item 本身,而{{item}}的item是默认的。也可以使用如下方法:
<view wx:for-items="{{newstitle}}" wx:for-item="title" wx:key="*this">
{{title}}
</view>
默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item; 使用 wx:for-item
可以指定数组当前元素的变量名,使用 wx:for-index 可以指定数组当前下标的变量名。
条件渲染
<view wx:if="{{female > 5}}"> 如果女生人数多于5人就显示</view>
<view wx:if="{{female > 10}}"> 如果女生人数多于10人就显示</view>
2.hidden属性的用法
组件都有公共属性,而其中公众属性hidden也是可以控制微信小程序中组件的显示与否。hidden为false组件显示,hidden为true组件隐藏。值得注意的是hidden在隐藏时仍然渲染,只是不呈现
微信公众平台网页版客服工具
https://mpkf.weixin.qq.com/
删除对象的某个属性
比如我们想删除movie的img属性,可以通过delete 方法来删除
delete movie.img
Math对象
let x=3,y=4,z=5.001,a=-3,b=-4,c=-5;
console.log(Math.abs(b)); //返回b的绝对值
console.log(Math.round(z));//返回z四舍五入后的整数
console.log(Math.pow(x,y)) //返回x的y次幂
console.log(Math.max(x,y,z,a,b,c)); //返回x,y,z,a,b,c的最大值
console.log(Math.min(x,y,z,a,b,c));//返回x,y,z,a,b,c的最小值
console.log(Math.sign(a)); //返回a是正数还是负数
console.log(Math.hypot(x,y)); //返回所有x,y的平方和的平方根
console.log(Math.PI); //返回一个圆的周长与直径的比例,约3.1415
Date对象
let now = new Date(); //返回当日的日期和时间。
console.log(now);
console.log(now.getFullYear()); //从 Date 对象以四位数字返回年份。
console.log(now.getMonth()); //从 Date 对象返回月份 (0 ~ 11)。
console.log(now.getDate()); //从 Date 对象返回一个月中的某一天 (1 ~ 31)。
console.log(now.getDay()); //从 Date 对象返回一周中的某一天 (0 ~ 6)。
console.log(now.getHours()); //返回 Date 对象的小时 (0 ~ 23)。
console.log(now.getMinutes()); //返回 Date 对象的分钟 (0 ~ 59)。
console.log(now.getSeconds()); //返回 Date 对象的秒数 (0 ~ 59)。
console.log(now.getMilliseconds()); //返回 Date 对象的毫秒(0 ~ 999)。
console.log(now.getTime()); //返回 1970 年 1 月 1 日至今的毫秒数。
小程序API
wx
具体文档:https://developers.weixin.qq.com/miniprogram/dev/api/
1、了解网络状态
wx.getNetworkType()接口可以用于获取小程序所在的手机当前的网络状态是WiFi、3G、4G、5G?这样的场景经常会有,比如播放视频音乐或玩一些游戏以及流量大图片时,如果网络处于非WiFi状态时就会有流量注意的提醒。
大家可以切换一下开发者工具的模拟器的网络,然后多次在控制台console输入以下代码查看有什么不同:
wx.getNetworkType({
success(res) {
console.log(res)
}
});
2、 获取设备信息
wx.getSystemInfo()可以用于获取用户手机的微信版本、操作系统及版本、屏幕分辨率、设备的型号与品牌、基础库版本等信息。
wx.getSystemInfo({
success (res) {
console.log("设备的所有信息",res)
console.log(res.model)
console.log(res.pixelRatio)
console.log(res.windowWidth)
console.log(res.windowHeight)
console.log(res.language)
console.log(res.version)
console.log(res.platform)
}
})
3、页面链接跳转
除了可以获取到用户、设备、网络等的信息,使用控制台来调用对象的方法也可以执行一些动作,比如页面跳转wx.navigateTo()
的接口。前面我们在home页面的下面建了一个imgshow的二级页面,我们在控制台Console里输入:
wx.navigateTo({
url: '/pages/home/imgshow/imgshow'
})
还可以在控制台直接调用wx.navigateBack()返回页面的上一层,在控制台里输入
wx.navigateBack({
delta: 1
})
4、显示消息提示框
wx.showToast()接口可以来显示消息提示框,比如操作成功、操作失败等都需要给用户一个反馈,这个时候就需要调用这个接口,我们在console控制台打印一下,看看模拟器小程序的效果:
wx.showToast({
title: '弹出成功',
icon: 'success',
duration: 1000
})
5、设置当前页面的标题
wx.setNavigationBarTitle()可以用来设置当前页面的标题。在我们实际生活中,会经常看到资讯、商品、博客有无数个新闻、商品、文章,打开不同的页面都会显示对应的标题,这个当然不会像静态页面一样写死,而都是用JavaScript来控制的,而小程序就会调用这个接口。
wx.setNavigationBarTitle({
title: '控制台更新的标题'
})
6、打开文件选择器上传文件
调用wx.chooseImage()打开图片上传选择器,其实就已经可以将电脑上面的图片上传到小程序端,只是由于一个接口只干一件事情,上传的图片路径需要我们用其他函数来处理才行。
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success (res) {
const tempFilePaths = res.tempFilePaths
}
})
7、控制台实战云开发API
在前面我们已经说过wx是小程序的全局对象,而在这个对象里的cloud属性也是一个对象,这个是用于承载云开发在小程序端的相关能力的API,我们仍然可以通过console控制台了解相关信息。
我们可以在控制台依次打印如下内容,至于具体的含义,大家可以通过以后章节的学习来了解:
wx.cloud
wx.cloud.database()
wx.cloud.database().command
wx.cloud.database().command.aggregate
小程序的这些API有的是返回数据(如网络状态、设备信息、用户信息等),有的是在小程序上出现交互(消息提示框、模态框、操作菜单、标题的设置),还有的需要传入一些参数等等。这一部分主要是让大家明白控制台Console的强大之处,以及通过控制台实战的方法对小程序API的运行机制有一个初步的了解。
3.2.3 API的可用性判断与权限
1、API的可用性
wx.canIUse('console.log')
wx.canIUse('CameraContext.onCameraFrame')
wx.canIUse('CameraFrameListener.start')
wx.canIUse('Image.src')
// wx接口参数、回调或者返回值
wx.canIUse('openBluetoothAdapter')
wx.canIUse('getSystemInfoSync.return.safeArea.left')
wx.canIUse('getSystemInfo.success.screenWidth')
wx.canIUse('showToast.object.image')
wx.canIUse('onCompassChange.callback.direction')
wx.canIUse('request.object.method.GET')
// 组件的属性
wx.canIUse('live-player')
wx.canIUse('text.selectable')
wx.canIUse('button.open-type.contact')
2、提前发起权限设置
部分接口需要经过用户授权同意才能调用。我们把这些接口按使用范围分成多个scope ,用户选择对 scope 来进行授权,当授权给一个 scope 之后,其对应的所有接口都可以直接使用。
使用wx.authorize可以提前向用户发起授权请求,调用后会立刻弹窗询问用户是否同意授权小程序使用某项权限,如果用户之前已经同意授权,则不会出现弹窗,直接返回成功,这些权限有scope.userInfo是否允许获取用户信息,scope.record是否允许录音、scope.writePhotosAlbum是否允许保存到相册等等
wx.authorize({
scope: 'scope.record',
success () {
// 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
wx.startRecord()
}
})
3、获取用户信息
wx.getUserInfo()接口可以用于获取微信用户的一些基本信息,比如头像、昵称、城市等等,常用与小程序的用户基础信息与社交场景。不过调用这个接口的前提是先要取得用户的授权,而且还不能通过wx.authorize({scope: “scope.userInfo”})的方式(因为不会弹出授权窗口),只能通过button的 open-type=“getUserInfo”,方法如下:
新建一个页面,比如user,然后再在user.wxml里输入以下代码,点击按钮之后就会弹出授权弹窗,如果已经授权了,就不会有弹窗了:
<button open-type="getUserInfo">弹出授权弹窗</button>
当授权完成之后然后我们可以在控制台console里输入以下代码,看得到什么信息,点击开发者工具菜单里的”清缓存“的”全部清除“之后再输入看看什么效果:
wx.getUserInfo({
success(res) {
console.log(res);
}
});
命名规范
JavaScript的项目名、函数名、变量等都应该遵循简洁、语义化的原则。函数名推荐使用驼峰法来命名(camelCase),比如scrollToTop、pageScrollTo,也就是由小写字母开始,后续每个单词首字母都大写,长得跟骆驼🐫的驼峰似的。
3.3.2 消息提示框Toast
消息提示框是移动端App、H5(WebApp)、小程序经常会使用到的一个交互界面。在tapevent.wxml输入代码:
<button type="primary" bindtap="toastTap">点击弹出消息对话框</button>
在js里输入以下代码:
toastTap() {
wx.showToast({
title: '购买成功',
icon: 'success',
duration: 2000
})
},
云函数的初始化
在云函数中调用其他API前,同小程序端一样,也需要执行一次初始化方法,首先使用require引入wx-server-sdk依赖,然后在初始化cloud.init()
中指定云开发的环境,方法如下:
//方法一,直接使用字符串envId指定环境
const cloud = require('wx-server-sdk')
cloud.init({
env: 'xly-xrlur' //换成你的云函数envId
})
//方法二,使用cloud.DYNAMIC_CURRENT_ENV常量,也就是使用云函数当前所在环境
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV //注意它不是字符串,不要加引号
})
- 尽管直接使用
cloud.init()
不指定环境在某些特定情况下仍然可以使用,比如你的云函数就部署在你创建的第一个云开发环境里,但是非常不推荐这种写法; cloud.DYNAMIC_CURRENT_ENV
标志的是云函数当前所在的环境,也就是你将云函数部署到哪个环境,它就是指哪个环境;- 我们可以在云开发环境A直接调用同一个账号下云开发环境B的资源,只需要在云环境初始化时指定B的envId即可,在开发时切换生产环境、测试环境非常方便;
- 我们还可以在云函数里分别调用不同云开发环境里的云存储、云数据库、云函数等的资源,比如
env:{"database":"xly-xrlur","storage":"xly-1o7da","functions":"xly-oau0j"};
- 如果调用云函数时,提示
找不到对应的FunctionName
,可能是你的小程序账号之下有多个云开发环境,而你在云函数初始化时没有指定envId。
开发者工具右键操作说明
1、同步云函数列表
当我们右键云函数根目录cloudfunctions时,会有一个同步云函数列表的选项,它可以拉取当前云开发环境所有云函数的列表,右键指定的云函数选择下载就可以将云端的代码给下载到本地电脑。也就是说,上传到云开发环境的云函数以及代码都会存储在云端,你可以在其他设备上通过这种方式进行同步,除非你在云开发控制台将这个云函数给删掉了。
当我们在开发者工具本地或使用云开发控制台将云函数删掉之后,建议先同步云函数列表,不然在重新上传部署同名的云函数的时会出现一些报错。
2、新建Node.js云函数
在前面我们也已经介绍过右键云函数根目录cloudfunctions,选择新建Node.js云函数可以直接在云端新建一个云函数,同时会自动在云端给新建的云函数安装好wx-server-sdk依赖,并将该云函数在云端部署的情况反馈到开发者工具,即开发者工具本地的云函数目录图标会变色(注意区分同步和没有同步的云函数目录图标的不同)。
弄明白了这个机制以及前面的上传并部署所有文件、上传并部署:云端安装依赖(不上传node_modules),你才能理清什么时候需要我们在本地下载依赖,什么时候只需要更新代码本身就可以。
3、增量上传
如果你在云端已经部署好了一个云函数所需要的依赖,那在编写云函数的核心文件index.js、权限配置文件或云函数其他目录文件时就不需要再上传并部署所有文件或上传并部署:云端安装依赖(不上传node_modules),只需要右键云函数目录,选择云函数增量上传:更新文件,这种方式只更新我们修改过的文件,更快捷。