在开发者工具中打开源代码文件夹miniprogram里的app.js,找到如下代码:
1 2 3 4 5 |
wx.cloud.init({ // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 env: 'my-env-id', traceUser: true, }) |
在 env: 'my-env-id'处改成你的环境ID,如 env: 'xly-snoop'
NodeJS是在服务端运行JavaScript的运行环境,云开发所使用的服务端环境就是NodeJS。npm是Node包管理器,通过npm,我们可以非常方便的安装云开发所需要的依赖包。
npm(Node Package Manager)是前端开发必不可少的包(模块)管理器,它的主要功能就是来管理包package,包括安装、卸载、更新、查看、搜索、发布等,其他编程语言也有类似的包管理器,比如Python的pip,PHP的composer、Java的maven。我们可以把包管理器看成是windows的软件管理中心或手机的应用中心,只是它们用的是可视化界面,包管理器用的是命令行Command Line。
下载地址:Nodejs下载地址
npm install这条命令会下载云函数目录下的配置文件package.json里的dependencies,它表示的是当前云函数需要依赖的模块,然后利用这些依赖进行本地调试。package.json在哪里,就在哪里执行npm install,没有package.json,没有dependencies,就没法下载啊。
如果显示“npm不是内部或外部命令”,你需要关闭微信开发者工具启动的终端,而是重新打开一个终端窗口,并在里面输入 cd /D 你的云函数目录进入云函数目录,比如 cd /D C:\download\tcb-project\cloudfunctions\login进入login的云函数目录,然后再来执行npm install命令。
解决办法:在用户环境变量path中添加nodejs的路径,然后重启电脑即可。
执行npm install命令下载的依赖模块会放在node_modules文件夹里,可以在执行了npm install命令之后,在电脑里打开查看一下node_modules文件夹里下载了哪些模块。
既然npm install是下载模块,那它是从哪里下载的呢?就以wx-server-sdk为例,我们可以在以下链接看到wx-server-sdk的情况:
1 |
https://www.npmjs.com/package/wx-server-sdk |
为什么package.json里依赖的是一个模块wx-server-sdk,但是node_modules文件夹里却下载了那么多模块?这是因为wx-server-sdk也依赖三个包tcb-admin-node、protobuf、jstslib,而这三个包又会依赖其他包,子子孙孙的,于是就有了很多模块。
为什么调用云函数login返回的res的result对象里会包含event对象、appid、userInfo这些结果?这就取决于云函数是怎么写的了。使用开发者工具打开login云函数(在cloudfuntions文件夹里)的index.js。
1 |
exports.main = (event, context) => {} |
这是一个箭头函数的写法,其中event和context ['kɒntekst]环境是参数。我们将两个打印日志修改为以下代码,相当于备注一下到底打印到哪里去了:
1 2 |
console.log('服务端打印的event',event) console.log('服务端打印的context',context) |
保存之后,右键点击index.js文件,选择云函数增量上传:(更新文件),更新login云函数,我们再来点击“点击获取openid”按钮,打印的结果在哪里呢?在云开发控制台的云函数日志里面(注意不是开发者工具的控制台)。打开云开发控制台–云函数–日志,按函数名筛选,选择login云函数,可以看到云函数被调用的日志记录,我们可以在日志里发现:
getWXContext()API是云开发服务端的工具类API,会返回小程序用户的openid、小程序appid、小程序用户的unionid等。说这么多不如直接打印,在下面添加一行打印信息:
1 2 |
const wxContext = cloud.getWXContext() console.log('getWXContext返回的结果',wxContext) |
保存之后,右键点击index.js文件,选择云函数增量上传:(更新文件),更新login云函数,我们再来点击“点击获取openid”按钮,然后去云开发控制台的云函数日志里看到底返回了什么结果。
技术文档:getWXContext()
注意小程序用户 unionid只有在开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用才能获得。
JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,因为对象如果直接渲染到页面是会显示 [object Object]的。
比如{sum: 3}变成{"sum":3}
把miniprogram文件夹下的pages、images、components、style文件夹里的文件清空,以及app.json的pages配置项里的页面删除,把app.wxss里的样式代码都删掉。
1.新建一个miniprogram和cloudfunctions文件夹,把小程序除了project.config.json以外的其他文件都各自放进去。
2.再在project.config.json添加miniprogramRoot配置:
1 2 |
"cloudfunctionRoot": "cloudfunctions/", "miniprogramRoot":"miniprogram/", |
3.同步云函数列表,可以把所有云端的云函数列表都列举出来(这只是列举了列表,还是空的)
4.而要修改云函数里面的内容,我们可以右键点击其中的一个云函数目录选择下载云函数即可。
5.除此之外,我们需要小程序的app.js的生命周期函数onLaunch里使用wx.cloud.init()来初始化云开发能力:
1 2 3 4 5 6 7 8 9 10 |
onLaunch: function () { if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力') } else { wx.cloud.init({ env: '你的环境ID', traceUser: true, }) } }, |
云开发能力全局只需要初始化一次即可,这里的traceUser属性设置为true,会将用户访问记录到用户管理中,在云开发控制台的运营分析—用户访问里可以看到访问记录。
wx.cloud的方法:
1 2 3 4 5 6 7 8 |
CloudID: ƒ () //用于云调用获取开放数据 callFunction: ƒ () //调用云函数 database: ƒ () //获取数据库的引用 deleteFile: ƒ () //从云存储空间删除文件 downloadFile: ƒ () //从云存储空间下载文件 getTempFileURL: ƒ () //用云文件 ID 换取真实链接 init: ƒ () //初始化云开发能力 uploadFile: ƒ () //上传文件至云存储空间 |
1.新建云函数,选择在终端中打开,使用npm install来安装依赖。
2.本地调试:右键点击云函数目录,选择本地调试,请求方式有模拟器触发和手动触发两种,模拟器触发的意思是模拟用户操作界面,然后触发相应的事件处理函数,函数再调用云函数(比较繁琐费时),还有就是手动触发,可以直接自定义传参(注意传递的是JSON格式,最后一个参数结尾不能有逗号,),然后点击调用。
3.云端测试:在控制台点击云端测试,修改参数,调试即可。
小程序默认可以创建两个环境,一般一个用于生产环境,一个用于测试环境。
小程序的初始化是在app.js文件里使用wx.cloud.init来初始化,如下:
1 2 3 4 |
wx.cloud.init({ env: 'my-env-id', //可以填写生产环境或者测试环境的环境ID traceUser: true, }) |
这里的 env 只会决定小程序端API调用的云环境(如云函数、云存储、数据库,毕竟有两个环境里都有),并不会决定云函数中的 API 调用的环境。在开发者工具的控制台,也会打印默认环境:
云函数中的API调用的环境也可以使用初始化来设置。
1 2 3 |
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) |
cloud.DYNAMIC_CURRENT_ENV设置 API 默认环境等于当前所在环境。建议所有的云函数都使用以上方式来初始化,也就是配置env的值为cloud.DYNAMIC_CURRENT_ENV或使用你的环境ID,不要为空。
wx-server-sdk中不再兼容success、fail、complete回调,只会返回Promise。在云函数中也经常会需要处理一些异步操作,在异步操作完成后再返回结果给到调用方,我们可以通过在云函数中返回一个 Promise 的方法来实现。Promise表示异步操作返回的结果。在新建的云函数里会看到下面这样的一个语句(有 async):
1 2 |
exports.main = async (event, context) => { } |
async表示函数里有异步操作,async函数的返回值是一个 Promise 对象。在后面还会遇到 await,表示紧跟在它后面的表达式需要等待结果;以及promise对象的then()方法(有点类似于success回调函数),和catch()方法(有点类似于fail回调函数),这些我们以后会经常遇到,先理解不了也没有关系,大家在书写时推荐云函数使用上面的写法就对了。
方法一:先判断用户是否授权然后再调用wx.getUserInfo
方法二: 通过button的开放能力,然后onGotUserInfo的参数中可以获得用户信息。
使用open-type=”getUserInfo” 来获取用户信息的作用和 wx.getUserInfo API基本效果是一样的,区别在于wx.getUserInfo 这种方式最好是在用户允许获取公开信息(也就是res.authSetting[‘scope.userInfo’]的值为true)之后再调用,如果用户拒绝了授权就不会再有弹窗(除非用户删掉了你的小程序再使用),调用就会失败,而使用组件的方式是用户主动点击,用户即使拒绝了,再点击仍会弹出授权弹窗。所以推荐先使用组件来获取用户授权,然后再来使用wx.getUserInfo来获取用户信息。
推荐方法:用户点击个人中心,然后如果没登录的话,跳到一个大的页面,这个页面只有logo和微信授权的按钮,点击button后弹出微信授权确认框,接受就ok,不接受的话就弹出个温馨提示框,说不授权就不好用了,然后下面放个继续授权的button。(可以去研究一下其他小程序)
默认返回的头像链接大小为132*132(UserInfo用户头像说明),如果把avatarUrl链接后面的132修改为0就能获取到640*640大小的头像了:
先将字符串avatarUrl根据‘/'分成一个数组,然后把数组最后一个变成0,最后再拼接起来。
1 2 3 4 5 6 7 8 9 |
getUserInfomation: function (event) { let { avatarUrl, city, nickName}= event.detail.userInfo avatarUrl = avatarUrl.split("/") avatarUrl[avatarUrl.length - 1] = 0; avatarUrl = avatarUrl.join('/'); this.setData({ avatarUrl,city, nickName }) }, |
split
技术文档:wx.cloud.uploadFile
把本地资源也就是临时文件里的文件上传到云存储里。
坑:chooseImg返回的临时路径是数组形式的,所以要加这个const filePath = res.tempFilePaths[0]
正则匹配文件的后缀(选择好图片以后,临时路径是一段长长的字符,不是原来的文件名)
1 |
1 2 |
const filepath="http://tmp/wx7124afdb64d578f5.o6zAJs291xB-a5G1FlXwylqTqNQ4.esN9ygu5Hmyfccd41d052e20322e6f3469de87f662a0.png" const cloudPath = 'my-image' + filePath.match(/\.[^.]+?$/)[0] |
给文件命不同名字的方法:
1 |
const cloudPath = `${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0] |
给文件名加上时间戳和一个随机数,时间戳是以毫秒计算,而随机数是以1000内的正整数,除非1秒钟(1秒=1000毫秒)上传几十万张照片,不然文件名是不会重复的。
云存储的二级目录
在存储里我们都是把所有的图片放在根目录下,没有二级目录,那我们能不能建一个二级目录呢?当然是可以的,我们可以在cloudPath的前面加一个文件路径就可以了,比如:
1 |
const cloudPath = `cloudbase/${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0] |
json格式的数据库,每条记录之间用\n来分隔开
导入时会有冲突模式选择,推荐大家使用upsert:
导入后,发现数据库自动给每一条数据(记录)都加了唯一的标识_id。
在小程序端调用数据库的方式很简单,我们可以把下面的代码写到一个事件处理函数里,然后点击组件触发事件处理函数来调用;也可以直接写到页面的生命周期函数里面;还可以把它写到app.js小程序的生命周期函数里面。
使用开发者工具,将下面的代码写到login.js的onLoad函数里面,我们
1 2 3 4 5 6 7 8 9 |
const db = wx.cloud.database() db.collection('zhihu_daily') .get() .then(res => { console.log(res.data) }) .catch(err => { console.error(err) }) |
编译之后,就能在控制台看到调用的20条数据库记录了(如果没有指定 limit,则默认最多取 20 条记录)。
云函数调用数据库
使用云函数也可以调用数据库,使用开发者工具右键点击云函数根目录也就是cloudfunctions文件夹,选择新建Node.js云函数,云函数的名称命名为zhihu_daily,然后打开index.js,输入以下代码:
1 2 3 4 5 6 7 8 9 |
const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db = cloud.database() exports.main = async (event, context) => { return await db.collection('zhihu_daily') .get() } |
然后右键点击index.js,选择云函数增量上传:更新文件,我们既可以使用云函数的本地调试(要本地调试需要使用npm install安装wx-server-sdk依赖),也可以使用云端测试来了解云函数调用数据库的情况。
openid与数据库
在云开发控制台的数据库标签里,每条记录除了有_id字段以外,还有一个_openid字段用来标志每条记录的创建者(也就是小程序的用户)。但是在我们使用管理端(控制台和云函数)中创建的数据比如我们之前导入的zhihu_daily,就不会有 _openid 字段,因为这些记录属于管理员(不是用户)创建的记录。