后台回复“z”加群,一起交流技术!
欢迎继续阅读《Taro 小程序开发大型实战》系列,前情回顾:
熟悉的 React,熟悉的 Hooks[1]:我们用 React 和 Hooks 实现了一个非常简单的添加帖子的原型
多页面跳转和 Taro UI 组件库[2]:我们用 Taro 自带的路由功能实现了多页面跳转,并用 Taro UI 组件库升级了应用界面
实现微信和支付宝多端登录[3]:实现了微信、支付宝以及普通登录和退出登录
使用 Hooks 版的 Redux 实现大型应用状态管理(上篇)[4]:使用 Hooks 版的 Redux 实现了
user
逻辑的状态管理重构使用 Hooks 版的 Redux 实现大型应用状态管理(下篇)[5]:使用 Hooks 版的 Redux 实现了
post
逻辑的状态管理重构Taro 小程序开发大型实战(六):尝鲜微信小程序云(上篇)[6]:
user
逻辑接入微信小程序云Taro 小程序开发大型实战(七):尝鲜微信小程序云(下篇)[7]:
post
逻辑接入微信小程序云
在上两篇文章中,我们讲解了使用微信小程序云作为我们的小程序后台,然后我们跑通了我们的注册登录、创建帖子、获取帖子列表、获取帖子详情的全栈流程,如果只想了解微信小程序的全栈开发流程的话,之前的文章已经足够了,如果还想了解跨端开发全栈开发流程的话(当然用 Taro 的同学估计也比较期待跨端的全栈开发流程,手动滑稽)接下来这篇文章就是你的菜了????
首先我们先来看一下最终的运行效果:
如果你不熟悉 Redux,推荐阅读我们的《Redux 包教包会》系列教程:
Redux 包教包会(二):趁热打铁,完全重构[9]
Redux 包教包会(三):各司其职,重拾初心[10]
如果你希望直接从这一步开始,请运行以下命令:
git clone -b leancloud-start https://github.com/tuture-dev/ultra-club.git
cd ultra-club
本文所涉及的源代码都放在了 Github[11] 上,如果您觉得我们写得还不错,希望您能给❤️这篇文章点个在看+Github仓库加星❤️哦~
此教程属于 React 前端工程师学习路线[12]的一部分,欢迎来 Star 一波,鼓励我们继续创作出更好的教程,持续更新中~
在这一篇文章中,我们将接入 LeanCloud Serverless 服务,它类似微信小程序云,只不过它没有平台属性,所有的端都可以便捷访问,相信你已经迫不及待了,让我们马上开始吧????!
小程序接入外网的流程
因为小程序是封装在一些巨型 App 应用里的沙盒环境之内,所以对于接入外站的服务需要一些特殊的流程,我们在这里总结一下:
注册外站服务的账号
找到对应的小程序开发接入指南
获取对应的接入地址,将接入地址填入小程序后台的白名单列表
在小程序实际接入,并进行测试
在这篇文章中,我们的外站特指 LeanCloud Serverless 云服务,小程序特指微信小程序和支付宝小程序。
好的,了解了流程之后,我们现在来走一遍流程来将我们的 LeanCloud 接入到微信/支付宝小程序。
注册外站服务的账号
访问 LeanCloud 网址:点我访问[13],完成注册登录流程。
找到对应的小程序开发接入指南
这里我们找到 LeanCloud 微信/QQ 小程序接入指南:点我访问[14]
注意
LeanCloud 没有提供支付宝的接入指南,但是小程序接入指南都基本类似,我们会一一讲解这一流程。
获取对应的接入地址
LeanCloud 已经有详细的链接提示如何接入:
对于支付宝小程序的白名单配置地址如下:点我访问[15]。
在小程序实际接入,并进行测试
最后我们需要进行小程序的实际接入,因为 LeanCloud 并没有提供支付宝小程序的 SDK 包,这里对于支付宝小程序我们使用 LeanCloud 提供的 REST 接口进行访问,具体地址如下:点我访问[16]。
定义 LeanCloud 相关的辅助函数
对于接入 LeanCloud,我们需要在应用中做一系列初始化环境的准备,在 src/api/
文件夹下创建 utils.js
文件,并在其中编写内容如下:
const API_BASE_URL = ''
const LOGIN_URL = `${API_BASE_URL}/1.1/functions/login`
const CREATE_POST_URL = `${API_BASE_URL}/1.1/functions/createPost`
const GET_POST_URL = `${API_BASE_URL}/1.1/functions/getPost`
const GET_POSTS_URL = `${API_BASE_URL}/1.1/functions/getPosts`
const HEADER = {
'X-LC-Prod': 1,
'X-LC-Id': '',
'X-LC-Key': '',
}
const convertUserFormat = user => {
const _id = user.objectId
delete user.objectId
return { ...user, _id }
}
const convertPostFormat = post => {
const _id = post.objectId
const user = convertUserFormat(post.user)
delete post.objectId
delete post.user
return { ...post, _id, user }
}
const convertPostsFormat = posts => {
const convertedPosts = posts.map(post => convertPostFormat(post))
return convertedPosts
}
export {
LOGIN_URL,
HEADER,
CREATE_POST_URL,
GET_POST_URL,
GET_POSTS_URL,
convertPostsFormat,
convertPostFormat,
convertUserFormat,
}
可以看到,上面的代码主要分为四个部分:
定义云函数的 REST URL,LeanCloud 的云函数 REST URL 的格式类似这样:
https://API_BASE_URL/1.1/functions/functionName
,其中API_BASE_URL
可以通过文档获取:点我访问[17];而functionName
即为我们需要调用的云函数名字。这里我们定义了API_BASE_URL
,我们给了空字符串,读者可以根据 LeanCloud 给与的Base URL
替代空字符串;同样我们定义了四个云函数,分别代表登录、创帖、查询帖子列表、查询单个帖子,具体的云端云函数我们将在后面定义。第二个部分即为向 LeanCloud 服务器发送 REST 请求时需要携带的请求头部,这个也可以在文档里给出:点我访问[18];这里也需要用户用自己的内容来替换上面的空字符串。
第三个部分则为两个辅助转换格式的函数,主要用于将 LeanCloud 数据库格式的数据与现有的微信小程序数据库格式的数据兼容。
第四个部分为导出这些定义的内容,供其它模块使用。
提示
上面的
API_BASE_URL
和HEADER
都需要用户在登录的情况下访问给出的地址才能获取到。
在 LeanCloud 上面创建数据库表
登录 LeanCloud 控制台,在左边栏的 存储 > 结构化数据 可以看到创建 Class 的按钮,我们可以通过创建一个 Class 来创建一张数据库表:
可以看到我们创建了两张表:Post
和 MyUser
,一个存放和帖子相关的数据,一个存放和用户相关的数据。其中 MyUser
类似之前我们在微信小程序数据库表时的 user
表。
定义 MyUser 字段
如图之前在微信小程序数据库表创建时一样,我们同样为 MyUser
定义如下的字段:
avatar
nickName
至于读者看到的其它字段都是 LeanCloud 默认创建且自动更新的字段,用户不可以操作。
定义 Post 字段
同样和之前在微信小程序里面创建 post
一样,我们给 Post 定义如下字段:
content
title
user
眼尖的同学可能注意到了,这里的 user
字段是一个 Pointer
类型,它是 LeanCloud 数据表独有的引用类型,类似关系数据库里面的外键,即存一个指针,之后获取数据的时候可以便捷的获取对应的 user
数据。
关于默认 Class 的解释
这里有些读者可能有疑问,为什么还有一些多余的表了?这些以下划线开头的 Class 其实是 LeanCloud 默认创建的,不允许删除,用于 LeanCloud SDK 封装一系列常用且复杂的应用功能,供用户快速搭建 App/网站/小程序原型,比如类似微信的朋友圈功能,LeanCloud 提供开箱即用的逻辑,你可以直接调用。
并且,类似 _User
和 User
Class 其实是引用自同一个 Class,所以不能创建和 LeanCloud 默认的类具有同名且不带前缀下划线的类,比如 User
,File
类就不能创建,所以这里我们创建了 MyUser
类,这样不用去考虑 _User
类本身存在的一些细节限制。
在 LeanCloud 上创建云函数
在上一步里面,我们在小程序代码里创建了和 LeanCloud 有关的逻辑代码,其中我们创建了四个云函数,现在我们要创建对应这四个云函数的实际云函数。
注册并登陆 LeanCloud 之后,点击左边栏的 云引擎 > 部署 可以看到类似下面的界面:
LeanCloud 提供给我们在线创建和编写云函数的方便界面,使得我们不用自己创建本地服务器代码和配置部署和运维过程,大大加速了程序的开发过程。
接下来,我们将遵循以下三步走的方式来进行 LeanCloud 云函数的开发:
创建云函数
部署
在小程序端进行调试
创建 User 逻辑 云函数
点击界面里面的创建按钮,会看到如下的界面:
可以看到上图分为如下几个部分:
选择我们要创建的函数类型,主要有三类,这里我们选择
Function
,这也是默认选择的类型,其余两类读者有兴趣可以自行探索,这里我们不展开讲。接着就是定义你的函数名,这里我们填入
login
。接着就是编写函数体,它是一个 Node.js 函数,我们只需要编写对应的 Node.js 处理逻辑就可以了。
最后我们可以对这个函数写一点注释,方便日后回顾,这里我们选择不填入。
好的,了解了创建函数的弹出层之后,我们填入我们需要创建的 login
函数体如下:
const { userInfo } = request.params
const query = new AV.Query('MyUser')
query.equalTo('nickName', userInfo.nickName)
const users = await query.find()
if (users.length > 0) {
return users[0]
} else {
const MyUser = AV.Object.extend('MyUser')
const myUser = new MyUser()
const { nickName, avatar } = userInfo
myUser.set('nickName', nickName)
myUser.set('avatar', avatar)
const user = await myUser.save()
return user
}
可以看到我们上面的内容主要改动有四处:
从
request.params
取到对应的请求体数据userInfo
,这决定了我们之后在小程序端调用 LeanCloud 云函数时,要使用POST
的方式。接着我们使用了 LeanCloud 的查询 SDK 操作
首先通过
new AV.Query
新建一个对MyUser
Class 的查询请求。注意到这里的AV
接口是 LeanCloud 暴露给我们的默认接口,可以通过这个接口操作 LeanCloud 的各种资源。接着通过
equalTo
进行条件过滤,这里我们查询nickName
为userInfo.nickName
的用户。通过
query.find()
来提交查询操作,注意到这里我们使用了await
关键字,那是因为默认包裹云函数提的是一个async
函数,允许我们方便的执行异步流程。
接着我们对查询到的数据进行判断,如果
users.length > 0
表示存在用户,那么我们返回查询到的第一个用户;如果不存在,我们执行创建用户操作,再返回创建的用户。创建用户的操作主要是如下几个步骤:
AV.Object.extend
对应的 Class 来获取对应的类实例化这个类获取一个对象
设置这个对象的属性,这里通过
set(key, value)
的方式设置通过对象的
save
方法进行保存,保存到 LeanCloud 数据库
注意
这里我们只用到了 LeanCloud 的一些简单操作,具体的详情可以查看官方文档,官方文档撰写了非常完备的操作指南:点我查看[19]。
部署
按照上面的步骤编写完 login
云函数之后,点击保存,此时我们的云函数就编写好了,但是我们目前在小程序端还无法调用它,因为我们还需要一个部署的操作。
在 LeanCloud 上面进行云函数的部署也同样简单,只需要点击一个按钮:
点我之后,等待部署提示,过一会应该就会提示部署成功,这个时候我们就可以在小程序端通过 REST API 访问了。
在小程序端进行调试
我们这里使用 LeanCloud 主要是让支付宝小程序也可以成为全栈应用,对应我们之前提到的 H5,因为 Taro 目前对 H5 的支持还不完善,我们决定放弃对 H5 的讲解, 但是这并不代表 Taro 存在缺陷,只能说它是一个很有潜力的框架,成长还需要实践,并且跨端小程序是它诞生的重点,将精力放在主要的路径上是值得提倡的,Taro 在近期发布了 Taro Next,支持使用 Vue/React/Nerve 开发跨端小程序,笔者这里推荐读者可以尝试一波:点我跳转[20]。
因为我们首先创建了 login
的云函数,所以我们需要改进一下我们的支付宝登录的按钮逻辑,打开 src/components/AlipayLoginButton/index.js
对其中的内容作出如下的修改:
import { useDispatch } from '@tarojs/redux'
import './index.scss'
import { LOGIN } from '../../constants'
export default function AlipayLoginButton(props) {
const [isLogin, setIsLogin] = useState(false)... userInfo = JSON.parse(userInfo.response).response
const { avatar, nickName } = userInfo
dispatch({
type: LOGIN,
payload: {
userInfo: {
avatar,
nickName,
},
},
})
} catch (err) {
可以看到,上面的内容改动主要有三处:
我们删掉了使用支付宝获取登录信息之后存缓存的逻辑
接着,我们 dispatch 了一个
action.type
为 LOGIN 的异步 ACTION,并传递了userInfo
数据最后我们导入了需要的
LOGIN
常量。
除了支付宝登录按钮的逻辑改进之外,我们还要改进我们的 api 逻辑,加上对支付宝环境的判断和调用对应的 LeanCloud 云函数。
打开 src/api/user.js
文件,对其中的内容作出对应的修改如下:
import Taro from '@tarojs/taro'
import { HEADER, LOGIN_URL, convertUserFormat } from './utils'
async function login(userInfo) {
const isWeapp = Taro.getEnv() === Taro.ENV_TYPE.WEAPP
const isAlipay = Taro.getEnv() === Taro.ENV_TYPE.ALIPAY
const isH5 = Taro.getEnv() === Taro.ENV_TYPE.WEB
// 针对微信小程序使用小程序云函数,其他使用小程序 RESTful API
try {... })
return result.user
} else if (isAlipay || isH5) {
const { data } = await Taro.request({
url: LOGIN_URL,
method: 'POST',
header: { ...HEADER },
data: {
userInfo,
},
})
return convertUserFormat(data.result)
}
} catch (err) {
console.error('login ERR: ', err)
可以看到上面主要做了四处修改:
首先我们导入了之前定义的和 LeanCloud 有个的
utils
函数。接着我们加入了对 H5 环境的判断。
最后我们增加了一个
else if
流程,用于判断在支付宝小程序或者 H5 环境下需要执行发起 REST 请求的逻辑,这里我们使用了Taro.request
进行网络请求,并传入了对应的url
、header
、data
,以及将请求的类型设置为POST
,之前我们提到过,对 LeanCloud 云函数发起请求都需要使用POST
方法。最后我们将从 LeanCloud 拿到的请求结果使用
convertUserFormat
做了一次格式的转换,以适应现有的微信小程序数据类型。
好了,通过以上三步流程,我们就跑通了小程序类请求 LeanCloud 的流程,保存修改的代码,让我们马上打开支付宝小程序试一下吧!
创建 Post 逻辑云函数
在上一节中,我们创建了 User 逻辑的 login
云函数,在这一节中,我们来收尾 Post 逻辑的三个云函数:
createPost
getPosts
getPost
因为创建的逻辑和方式和之前的 login
云函数类似,我们这里不再赘述,会简单的贴一下代码,但我们同样按照之前的三步流程来讲解。
创建云函数
首先创建我们的 createPost
云函数,其代码如下:
const { postData, userId } = request.params
const Post = AV.Object.extend('Post')
const post = new Post();
const myUser = AV.Object.createWithoutData('MyUser', userId)
const newPost = await post.save({
...postData,
user: myUser
});
const query = new AV.Query('Post')
const postWithUser = await query.equalTo('objectId', newPost.get('objectId')).include('user').first()
return postWithUser
接着来创建我们的获取帖子列表的云函数 getPosts
,其代码如下:
const query = new AV.Query('Post')
const posts = await query.include('user').find()
return posts
最后是我们的获取帖子详情的云函数 getPost
:
const { postId } = request.params
const query = new AV.Query('Post')
const post = await query.equalTo('objectId', postId).include('user').first()
return post
部署
好的,三个和 Post 逻辑有关的云函数创建好了,我们马上点击部署按钮来将它们部署上线。
在小程序端测试
当创建好云函数,并部署好之后,我们就可以在小程序端编写对应的代码进行测试了,打开 src/api/post.js
文件,对其中的代码做出对应的修改如下:
import Taro from '@tarojs/taro'
import {
HEADER,
CREATE_POST_URL,
GET_POSTS_URL,
GET_POST_URL,
convertPostFormat,
convertPostsFormat,
} from './utils'
async function createPost(postData, userId) {
const isWeapp = Taro.getEnv() === Taro.ENV_TYPE.WEAPP
const isAlipay = Taro.getEnv() === Taro.ENV_TYPE.ALIPAY
const isH5 = Taro.getEnv() === Taro.ENV_TYPE.WEB
// 针对微信小程序使用小程序云函数,其他使用小程序 RESTful API
try {... })
return result.post
} else if (isAlipay || isH5) {
const { data } = await Taro.request({
url: CREATE_POST_URL,
method: 'POST',
header: { ...HEADER },
data: {
postData,
userId,
},
})
return convertPostFormat(data.result)
}
} catch (err) {
console.error('createPost ERR: ', err)...async function getPosts() {
const isWeapp = Taro.getEnv() === Taro.ENV_TYPE.WEAPP
const isAlipay = Taro.getEnv() === Taro.ENV_TYPE.ALIPAY
const isH5 = Taro.getEnv() === Taro.ENV_TYPE.WEB
// 针对微信小程序使用小程序云函数,其他使用小程序 RESTful API
try {... })
return result.posts
} else if (isAlipay || isH5) {
const { data } = await Taro.request({
url: GET_POSTS_URL,
method: 'POST',
header: { ...HEADER },
})
return convertPostsFormat(data.result)
}
} catch (err) {
console.error('getPosts ERR: ', err)...async function getPost(postId) {
const isWeapp = Taro.getEnv() === Taro.ENV_TYPE.WEAPP
const isAlipay = Taro.getEnv() === Taro.ENV_TYPE.ALIPAY
const isH5 = Taro.getEnv() === Taro.ENV_TYPE.WEB
// 针对微信小程序使用小程序云函数,其他使用小程序 RESTful API
try {... })
return result.post
} else if (isAlipay || isH5) {
const { data } = await Taro.request({
url: GET_POST_URL,
method: 'POST',
header: { ...HEADER },
data: {
postId,
},
})
return convertPostFormat(data.result)
}
} catch (err) {
console.error('getPost ERR: ', err)
可以看到上面主要做了四处修改:
首先我们导入了之前定义的和 LeanCloud 有关的
utils
函数。接着我们加入了对 H5 环境的判断。
最后我们增加了一个
else if
流程,用于判断在支付宝小程序或者 H5 环境下需要执行发起 REST 请求的逻辑,这里我们使用了Taro.request
进行网络请求,并传入了对应三个和 Post 逻辑有关的url
、以及对应的header
、data
,以及将请求的类型设置为POST
,之前我们提到过,对 LeanCloud 云函数发起请求都需要使用POST
方法。最后我们将从 LeanCloud 拿到的请求结果使用
convertPostFormat
做了一次格式的转换,以适应现有的微信小程序数据类型。
好了,通过以上三步流程,我们就跑通了小程序类请求 LeanCloud 的流程,保存修改的代码,让我们马上打开支付宝小程序试一下吧!
小结
在这篇文章中,我们讲解了支付宝小程序接入 LeanCloud Serverless 云服务的过程,我们再来复习一下整个流程:
首先我们讲解了微信小程序云的不足,然后引出了 LeanCloud 来实现跨端小程序开发
接着我们介绍了 LeanCloud 服务的配置过程,具体包含 1)注册登录 LeanCloud 2)配置对应的小程序后台的白名单。且因为 LeanCloud 没有支付宝小程序的 SDK,所以我们采用 REST 请求的方式来获取和修改对应的数据
接着我们讲解了如何在 LeanCloud 上面创建数据表。
接着,我们介绍了如何在 LeanCloud 创建云函数。
最后我们通过三步走流程:1)创建云函数 2)部署 3)在小程序端测试,创建了我们需要的四个云函数。
我们再来看一下整体的接入效果:
到这里我们的 Taro 多端小程序开发大型实战 就基本告一段落了,整个教程内容想当长,涵盖的内容也相当多,这也是图雀社区最长的一个系列教程。最后希望 Taro 社区越来越好,也希望能帮到您!
One More Thing
我们在之前的教程中花了8篇文章的篇幅讲解了小程序从0到开发完成的过程,但是我们还没将如何将小程序上线,这里我们再额外花一点笔墨讲一下如何上线你的小程序,因为小程序的上线很容易,所以内容不会很长,有兴趣的读者可以继续读下去ღ( ´・ᴗ・` )比心。
微信小程序上线
首先点击小程序开发者工具的右上角的上传按钮:
接着去微信小程序网站后台:点我前往。
进行登录之后,在进来的第一个页面的第二步可以看见版本发布的信息,安装微信官方的流程进行即可。
支付宝小程序上线
首先点击支付宝小程序开发者工具的右上角上传按钮:
接着去支付宝小程序后台:点我前往[21]。
进行登录之后,点击顶部的 开发中心,选择小程序应用,选择你的小程序应用,然后同样可以看到类似发布上线的栏目,安装支付宝官方的流程进行发布就可以了。
提示
微信/支付宝小程序对于有社交、社区性质的小程序是需要企业认证的,所以有类似需求的需要做一下准备。
好了,到这里我们的要说再见了 ????!希望你们学得开心!
想要学习更多精彩的实战技术教程?来图雀社区[22]逛逛吧。
本文所涉及的源代码都放在了 Github[23] 上,如果您觉得我们写得还不错,希望您能给❤️这篇文章点个在看+Github仓库加星❤️哦
参考资料
[1]
熟悉的 React,熟悉的 Hooks: https://juejin.im/post/5e046c4fe51d45584221e508
[2]多页面跳转和 Taro UI 组件库: https://juejin.im/post/5e0891b66fb9a0165936fb0b
[3]实现微信和支付宝多端登录: https://juejin.im/post/5e10118be51d454165777203
[4]使用 Hooks 版的 Redux 实现大型应用状态管理(上篇): https://juejin.im/post/5e100f78e51d4541493621cd
[5]使用 Hooks 版的 Redux 实现大型应用状态管理(下篇): https://juejin.im/post/5e1e63e8f265da3e4412b1f1
[6]Taro 小程序开发大型实战(六):尝鲜微信小程序云(上篇): https://juejin.im/post/5e1dd614f265da3e12181ff3
[7]Taro 小程序开发大型实战(七):尝鲜微信小程序云(下篇): https://juejin.im/user/5b33414351882574b9694d28/posts
[8]Redux 包教包会(一):解救 React 状态危机: https://juejin.im/post/5df62cd8e51d4558270ef5ca
[9]Redux 包教包会(二):趁热打铁,完全重构: https://juejin.im/post/5df7b11c51882512664b1068
[10]Redux 包教包会(三):各司其职,重拾初心: https://juejin.im/post/5e0fe9705188253ab044c869
[11]Github: https://github.com/tuture-dev/ultra-club
[12]React 前端工程师学习路线: https://github.com/tuture-dev/react-roadmap
[13]点我访问: https://www.leancloud.cn/
[14]点我访问: https://leancloud.cn/docs/weapp.html
[15]点我访问: https://mini.open.alipay.com/channel/miniIndex.htm
[16]点我访问: https://leancloud.cn/docs/leanengine-rest-api.html#hash20005220
[17]点我访问: https://leancloud.cn/docs/leanengine-rest-api.html#hash-1722650509
[18]点我访问: https://leancloud.cn/docs/leanengine-rest-api.html#hash20005220
[19]点我查看: https://leancloud.cn/docs/leanstorage_guide-js.html
[20]点我跳转: https://taro.jd.com/
[21]点我前往: https://mini.open.alipay.com/channel/miniIndex.htm
[22]图雀社区: https://tuture.co?utm_source=juejin_zhuanlan
[23]Github: https://github.com/tuture-dev/ultra-club
● Taro小程序开发大型实战(一):熟悉的React,熟悉的Hooks
● Taro小程序开发大型实战(二):多页面跳转和TaroUI组件库
● Taro 小程序开发大型实战(七):尝鲜微信小程序云(下篇)
·END·
图雀社区
汇聚精彩的免费实战教程
喜欢本文,点个“在看”告诉我