欢迎继续阅读《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 包教包会(一):解救 React 状态危机[8]
- Redux 包教包会(二):趁热打铁,完全重构[9]
- Redux 包教包会(三):各司其职,重拾初心[10]
如果你希望直接从这一步开始,请运行以下命令:
代码语言:javascript复制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
代码语言:javascript复制● Taro小程序开发大型实战(一):熟悉的React,熟悉的Hooks
● Taro小程序开发大型实战(二):多页面跳转和TaroUI组件库
● Taro 小程序开发大型实战(七):尝鲜微信小程序云(下篇)
·END·