最近微信小程序開(kāi)發(fā)文檔說(shuō)明,wx.getUserInfo()接口已經(jīng)不會(huì)再?gòu)検跈?quán)框,甚至揚(yáng)言要放棄這個(gè)接口。這次調(diào)整,還是蠻傷的。
看文檔說(shuō)需要用
<button open-type="getUserInfo"></button>
這個(gè)功能按鈕。乍一想,我需要判斷登錄了,就要有這樣一個(gè)按鈕?,多“撈”哦。我頁(yè)面這么好看,容不下你這個(gè)按鈕好嘛,根本沒(méi)有你位置。
解決方案1
單獨(dú)做個(gè)好看的登錄頁(yè)面,放個(gè)<button open-type=”getUserInfo”></button>
按鈕。用戶一進(jìn)來(lái),就是登錄頁(yè)面,要他授權(quán)。也可以在需要登錄的地方,跳轉(zhuǎn)到登錄頁(yè)面,授權(quán)了然后再回來(lái)。
解決方案2
既然你不就是想要個(gè)按鈕嘛,給你彈一個(gè)好了。只要你需要登錄,我就給你彈一個(gè)<button open-type=”getUserInfo”></button>
讓你給我授權(quán)。當(dāng)然,你彈個(gè)登錄頁(yè)面也是一樣的。
方案1就不多說(shuō)了,看看方案2效果圖吧。
上面的彈框用的不是wx.showModal()彈框。這個(gè)需要自己封裝的。
|--components
|--dialog
dialog.js // 彈框組件
dialog.json
dialog.wxml
dialog.wxss
components.js //頁(yè)面綁定數(shù)據(jù)、方法的一個(gè)類
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);
//重寫(xiě)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);
//將組件內(nèi)的方法重命名并掛載到 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;
}
/**
* 設(shè)置元素顯示
*/
setVisible () {
this.setData({
[`${this.options.scope}.visible`]: !0
});
}
/**
* 設(shè)置元素隱藏
*/
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 {
//默認(rèn)數(shù)據(jù)
data () {
return {
title: "提示",
content: "提示內(nèi)容",
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();
},
//按鈕回調(diào)
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);
}
});
},
//用戶信息回調(diào)
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;
}
引用組件
在需要彈框的頁(yè)面(.wxml)引入dialog.wxml模板
<import src="../../../components/dialog/dialog.wxml"/>
<template data="{{...myDialog}}" is="dialog" />
直接在app.wxss全局引用dialog.wxss
@import "./components/dialog/dialog.wxss";
對(duì)應(yīng)js文件里面引用dialog.js
import myDialog from '../../../components/dialog/dialog';
//調(diào)起組件
myDialog.showModal({
title: "提示",
content: "需要您授權(quán)",
confirmOpenType: "getUserInfo", //如果不設(shè)置就是普通彈框
success: (e) => {
console.log("e", e);
let userInfo = e.detail.userInfo;
wx.setStorageSync("userInfo", userInfo);
},
fail: (err) => {
// 用戶不小必點(diǎn)到拒絕,提示登錄失敗
wx.showToast({
title: "登錄失敗",
icon: "none"
});
}
});
這樣原來(lái)我們用
wx.login({
success: (n) => {
wx.getUserInfo () {
success (e) => {
console.log(e);
}
}
}
});
就可以寫(xiě)成
wx.login({
success: (n) => {
myDialog.showModal({
title: "提示",
content: "需要您授權(quán)",
confirmOpenType: "getUserInfo",
success: (e) => {
console.log("e", e);
let userInfo = e.detail.userInfo;
wx.setStorageSync("userInfo", userInfo);
}
});
}
});
總結(jié)
寫(xiě)到這里呢,就已經(jīng)結(jié)束了,有兩個(gè)需要我們注意的細(xì)節(jié)。一個(gè)是,在調(diào)起彈框之前,我們先要wx.login(),不然會(huì)報(bào)錯(cuò)說(shuō)你還沒(méi)登錄。二個(gè)是,如果用戶在調(diào)起授權(quán)框之后,他選擇了拒絕。當(dāng)再次調(diào)起授權(quán)框,并同意,很可能會(huì)提示你code無(wú)效,就是已經(jīng)用過(guò)的意思。所以還是要做好處理。
還有在寫(xiě)登錄的時(shí)候我們可以把登錄的邏輯代碼封裝成一個(gè)方法,然后在頁(yè)面上引用就行。麻煩的是,在需要調(diào)起彈框的頁(yè)面(wxml),我們都要引用dialog.wxml的模板。總的來(lái)說(shuō)吧,這次api的調(diào)整還是蠻傷的。核心就是官方給的<button open-type="getUserInfo"></button>
,看你怎么用了。如果你也喜歡彈彈彈這種方式,可以參考下。
最后附上一個(gè)我非常喜歡的大神寫(xiě)的一個(gè)小程序組件庫(kù): https://github.com/skyvow/wux,里面啥都有哦~