小程序模板網(wǎng)

微信小程序全局Toast嘗試思路

發(fā)布時間:2018-05-09 14:56 所屬欄目:小程序開發(fā)教程

前言

toast 或 message 組件,基本是每個項目都會使用到的。

在Vue、React中它們都是組件,而我們習(xí)慣將這類型的組件處理全局Api,以避免每個頁面都要寫 template 以及 data,更加方便使用

而在小程序中,自定義組件 Toast 也有同樣的問題[wx.showToast() 這個 api 只有 success/loading 兩種方式,無法滿足我們的需求]

原版是這樣…

<td-toast is-show="{{$toast.show}}" icon="{{$toast.icon}}" text="{{$toast.text}}"></td-toast>
{
 //data
 data:{
   $toast: {
     show: false,
     text: '',
     icon: ''
   }
 },
 //methods
 toast(text, icon = '', times = 2000, cb) {
   //...省略其他邏輯
   this.setData({
     $toast: {
       show: true,
       text: text,
       icon: icon
     }
   });
   //...省略其他邏輯
 },
 clearToast() {
   //...省略其他邏輯
   this.setData({
     $toast: {
       show: false,
       text: '',
       icon: ''
     }
   });
   //...省略其他邏輯
 }
}


<div class="md-section-divider"></div>

 

問題

我們的業(yè)務(wù)基本上每個頁面都會有 toast。這意味著每個 page 都得去定義wxml、data、toast()、clearToast() ?
我們需要個 wx.showToast() 一樣的方式去調(diào)用

方案

我們先處理wxml的問題,發(fā)現(xiàn)這個問題并不好解決,我們沒有辦法動態(tài)的創(chuàng)建標(biāo)簽。
那么只好先采用莽夫方案了: 創(chuàng)建一個 plugin.wxml(用來存放所有的全局公用模板)
每個page 都會 include 這個 plugin.wxml

//plugin.wxml

<!-- 目前只有toast -->
<td-toast is-show="{{$toast.show}}" icon="{{$toast.icon}}" text="{{$toast.text}}"></td-toast>


<div class="md-section-divider"></div>

 

接下來處理js 的問題,來個 plugin.js 來做plugin.wxml對應(yīng)的數(shù)據(jù)邏輯

//plugin.js

export default {
 $data: {
   $toast: {
     show: false,
     text: '',
     icon: ''
}
},
//methods
 toast(text, icon = '', times = 2000, cb) {
//...省略其他邏輯
this.setData({
     $toast: {
       show: true,
       text: text,
       icon: icon
}
});
//...省略其他邏輯
},
 clearToast() {
//...省略其他邏輯
this.setData({
     $toast: {
       show: false,
       text: '',
       icon: ''
}
});
//...省略其他邏輯
}
};


<div class="md-section-divider"></div>

 

能看出來其實plugin.js就是page的內(nèi)容,那下一步需要做的就是吧plugin.js的內(nèi)容注入到每個page中。

這時候嘗試著定義了一個inject.js

import plugin from './plugin';
function inject(page) {
for (let key in plugin.$data) {
if (Object.prototype.hasOwnProperty.call(plugin.$data, key)) { //過濾
     page.data[key] = plugin.$data[key];
}
}
const obj = Object.assign({}, plugin, page);
return obj;
}

export default (page) => {
return inject(page)
}


<div class="md-section-divider"></div>

 

這時候有了個 inject方法能把 plugin.js合并到page了。
只需要在page里加上inject方法就好了

// pages/demo/index.js
import inject from './../plugin/inject';
Page(
// 注入 plugin
 inject({
   data: {},
   onLoad: function(options) {},
   onReady: function() {},
   onShareAppMessage: function() {
// plugin.js中定義的 toast()
this.toast('分享')
}
})
);


<div class="md-section-divider"></div>

 

到這里就差不多基本完成了,當(dāng)然還有一些問題,比如說json配置中的 usingComponents 字段
這些問題目前也沒有找到好的解決方式,
目前正在寫一個構(gòu)建工具來自動處理 json配置,當(dāng)然主要是用來單文件開發(fā),處理不能使用 npm 的問題,附加支持postcss

這是題外話了,上面的inject 我們還能用來做一些其他的事情,比如對page的hook

例如:增加onLogin回調(diào)

//plugin.js
export default {
 $data: {
   $toast: {
     show: false,
     text: '',
     icon: ''
}
},
/**
  * 生命周期函數(shù)--監(jiān)聽onLoad
  */
 loadHooker: function(onLoad, onLogin) {
return function(option) {
// 不管三七二十一 先調(diào)了onLoad再說
     onLoad.call(this, option);
const app = getApp();
if (app.globalData.userInfo) { // 已經(jīng)登錄 
       setTimeout(()=>{
this.globalData = app.globalData;
if (onLogin) { 
           onLogin.call(this, option, app.globalData.userInfo);
}
},0)
} else { //沒有登錄 異步=》onLogin
       app.userInfoReadyCallback = json => {
this.globalData = app.globalData;
if (onLogin) {
           onLogin.call(this, option, app.globalData.userInfo);
}
};
}
};
},
 toast(text, icon = '', times = 2000, cb) {
//...省略其他邏輯
},
 clearToast() {
//...省略其他邏輯
}
};


//inject.js
import plugin from './plugin';

function inject(page) {
for (let key in plugin.$data) {
if (Object.prototype.hasOwnProperty.call(plugin.$data, key)) { //過濾
     page.data[key] = plugin.$data[key];
}
}
//新回調(diào)
const onLoadHooker = plugin.loadHooker(page.onLoad, page.onLogin);
const obj = Object.assign({}, plugin, page);
 obj.onLoad = onLoadHooker;// hookonLoad
return obj;
}

export default (page) => {
return inject(page)
}


<div class="md-section-divider"></div>

 

如果fetch接口依賴于用戶信息

Page(
 inject({
   data: {},
   onLoad: function() {},
   onLogin: function(options, userInfo) {
this.toast('拿到用戶信息')
this.fetch(userInfo.openid);
}
})
)

 

好吧 第一次寫這種文章 挺生疏,有什么錯誤或者有更好的思路希望能指出



易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://22321a.com/wxmini/doc/course/24378.html 復(fù)制鏈接 如需定制請聯(lián)系易優(yōu)客服咨詢:800182392 點擊咨詢
QQ在線咨詢