preface
The Toast or Message component is something that almost every project uses.
In Vue and React, they are components, and we tend to use these types of components to handle the global Api, so as to avoid having to write templates and data on every page and make it easier to use
Wx.showtoast () API has only success/loading two ways, which cannot meet our requirements.
Here’s the original…
<td-toast is-show="{{$toast.show}}" icon="{{$toast.icon}}" text="{{$toast.text}}"></td-toast>
Copy the code
{
//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: ''
}
});
//...省略其他逻辑
}
}
Copy the code
The problem
Our business basically has toasts on every page. Does this mean that each page has to define WXML, data, toast(), clearToast()? We need a wx.showtoast () call
plan
We started with the WXML problem and found that it was not easy to solve. There was no way to create tags dynamically. WXML: create a plugin.wxml(to store all global common templates) and include the plugin.wxml in each page
//plugin.wxml
<! - currently only toast - > < td - toast is - show = "{{$toast. Show}}" icon = "{{$toast. Icon}}" text = "{{$toast. Text}}" > < / td - toast >Copy the code
Next deal with the js problem, to plugin.js to do plugin.wxml corresponding data logic
//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: ''
}
});
//...省略其他逻辑
}
};
Copy the code
Plugin.js is the content of the page, so the next step is to inject the content of plugin.js into each page.
This time we try to define an 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)
}
Copy the code
There is an inject method that adds plugin.js to the page. Just add inject method to the page
// pages/demo/index.js import inject from './.. /plugin/inject'; Page(// inject plugin inject({data: {}, onLoad: function(options) {}, onReady: function() {}, onShareAppMessage: Function () {// plugin.js () this.toast(' share ')}}));Copy the code
There are still some problems, such as the usingComponents field in JSON configuration. There is no good solution to these problems. Currently, we are writing a build tool to automatically handle JSON configuration, mainly for single file development. Handle NPM issues with additional support for PostCSS
That’s beside the point, we also use inject to do some other things, such as hook to page
For example, add the onLogin callback
//plugin.js export default { $data: { $toast: { show: false, text: '', icon: }}, /** * lifecycle function -- listen onLoad */ loadHooker: Function (onLoad, onLogin) {return function(option) {// onLoad. Call (this, option); const app = getApp(); If (app.globaldata.userinfo) {setTimeout(()=>{this.globalData = app.globalData; if (onLogin) { onLogin.call(this, option, app.globalData.userInfo); }} else {0} / / not login asynchronous = "onLogin app userInfoReadyCallback = json = > {this. GlobalData = app. GlobalData; if (onLogin) { onLogin.call(this, option, app.globalData.userInfo); }}; }}; }, toast(text, icon = '', times = 2000, cb) { //... Omit other logic}, clearToast() {//... Omit other logic}}; //inject.js import plugin from './plugin'; function inject(page) { for (let key in plugin.$data) { if (Object.prototype.hasOwnProperty.call(plugin.$data, {// filter page. Data [key] = plugin.$data[key]; }} // New callback 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) }Copy the code
If the FETCH interface depends on user information
Page( inject({ data: {}, onLoad: function() {}, onLogin: Function (options, userInfo) {this.toast(' get userInfo ') this.fetch(userinfo.openid); }}))Copy the code
Ok, this is a strange article to write for the first time. Any mistakes or better ideas to point out