- 5行代码获取小程序用户手机号
最近有很多同学有获取小程序用户手机号的需求。其实云开发出现之前我们获取小程序用户的手机号特别繁琐。自从有了云开发,我们获取用户手机号变得非常简单。只需要5行代码即可。 老规矩,我们先来看下效果图 [图片] 再来看下核心的代码,其实只有下面这一些。 [图片] 甚至可以说核心代码只有上图红色框里的两行。是的,你没听错,只靠这2行代码,就可以轻松的获取用户小程序绑定的手机号。 下面我们就来具体讲解吧。 注意:只有企业小程序才可以获取用户手机号,个人小程序没有办法获取的。 一,首先要用到button组件的开发能力 [图片] 编写wxml文件,代码很简单 [图片] 可以看到我们的button按钮,使用了open-type。 再来看下我们对应的js方法。这样我们点击按钮时,就会弹出授权弹窗。如下图 [图片] 不管用户点击拒绝还是允许,我们都能拿到对应的回调。再用户点击了允许以后,就可以获取到以下数据。 [图片] 大家看到我们获取的数据里有一个cloudID,其实这个值很有用的。 二,开发数据检验与解密 1,首先我们看下官方提供的获取手机号的文档。 [图片] 看官方文档,可以知道,我们这里涉及到一个数据的检验与解密问题 2,开发数据检验与解密 [图片] 这里我们要使用的就是方式二,使用云函数来实现解密,然后拿到用户的手机号。 三,云函数的编写 [图片] 通过上图可以看到,我们编写的云函数很简单。这里主要用的就是cloud.getOpenData这个功能。而这个功能需要的参数就是我们上面第一步获取的cloudID [图片] 这样我们调用云函数的时候,只需要把对应的cloudID传进来即可。 [图片] 看下我们的cloudID的作用,再来看下我们通过button的open-type获取的cloudID [图片] 可以看出,我们的cloudID和encryptedData一样,是一串加密数据。我们要通过云函数获取手机号,需要的就是这串加密字段。 四,上传cloudID获取手机号。 上面第三步云函数编写好以后,我们就可以来调用了。调用之前一定要记得部署下云函数,一定要记得部署下云函数。。。。 [图片] 上图就是我们的云函数的调用。如果你对云开发和云函数还不了解,建议你去看下我之前写的云开发相关的文章,获取看下我录的《微信小程序云开发云函数入门》 这时候点击按钮,我们就可以获取到了我们所需要的手机号了 [图片] 到这里我们就可以轻松的通过云开发获取用户的手机号了,比起传统的后台开发来获取,是不是简单了很多。 今天就讲到这里了,后面我还会写更多小程序相关的技术文章出来,请持续关注。
2019-12-16 - 还在为看英语的stackoverflow,Github,文档发愁?我把让我托福116分的秘密武器做成了小程序。
[图片] 写程序最不可缺少的语言是什么呢? 英语。 stackoverflow上面的提问和回答,Github上面的讨论,最新的文档往往都是英语的。对于我们这些英语不是母语的人来说,如果都可以顺畅地直接看英语版也就更容易走在大部分人前面。 学习英语没有速成的办法,需要不断地积累,让质变引起量变。而编程也是一个需要不断学习新技术的领域。在繁忙的本职工作学习之外,兼顾不那么有趣的英语学习,比如背单词,也就显得比较艰难。 就我自己的经验来说,文章听写是一个全面提升英语的方法。我高中坚持过一个学期听写,再也没为听力烦恼过。后来每次有比较重要的英语考试(比如托福),我都会集中练习一段时间,保持良好的状态。因为会潜移默化地记住常用句型,会有针对性地背单词,也会跟读模仿语音,所以坚持一段时间下来能感觉到听说读写都有提高。 [图片] 如果可以的话真想每天都听写一段。可惜之前纸质听写对我来说问题不少。 先要在浩如烟海的材料中找到长度合适,难度合适,有完整音频和原文的新闻 听写时手忙脚乱,播放,写两笔,暂停,拖动时间,播放循环,反复几十次 写完后校对得眼花缭乱,很容易就看漏看错行 写完后想要电子化保存方便之后搜索复习很麻烦 不能轻松地和小伙伴互相激励,一个人比较孤独也就更难坚持下去 于是我写了一个让听写变得简单的微信小程序。通勤,等待之类的时间可以利用起来。。 [图片] 五大特点: 个性化重复次数 专有名词提示 (用spacy的NER做的) 自动校对结果 将生词加入单词本 和群内小伙伴PK https://oliwang.github.io/DailyDictation/ 刚上线,还有这样那样的一些问题。希望大家能多多试用多多反馈,帮我让这个小程序更完善~ 完成小程序的过程中遇到了一些坑,积累了一些经验,接下来会整理一下发出来。
2019-12-03 - 【小程序学习记录】-text组件
前言 上一篇文章讲的是view组件,写的很简单我感觉应该还有一些东西没有说到,但是还是得到了一些小伙伴的支持(大神勿喷😝),我觉得很有动力,今天继续更新,聊聊 <text> 和 <image>组件。 <text>组件作用 <text>是一个文本组件,也就是说,我们在小程序里面要展示的一些文字可以用<text>包起来,然后小程序框架就可以渲染出来了,(ps:其实不包也可以渲染出来)包起来之后就可以通过wxss来改变文本的样式,搭配出漂亮的UI啦 使用 <text>组件默认是在一行显示的,如果按照HTML的意思来说的话:<text>其实是一个行内元素,而且<text>的宽高都是由里面的内容来决定的,也就是说里面没有文字的话,你的界面就不会显示<text>,下面代码大家可以更清晰的看到 wxml代码 [代码]<text class='temp'></text> <text class='textOne'>你好哇!</text> <text class='textTwo'>我还可以!</text> <text class='textThree'> 开发者可以使用云开发开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力云开发为开发者提供完整的云端支持,弱化后端和运维概念,无需搭互兼容,并不互斥。 </text> [代码] wxss代码 [代码].temp{ background-color: orange; } .textOne{ background-color: red; } .textTwo{ width: 400rpx; /* 设置宽高进行对比 */ height: 400rpx; background-color: blue; } .textThree{ background-color: orange; } [代码] 运行效果图 [图片] 通过上面可以看到<text>普通情况下指定宽高是没有用的,那要怎么办呢?在这里就需要wxss的display属性来控制它是行内还是块级元素了,在对应的wxss样式里面加上 display: block ; 就可以使<text>变身,现在它既可以设置宽高,也可以加外边距等等,还是通过代码看看 wxml代码 [代码]<text class='textOne'>你好哇!</text> <text class='textTwo'>我还可以!</text> [代码] wxss代码 [代码].textOne{ background-color: red; } .textTwo{ display: block; /*注意这里 */ width: 400rpx; height: 400rpx; background-color: blue; } [代码] 运行效果图 [图片] text属性 微信小程序的官方文档提供了三个属性selectable、space、decode。我个人觉得用的最多的应该就是selectable了,它的值是布尔类型,默认为false,它的作用就是设置这段文字是不是可以长按复制 wxml代码 [代码]<text class='textOne' selectable='true'>你好哇!</text> <text class='textTwo'>我还可以!</text> [代码] 真机运行图 [图片] 结语 🆗!这一篇<text>也就差不多了,小插曲:不知道为什么编辑的时候图片总是显示不出来,然后就截图保存到本地在插入了,但是图片的清晰度很感人,大家将就的看一下吧。。呜呜呜,后期我看能不能改一改。最后还是谢谢大家的支持,希望可以帮到你。期待下一篇<image>组件😍 ps:图片已经改了,但是真机运行图那个没办法了…反正就是可以复制,在模拟器上不好显示,所以。。。
2019-06-03 - 使用css样式控制英文单词换行,以英文单词进行断词
期待的效果: [图片] 使用如下样式做到换行: [代码]word-wrap:[代码][代码]break[代码][代码]-word;[代码][代码]word-[代码][代码]break[代码][代码]:keep-all;[代码][代码]width:400rpx;[代码] 但是不知道怎么回事一直无法在开发工具和手机上达到换行的效果,最后通过对比AppData中的字符串存在问题。 最后使用replace的方法做到空格替换空格 replace(/\s/g, ' '),所以怀疑小程序中的字符串经过了处理导致样式无法生效。 目前为找到真正的问题,只是解决了这个不英文单词断词的bug
2019-06-12 - 请问setdata 里面为什么总是有一个红线说Unexpected token, expected?
[图片]已解决 谢谢各位
2020-02-09 - 小程序tabBar层级z-index问题,自定义弹窗遮挡不住
[图片] 示例截图!上面遮罩遮住的是自己写的自定义底部tabBar导航,下面是小程序官方tabBar组件。自定义的弹窗和遮罩不能将官方tabBar组件盖住,导致点击官方tabBar组件还能切换页面。@官方人员!能否给方便开发者自定义官方tabBar组件层级?能否方便开发者自定义弹窗遮罩全屏覆盖包括官方tabBar?会不会考虑以后的版本有这样的优化?
2018-11-12 - 巧用小程序·云开发实现邮件发送功能丨实战
先看效果图: [图片] 通过上面的日志,可以看出我们是158开头的邮箱给250开头的邮箱发送邮件,下面是成功接收到的邮件。 [图片] 准备工作 1、qq邮箱一个 2、开通你的qq邮箱的授权码(会具体讲解) 3、注册自己的小程序(因为只有注册的小程序才能使用云开发) 4、电脑要安装node(会用到npm命令行) 5、编写小程序代码 一、准备一个QQ邮箱,并启动SMTP服务 进入qq邮箱以后: 1、点击设置,然后点击账户 [图片] 2、开启POP3/SMTP服务,获取授权码 [图片] 具体操作可以看官方文档,官方文档有具体的讲解,这里我就不多说了。 官方文档:https://dwz.cn/SJCibDEi 我们获取的授权码如下图。请保存好这个授权码,我们后面发送邮件时会用到。 [图片] 二、注册小程序获取appid,创建一个小程序 关于小程序的注册和创建就不在此赘述,有需要的同学可以参照官方文档: https://dwz.cn/HpcWynVz 下图是我们创建好的小程序。 [图片] 代码很简单,就只有一个页面,页面上就一个按钮,我们点击这个按钮的时候实现邮件的发送。 三、初始化云开发,创建发送邮件的云函数 关于云开发初始化我这里也不在做具体讲解了,感兴趣或者不会的同学,可以去翻看腾讯云云开发公众号内菜单【技术交流-视频教程】中的教学视频。 初始化云开发环境时,需要注意以下几点: 1、一定要是注册的小程序有appid才可以使用云开发 2、一定要在app.js里初始化云开发环境id [图片] 3、在project.config.json里配置云函数目录,如下图箭头所示 [图片] 四、创建云函数 sendEmail 1、右键cloud文件,新建云函数: [图片] 这个函数名你可以随便起,只要是英文,并且调用的时候记得不要写错就行。我这里就用sendEmail。 2、创建完以后,右键sendEmail选择在终端里打开: [图片] 这里我们需要用npm安装一个依赖包 nodemailer 使用npm安装依赖包需要用到node,至于node的安装大家自行百度,一大堆的讲解文章。 3、在打开的命令行窗口里输入 npm install nodemailer: [图片] 4、等待 nodemailer类库的安装 [图片] 5、安装成功时,您能看到nodemailer的版本号 [图片] 五、编写发送邮件的核心代码 这里一定要注意填写你自己的qq邮箱的授权码: [图片] 代码里都有注释,直接把代码给大家贴出来。 [代码]const cloud = require('wx-server-sdk') cloud.init() //引入发送邮件的类库 var nodemailer = require('nodemailer') // 创建一个SMTP客户端配置 var config = { host: 'smtp.qq.com', //网易163邮箱 smtp.163.com port: 465, //网易邮箱端口 25 auth: { user: '1587072557@qq.com', //邮箱账号 pass: '这里要填你自己的授权码' //邮箱的授权码 } }; // 创建一个SMTP客户端对象 var transporter = nodemailer.createTransport(config); // 云函数入口函数 exports.main = async(event, context) => { // 创建一个邮件对象 var mail = { // 发件人 from: '来自小石头 <1587072557@qq.com>', // 主题 subject: '来自小石头的问候', // 收件人 to: '2501902696@qq.com', // 邮件内容,text或者html格式 text: '你好啊,编程小石头' //可以是链接,也可以是验证码 }; let res = await transporter.sendMail(mail); return res; } [代码] 六、上传云函数 编写完代码后,一定要记得上传云函数。 [图片] 七、调用云函数发送邮件 我们在index.wxml文件里写一个按钮,当点击这个按钮时就发送邮件。 [图片] 然后在index.js里调用我们的sendEmail云函数。 [图片] 八、点击发送邮件,查看效果 可以看到我们的控制台,打印里发送成功的日志信息: [图片] 然后到我们的邮箱里,可以看到新收到的邮件。 [图片] 到这里我们就完整的实现了微信小程序云开发使用云函数发送邮件的功能了。是不是很简单呢? 源码地址: https://github.com/TencentCloudBase/Good-practice-tutorial-recommended 如果你有关于使用云开发CloudBase相关的技术故事/技术实战经验想要跟大家分享,欢迎留言联系我们哦~比心! [图片]
2019-08-22 - 小程序云开发模糊查询,实现数据库多字段的模糊搜索
最近做小程序云开发时,用到了一个数据库的模糊搜索功能,并且是要求多字段的模糊搜索。 网上也有一大堆资源,但是都是单个字段的搜索。如下图 [图片] 上图只可以实现time字段的模糊搜索。但是我们如果相对数据表里的多个字段做模糊查询呢?该怎么办呢。 多字段模糊搜索 一,如我们的数据表里有以下数据,我们想同时模糊查询name和address字段 [图片] [图片] 如我们搜索“周杰”可以看到我们查询到下面两条数据。 [图片] 二,如我们搜索“编程”,可以搜索到下面数据 [图片] 可以看到我们搜索到的两条数据,一个是name字段为 编程小石头, 一个是address字段里包含“编程“ 字样。 下面把代码贴给大家 [代码] let key = "编程小石头"; console.log("查询的内容", key) const db = wx.cloud.database(); const _ = db.command db.collection('qcl').where(_.or([{ name: db.RegExp({ regexp: '.*' + key, options: 'i', }) }, { address: db.RegExp({ regexp: '.*' + key, options: 'i', }) } ])).get({ success: res => { console.log(res) }, fail: err => { console.log(err) } }) [代码] key就是我们要搜索的关键字。主要是用到了数据库查询的where,or,get方法。 代码都给大家贴出来来,如果对云开发和云数据库还不是很了解的同学可以去翻看下我以前写的文章。
2019-11-06 - setData使用[...]进行动态key赋值,wxml如何获取?
原data { "arr":[0,1,2], } js 处理业务流程: var arr =[0,1,2]; for(var i = 0;i<arr.length;i++){ var key = "aaaa" + i; this.setData({ [key] : "aaaaa", }); } 输出data结果是 { "arr":[0,1,2], "aaaa0":"aaaaaa", "aaaa1":"aaaaaa", "aaaa2":"aaaaaa", } 请问wxml如何循环arr调用 aaaa0/aaaa1/aaaa2?
2019-11-23 - 微信小程序Page间数据传递解决方案分析
内容概要 利用微信小程序的路由堆栈信息解决小程序内Page间的数据(或事件)传递的问题。通过对各种方案的对比、分析、总结,得出我们的升华版解决方案,满足你的不满足。 场景再现 工作中我们经常会遇到B页面需要A页面内的部分或全部数据;C页面内的一个函数执行完之后需要改变B页面内的显示样式;也或者是A和B两个页面用到了同样的网络数据,在其中一个页面做出修改后另一个页面也要随之改变以保证回传服务器时数据的准确性,等等诸如此类的页面间数据传递的问题。 现有方案梳理 当然针对上面场景中各种问题我们可以有很多种的解决方案。例如利用微信API中reLaunch、redirectTo、navigateTo 函数的url路径携带参数到目标页面;利用EventChannel信道实现打开页面与被打开页面通信;利用全局文件共享数据;利用路由堆栈获取目标页面实例等等,我目前用过的方案就以上四种,如果你用过其他方案也可以提出来我们一起讨论学习。接下来我们就针对以上四种方案进行一个简略的分析。 方案一:reLaunch、redirectTo、navigateTo 函数url路径携带参数到目标页面 这种方案大家应该都用过,在页面跳转过程中传递一些简单的数据还是十分方便的,但是它的缺点也很明显,在五个路由函数中只有三个可以在跳转路径上携带参数,而且参数不可以是对象类型,在遇到携带"?"等特殊字符的参数还需要进行转码操作。对于跨多个页面的数据传递比较繁琐。归纳如下: 优点:操作简单方便。 缺点:单项传递;复杂数据传递局限性较大;跨多页面数据传递繁琐;只能在reLaunch、redirectTo、navigateTo 三个函数中使用。 适用情况:页面间简单数据的单项传递。 方案二:EventChannel信道实现打开页面与被打开页面通信 从基础库2.7.3开始支持EventChannel。开发者可以通过navigateTo路由函数在页面跳转切换过程中自定义两个页面的数据交互函数。至于EventChannel自定义规则可参考微信API中的 navigateTo 函数。该方案解决了方案一中的复杂数据传递的局限性。可是它仅限于navigateTo函数中使用,并且在跨多页面传递时操作起来复杂性仍然很高。归纳如下: 优点:使用灵活性较高;可传递较复杂数据;可双向传递; 缺点:跨多页面数据传递繁琐;只能在navigateTo一个函数中使用。 适用情况:由navigateTo控制路由的两个页面间数据传递。 方案三:全局文件共享数据 全局共享数据无非就是定义一份谁都可以使用和修改的数据。这个方案很简单,而且很轻松的解决了方案一和方案二中的跨多个页面的数据传递问题。可是数据处理的及时性却大打折扣,只能期待各个页面自己触发自身的事件。归纳如下: 优点:实现简单,可跨多页面。 缺点:及时性欠缺,灵活度不够。 适用情况:不要求事件的及时性和功能比较集中的模块。 方案四:利用路由堆栈获取目标页面实例 兵法中常说“擒贼先擒王”,如果我们拿到了某个页面的实例索引,那就相当于是在战场上控制了敌方的将领,我们说要粮草他就得给粮草,我们说要兵器他就得乖乖的给兵器。所以该方案我们也可以戏称为“擒王方案”。如果我们给“擒王方案”做一个归纳的话,应该是这样的: 优点:灵活性/及时性高;数据类型不限;可跨多页面使用; 缺点:代码重复性较高;不在堆栈内的页面无法进行操作; 适用情况: 确定页面实例在堆栈内的交互性比较强多页面。 提炼升华 在上一节中我们对四个方案进行了一下简单的梳理,每个方案也各有优缺点,上述四种方案可能已经满足了我们工作中的使用,可是作为程序员的我们不应该停下追逐更优更好的脚步。我们尽量把上述方案的优点集中起来,并且规避掉缺点。整理出一个相对完善的方案。首先自定义一个跨页面(当然也可在页面内使用)的事件处理类,暂时命名其为funbus。具体的处理逻辑如下: 一:定义全局事件缓存Map。 [代码]// 事件缓存 const events = {}; [代码] 二:根据 getCurrentPages() 函数获取被操作页面实例。 [代码]/** * 同步执行,会立即执行并拿到被执行函数的返回结果 * * pagePath 页面名称或路径 * method 执行的方法名 * params 方法参数 */ function callFun(pagePath, method, params) { let pages = getCurrentPages(); let page = null; for (let i = 0; i < pages.length; i++) { if (pages[i].route.indexOf(pagePath) > -1) { page = pages[i]; break; } } if (page) { try { return page[method](...params); } catch (err) { console.error('FunBus Error: ', err); return null; } } return null; } [代码] 三:当然我们也需要处理如果被操作的页面不在堆栈内的情况。 1.事件注册和解绑。 [代码]/** * 注册事件 * * key 值命名规则 页面名称-描述 (如: index-refresh) * event 是一个对象: {path: '被注册事件发生的页面路径', method: '被注册的方法名称', params: [...被注册的方法需要的参数]} * * 调用范例: subscribe("index-refresh", {path:"pages/index", method:"refreshPage", params: [1,2,3]}); */ function subscribe(key, event) { events[key] = event; } /** * 解除绑定 */ function unSubscribe(key) { delete events[key]; } [代码] 2.之前未在堆栈内的页面加入到堆栈时(即展示到前台时)在适当时机触发之前缓存的事件。 [代码]/** * 唤醒/执行之前订阅的事件 */ function notifyEvent(key, remove) { let event = events[key]; if (event) { // 只有remove的值是布尔类型的false时才不会移除当前事件,其他任何值该事件都会被移除 if (!remove && remove !== false) { remove = true; } remove && delete events[key]; return callFun(event.path, event.method, event.params) } return null; } [代码] 四:工具类的使用 1. 直接使用 [代码]let result = funbus.callFun('a/a', 'returnBpageData', [1, 2]); this.setData({ astring: result, }); [代码] 2. 页面未在堆栈内的使用 [代码]// C页面内 // 由于B页面跳转C是重定向 redirectTo 跳过来的,所以B页面不在路由堆栈内,我们要先注册,然后再B页面里适当的时机出发该函数。 funbus.subscribe('b-changebgc', { path: 'b/b', method: 'changeBgColor', params:['yellow']}); // B页面内 // 触发在C页面注册的函数 funbus.notifyEvent('b-changebgc'); [代码] 五:传送门 Demo 下载 总结 本文大致可以分为两个重点部分。前一部分我们把页面之间进行数据传递的四种常用的方案做了一个简要的分析总结。后一部分主要是根据前一部分的优缺点整理得出一个通用的数据传递和事件处理的工具类,并对其实现和使用进行了简要说明。在文末也提供了Demo的github地址,若使用中有什么不合理不完善的地方还请不吝指出。
2019-11-14 - 新能力解读:页面间通信接口
在 2019 年 7 月 2 日的小程序基础库版本更新 v2.7.3 中,小程序新增了一个页面间通讯的接口,帮助我们的小程序完成不同页面间数据同步的功能。 页面间通信接口能干嘛? 在 v2.7.3 之前,小程序不同页面间的大批量数据传递主要有两种: 借助诸如 Mobx 、Redux 等工具,来实现不同页面间的数据传递。 借助小程序提供的 storage ,来完成在不同页面间数据的同步。 前者需要引入一些第三方工具库,从而提升了整个应用的大小,同时,引入的工具也带来了学习生本。而后者则是基于小程序提供的存储,先将数据存入存储,再到另外一个页面去读取,如果数据涉及到了多个页面,则可能会导致数据的紊乱。 新的页面间通信接口则直接解决了上述的两个问题,你可以直接使用 API 在两个页面之间传递数据,再也无需担心数据的紊乱。 新增的页面间通信接口应当如何使用? 关于页面间通信接口的使用非常简单。 这里,我们假设存在 A 和 B 两个页面,其中 A 是首页,B是详情页。 A 向 B 传递数据 如果你需要从首页向详情页传递数据,则可以这样操作。 在页面 A 执行代码 [代码]wx.navigateTo({ url: 'test?id=1' success: function(res) { // 通过eventChannel向被打开页面传送数据 res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' }) } }) [代码] 这样,当 A 跳转到 B 时,就会出发 B 当中定义的 acceptDataFromOpenerPage,并将后续的数据传递过去。 在 B 中,你可以在 onLoad 去定义 eventChannel 的相关方法 [代码]Page({ onLoad: function(option){ // 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据 let eventChannel = this.getOpenerEventChannel(); eventChannel.on('acceptDataFromOpenerPage', function(data) { console.log(data) }) } }) [代码] B 向 A 传递数据 如果需要被打开的页面向打开的页面传递数据,则可以使用如下代码: 在 A 中的跳转时,加入 events 的定义,定义你自己的函数,以及对应的处理函数。 [代码]wx.navigateTo({ url: 'test?id=1', events: { someEvent: function(data) { console.log(data) } }, }) [代码] 然后在 B 中,调用如下代码来发信息 [代码]Page({ onLoad: function(option){ const eventChannel = this.getOpenerEventChannel() eventChannel.emit('someEvent', {data: 'test'}); } }) [代码] 这样,就可以在 B 页面将数据传回到 A 页面了。 页面间通信接口使用注意事项? 在使用页面间通信接口时需要注意两点: 该功能从基础库 2.7.3 开始支持,低版本需做兼容处理。
2019-09-21 - 云开发调用云函数出错
已安装node.js 8.9.0 并安装wx-server-sdk,已创建云函数并上传云平台,访问云函数时报错 WACloud.js:1 Uncaught (in promise) Error: errCode: -404011 cloud function execution error | errMsg: cloud.callFunction:fail cloud function service error code -501005, error message Environment not found; at cloud.callFunction api; 调用代码: onLoad(){ wx.cloud.init({ env: 'text' }) wx.cloud.callFunction({ name:'add', data:{ a:12, b:19 } }).then(console.log) }
2018-09-19