imwty

专注大前端Web应用开发实践

0%

uni-app开发小程序系列--获取用户信息

上次我们分享了如何做微信登录,用户登录后,一般需要完善资料,这一期我们就来实现如何完善用户信息。因为微信小程序是在微信内,如果我们能直接通过微信获取用户的信息,是不是就可以不用让用户重新填写一遍基本信息了呢。其实是的,微信官方也考虑到了这一点,所以给我们提供了几种方式,但是这些方式都零散的分布在文档的各个地方,今天笔者就把他们进行一波汇总。

如何获取用户信息?

1. wx.getUserInfo(废弃)

原本微信给我们提供了接口,可以在 js 中直接获取当前用户的用户信息,昵称啊,头像,地区什么的都有,如果能直接获取到,我们直接转存到我们服务器上就好了,会方便很多。可是我看了下官方文档,有如下改动
image.png
也就是说,我们没法通过 wx.getUserInfo 直接获取用户信息了,这个方法只能在小游戏内使用了,GG~
笔者也亲自试了一下,果然,现在直接调用这个接口返回的信息都是空的,用户昵称会显示为“微信用户”…

2.开放标签

这个属于微信提供的官方组件,专门用于展示微信开放的数据,使用方式如下:

1
2
3
<open-data type="groupName" open-gid="xxxxxx"></open-data>
<open-data type="userAvatarUrl"></open-data>
<open-data type="userGender" lang="zh_CN"></open-data>

其中 type 可以为如下这些值:

groupName 拉取群名称
userNickName 用户昵称。不再返回,展示“微信用户”
userAvatarUrl 用户头像。不再返回,展示 灰色头像
userGender 用户性别。不再返回,将展示为空(“”)
userCity 用户所在城市。不再返回,将展示为空(“”)
userProvince 用户所在省份。不再返回,将展示为空(“”)
userCountry 用户所在国家。不再返回,将展示为空(“”)
userLanguage 用户的语言。不再返回,将展示为空(“”)

需要注意的是,这些开放标签官方也是说明已被回收~
image.png
但是笔者试了一下,发现其实还能用,不知道是否是后续某个版本里又给加回去了,当然,这种开放标签其实只能用于展示,如果我们想转存用户数据,这个就很麻烦。

3.头像昵称填写能力

image.png
代码示例如下:

1
2
3
4
5
6
7
8
<button
class="avatar-wrapper"
open-type="chooseAvatar"
bind:chooseavatar="onChooseAvatar"
>
<image class="avatar" src="{{avatarUrl}}"></image>
</button>
<input type="nickname" class="weui-input" placeholder="请输入昵称" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const defaultAvatarUrl =
"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0";

Page({
data: {
avatarUrl: defaultAvatarUrl,
},
onChooseAvatar(e) {
const { avatarUrl } = e.detail;
this.setData({
avatarUrl,
});
},
});

可以看到,这种方式要获取用户头像需要借助 button 组件的开放能力,而且还需要用户的交互行为,基本上是用于修改资料时提供默认选项的场景里。对于获取用户昵称,则是用了原生的 input 标签,需要添加一个type="nickname"的参数来实现。由此可见,如果我们要实现自动填写用户昵称,那么得使用原生 input 标签而非一些第三方 ui 库了。
同时,笔者好奇看了看 button 组件都有哪些开发能力,这就出来了第 4 个方法。

4. button 组件开放能力

微信小程序的 button 组件拥有一个 open-type 属性,不同的属性可以关联不同的能力,例如上述的头像昵称填写能力,那么总共有哪些开放能力呢,官网给出了列表:

合法值 说明 最低版本
contact 打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息,具体说明
(_小程序插件中不能使用_)
1.1.0
share 触发用户转发,使用前建议先阅读使用指引 1.2.0
getPhoneNumber 获取用户手机号,可以从 bindgetphonenumber 回调中获取到用户信息,具体说明
(_小程序插件中不能使用_)
1.2.0
getUserInfo 获取用户信息,可以从 bindgetuserinfo 回调中获取到用户信息 (_小程序插件中不能使用_) 1.3.0
launchApp 打开 APP,可以通过 app-parameter 属性设定向 APP 传的参数具体说明 1.9.5
openSetting 打开授权设置页 2.0.7
feedback 打开“意见反馈”页面,用户可提交反馈内容并上传日志
,开发者可以登录小程序管理后台
后进入左侧菜单“客服反馈”页面获取到反馈内容
2.1.0
chooseAvatar 获取用户头像,可以从 bindchooseavatar 回调中获取到头像信息 2.21.2

关键来了,open-type 有一个 getUserInfo 的值,就是说我们可以设计一个按钮,当用户点击按钮后,我们就能获得用户的头像昵称等一些用户数据。

uni-app 中如何用?

鉴于方式 3 属于新增的,笔者将使用方式 3 完成用户信息的收集。

获取用户昵称

首先是获取用户昵称,笔者封装了一个单独的页面组件,当需要填写用户昵称时,跳转到该页面,填写完并点击确定后,再跳转回去。
其中,用户昵称填写需要用到原生标签,一些第三方的表单组件是不能用的。笔者代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<form @submit="handleEditNickname">
<div class="form-item">
<input
name="nickname"
type="nickname"
placeholder="请输入昵称"
:value="user.nickname"
/>
</div>
<button class="submit-btn mt-2" form-type="submit" type="primary">
保存
</button>
</form>
</template>

<script setup>
import { useUserStore } from "@/stores/user";
const user = useUserStore();

function handleEditNickname(e) {
// 获取到用户昵称,存储到store中
user.setUserInfo("nickname", e.detail.value.nickname);
uni.navigateBack();
}
</script>

代码运行效果如下:
image.png

获取用户头像

获取用户头像相对简单一些,主要是需要使用原生的 button, 我们需要对原生 button 样式进行一些复写。话不多说,先看效果:
image.png
头像区域本身是一张图片,我们需要用 button 标签包裹住图片以实现用户点击时可以触发打开相册。另外,我们获取选择到的头像其实是一个本地的临时文件路径,我们在保存前还需要进行一次上传,笔者代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<template>
<div class="edit-info">
<div class="flex-box center align-center p-3">
<button
class="avatar-wrapper"
:plain="true"
open-type="chooseAvatar"
@chooseavatar="onChooseAvatar"
>
<image class="avatar" :src="user.avatar"></image>
<div class="font2">点击图片修改头像</div>
</button>
</div>
<div class="other-form p-3">
<div class="font1">基础信息</div>
<van-cell
class="form-cell"
title="昵称"
:value="user.nickname"
is-link
url="/pages/my/edit-nickname"
/>
</div>
</div>
</template>

<script setup>
import { reactive, ref } from "vue";
import { useUserStore } from "@/stores/user";
import request from "@/common/request";
import { uploadToQiniu } from "@/common/util";

const user = useUserStore();

function onChooseAvatar(e) {
uni.showLoading({
title: "上传中",
});
// 获取到微信头像临时地址
const { avatarUrl } = e.detail;
// 上传文件到服务器
request.get("/qiniu-token").then((tokenInfo) => {
uploadToQiniu(tokenInfo, avatarUrl).then((uploadedAvatar) => {
uni.hideLoading();
// 将头像存储到store中
user.setUserInfo("avatar", uploadedAvatar);
});
});
}
</script>

<style lang="scss">
.edit-info {
width: 100%;
height: 100%;
box-sizing: border-box;

.avatar-wrapper {
background-color: #fff;
border: 0 none;
line-height: 1.5;

.avatar {
width: 180rpx;
height: 180rpx;
border-radius: 20rpx;
background-color: #ddd;
}
}
}
</style>

其中关于上传文件的细节,其实就是使用wx.uploadFile接口去实现的,这里就不再赘述,如果有不懂的小伙伴,可以私信我。

总结

从上述 4 种方式比较可以看出,原本方便的前两种方式,微信官方都在试图收回,所以,大家选择的时候,最好还是使用后两种方式。如果不是那种必须要收集用户昵称头像的场景,应该尽量使用方式 3,也就是在用户填写和完善资料的时候提供快捷的默认选项。

关于作者

8 年+Web 开发经验,多年深耕 Vue2,Vue3 技术栈。全栈开发经验丰富,技能树覆盖从前端工程搭建到部署上线全链路流程。紧跟技术潮流,一直关注着各种新兴技术趋势并积极进行实践探索,追求优雅的开发体验,极致的开发效率,高标准的开发质量。
欢迎批评指正,或者与我交流探讨前端技术。
联系我:imwty2023(微信)