最近微信小程序開發(fā)文檔說明,wx.getUserInfo()接口已經不會再彈授權框,甚至揚言要放棄這個接口。這次調整,還是蠻傷的。

看文檔說需要用
<button open-type="getUserInfo"></button>這個功能按鈕。乍一想,我需要判斷登錄了,就要有這樣一個按鈕?,多“撈”哦。我頁面這么好看,容不下你這個按鈕好嘛,根本沒有你位置。
解決方案1
單獨做個好看的登錄頁面,放個<button open-type=”getUserInfo”></button>按鈕。用戶一進來,就是登錄頁面,要他授權。也可以在需要登錄的地方,跳轉到登錄頁面,授權了然后再回來。
解決方案2
既然你不就是想要個按鈕嘛,給你彈一個好了。只要你需要登錄,我就給你彈一個<button open-type=”getUserInfo”></button>讓你給我授權。當然,你彈個登錄頁面也是一樣的。
方案1就不多說了,看看方案2效果圖吧。


上面的彈框用的不是wx.showModal()彈框。這個需要自己封裝的。

|--components
|--dialog
dialog.js // 彈框組件
dialog.json
dialog.wxml
dialog.wxss
components.js //頁面綁定數(shù)據(jù)、方法的一個類
components.js 代碼
class Component {
constructor (options = {}) {
Object.assign(this, {options});
this.__init();
}
/**
* 初始化
*/
__init () {
this.page = getCurrentPages()[getCurrentPages().length - 1];
const setData = this.page.setData.bind(this.page);
//重寫setData方法
this.setData = (obj = {}, cb = ()=>({})) => {
const fn = () => {
if (typeof cb === 'function') {
cb();
}
};
setData(obj, fn);
}
this.__initState();
}
/**
* 初始化組件狀態(tài)
*/
__initState () {
this.options.data && this.__initData();
this.options.methods && this.__initMthods();
}
/**
* 綁定組件數(shù)據(jù)
*/
__initData () {
const scope = this.options.scope;
const data = this.options.data;
this._data = {};
if (!this.isEmptyObject(data)) {
for (let key in data) {
if (data.hasOwnProperty(key)) {
if (typeof data[key] === 'function') {
data[key] = data[key].bind(this);
} else {
this._data[key] = data[key];
}
}
}
}
// 將數(shù)據(jù)同步到 page.data 方便組件渲染
this.page.setData({
[`${scope}`]: this._data
});
}
/**
* 綁定組件方法
*/
__initMthods () {
const scope = this.options.scope;
const methods = this.options.methods;
if (!this.isEmptyObject(methods)) {
for (let key in methods) {
if (methods.hasOwnProperty(key) && typeof methods[key] === 'function') {
this[key] = methods[key] = methods[key].bind(this);
//將組件內的方法重命名并掛載到 page 上, 否則 template 上找不到方法
this.page[`${scope}.${key}`] = methods[key];
//將方法同步到 page.data 上,方便 template 使用 {{methods}} 綁定事件
this.page.setData({
[`${scope}.${key}`]: `${scope}.${key}`
});
}
}
}
}
/**
* 獲取組件數(shù)據(jù)
*/
getComponentData () {
let data = this.page.data;
let name = this.options.scope && this.options.scope.split(".");
name.forEach((n,i) => {
data = data[n];
});
return data;
}
/**
* 判斷 Object 是否為空
*/
isEmptyObject (e) {
for (let t in e)
return !1
return !0;
}
/**
* 設置元素顯示
*/
setVisible () {
this.setData({
[`${this.options.scope}.visible`]: !0
});
}
/**
* 設置元素隱藏
*/
setHidden (timer = 300) {
setTimeout(()=> {
this.setData({
[`${this.options.scope}.visible`]: !1
});
}, timer);
}
}
export default Component;
dialog.js 代碼
// components/dialog/dialog.js
import Component from "../component";
export default {
//默認數(shù)據(jù)
data () {
return {
title: "提示",
content: "提示內容",
showCancel: !0,
cancelText: "取消",
cancelType: "button",
confirmText: "確定",
confirmType: "button",
confrimOpenType: "",
success: () => {
},
fail: () => {
},
complete: () => {
}
}
},
/**
* 創(chuàng)建組件
*/
open (opts = {}) {
const options = Object.assign({
visible: !1
}, this.data(),opts);
const component = new Component({
scope: `myDialog`,
data: options,
methods: {
//隱藏
hide (cb) {
this.setHidden();
setTimeout(() => typeof cb === 'function' && cb());
},
//顯示
show () {
this.setVisible();
},
//按鈕回調
buttonTapped (e) {
const index = e.currentTarget.dataset.index;
const button = options.buttons[index];
this.hide(() => {
if (options.buttons.length > 1) {
if (index < 1) {
typeof options.fail === `function` && options.fail(e);
}
} else {
typeof options.success === `function` && options.success(e);
}
});
},
//用戶信息回調
getUserInfo (e) {
this.hide(() => {
if (e.detail.userInfo) {
// 成功獲得用戶信息
typeof options.success === `function` && options.success(e);
} else {
// 用戶拒絕,走fail方法
typeof options.fail === `function` && options.fail(e);
}
typeof options.complete === `function` && options.complete(e);
});
}
});
component.show();
return component.hide;
},
/**
* 顯示彈框
*/
showModal (opts) {
const options = Object.assign({
visible: !1
},this.data(),opts);
let buttons = [];
//聲明取消按鈕
let cancel_btn = {
text: options.cancelText,
type: options.cancelType,
onTap: (e) => {
options.fail === 'function' && options.fail(e)
}
},
//聲明確定按鈕
confirm_btn = {
text: options.confirmText,
type: options.confirmType,
openType: options.confirmOpenType,
className: "modal-btn-primary",
onTap: (e) => {
options.success === 'function' && options.success(e);
}
};
//是否顯示取消按鈕
if (options.showCancel) {
buttons[0] = cancel_btn;
buttons[1] = confirm_btn;
} else {
buttons[0] = confirm_btn;
}
return this.open(Object.assign({buttons}, options));
}
};
dialog.wxml 代碼
<template name="dialog">
<view class="modal" wx:if="{{visible}}">
<view class="dialog">
<view class="modal-content">
<view class="modal-header">{{title}}</view>
<view class="modal-body">{{content}}</view>
<view class="modal-footer flex">
<block wx:for="{{buttons}}">
<button wx:if="{{item.openType == 'getUserInfo'}}"
class="modal-btn modal-btn-default {{item.className}}"
data-index="{{index}}"
type="{{item.type}}"
open-type="{{item.openType}}"
bindgetuserinfo="{{getUserInfo}}">{{item.text}}</button>
<button wx:else class="modal-btn modal-btn-default {{item.className}}"
data-index="{{index}}"
type="{{item.type}}"
bindtap="{{buttonTapped}}">{{item.text}}</button>
</block>
</view>
</view>
</view>
</view>
</template>
dialog.wxss 代碼
/* components/dialog/dialog.wxss */
.flex {
display: flex;
}
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, .5);
font-size: 0;
text-align: center;
white-space: nowrap;
overflow: auto;
z-index:9999;
}
.modal:after {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
}
.dialog {
display: inline-block;
font-size: 14px;
vertical-align: middle;
text-align: left;
white-space: normal;
}
.modal-content {
width: 240px;
height: 145px;
background-color: #fff;
}
.modal-header,
.modal-body{
padding: 15px;
}
.modal-header {
border-bottom: 1px solid #ddd;
}
.modal-footer {
border-top: 1px solid #ddd;
border: 1px solid red;
}
.modal-btn {
display: block;
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
color: #3CC51F;
text-decoration: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
position: relative;
background: #fff;
border-radius: 0;
}
.modal-btn:after {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 2rpx;
bottom: 0;
border-left: 2rpx solid #D5D5D6;
color: #D5D5D6;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleX(0.5);
transform: scaleX(0.5);
}
.modal-btn:first-child:after {
display: none;
}
.modal-btn-default {
color: #353535;
}
.modal-btn-primary {
color: #0BB20C;
}
引用組件
在需要彈框的頁面(.wxml)引入dialog.wxml模板
<import src="../../../components/dialog/dialog.wxml"/>
<template data="{{...myDialog}}" is="dialog" />
直接在app.wxss全局引用dialog.wxss
@import "./components/dialog/dialog.wxss";
對應js文件里面引用dialog.js
import myDialog from '../../../components/dialog/dialog';
//調起組件
myDialog.showModal({
title: "提示",
content: "需要您授權",
confirmOpenType: "getUserInfo", //如果不設置就是普通彈框
success: (e) => {
console.log("e", e);
let userInfo = e.detail.userInfo;
wx.setStorageSync("userInfo", userInfo);
},
fail: (err) => {
// 用戶不小必點到拒絕,提示登錄失敗
wx.showToast({
title: "登錄失敗",
icon: "none"
});
}
});
這樣原來我們用
wx.login({
success: (n) => {
wx.getUserInfo () {
success (e) => {
console.log(e);
}
}
}
});
就可以寫成
wx.login({
success: (n) => {
myDialog.showModal({
title: "提示",
content: "需要您授權",
confirmOpenType: "getUserInfo",
success: (e) => {
console.log("e", e);
let userInfo = e.detail.userInfo;
wx.setStorageSync("userInfo", userInfo);
}
});
}
});
總結
寫到這里呢,就已經結束了,有兩個需要我們注意的細節(jié)。一個是,在調起彈框之前,我們先要wx.login(),不然會報錯說你還沒登錄。二個是,如果用戶在調起授權框之后,他選擇了拒絕。當再次調起授權框,并同意,很可能會提示你code無效,就是已經用過的意思。所以還是要做好處理。
還有在寫登錄的時候我們可以把登錄的邏輯代碼封裝成一個方法,然后在頁面上引用就行。麻煩的是,在需要調起彈框的頁面(wxml),我們都要引用dialog.wxml的模板??偟膩碚f吧,這次api的調整還是蠻傷的。核心就是官方給的<button open-type="getUserInfo"></button>,看你怎么用了。如果你也喜歡彈彈彈這種方式,可以參考下。
最后附上一個我非常喜歡的大神寫的一個小程序組件庫: https://github.com/skyvow/wux,里面啥都有哦~