Hello everyone, I am South Su, the chief pit fill officer of @it · Flathehead Brother Union. Today I would like to share with you a small program project recently done by our company. Some good summary and pit encountered in the process, I hope IT can bring some convenience to other siege lions, and I hope the boss will give you a raise after finishing IT

Today is the first day of the Mid Autumn Festival, I woke up very early in the morning of the holiday. I don’t know why. Maybe it is because I found a small bug on the way back from the project launched by the company last night, and I felt a little worried

The above pure for bullshit, now begin to install in a serious manner force, please fasten the safety belt, the middle process may drive, please pay attention to safety !!!!!

In a recent project, after communicating with my team mates, I used the WEPY framework instead of using the native one. The native one of the small programs is… We all know that using WEPY framework brings convenience to ourselves as well as a lot of pits. However, even so, I still cherish the mentality of “even if you abuse me thousands of times, I will still treat you like my first love” to complete the project seriously

toast

1.
toastAs we all know, the official API wx. ShowToast does not meet our requirements, because it only supports “success” and “loading” states, and “title text can display up to 7 characters in length”

Wx. showModal({title: 'success', icon: 'success', duration: 2000}) wx.showModal({title: 'indication ', content: 'This is a modal popover ', SUCCESS: Function (res) {if (res.confirm) {console.log(' User click OK ')} else if (res.cancel) {console.log(' User click Cancel ')}})

The text of the content of wx. Showmodal will not be in the center (now I am not sure whether there is an extension, you can set it). I vaguely remember once I almost quarreled with the product manager because of the problem, and I asked the text to be in the center. It takes two hours to center the text?? Two hours?? Two hours?? Then I decided to encapsulate a Toast component of my own. Here is part of the core code

<template lang="wxml"> <view class="ui-toast {{ className }}" hidden="{{ ! visible }}"> <view class="ui-toast_bd"> <icon wx:if="{{ options.icon}}" type="{{ options.icon }}" size="40" color="{{ options.color }}" class="ui-toast_icon" /> <view class="ui-toast_text">{{ options.text }}</view> </view> </view> </template> <script> import wepy from 'wepy'; const __timer__ =1900; }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} `success`, icon: `success`, className: `ui-toast-success`, }, { type: `cancel`, icon: `cancel`, className: `ui-toast-cancel`, }, { type: `forbidden`, icon: `warn`, className: `ui-toast-forbidden`, }, { type: `text`, icon: ``, className: `ui-toast-text`, }, ], timer:null, scope: `$ui.toast`, animateCss:'animateCss', className:'', visible:! 1, options:{ type: ``, timer: __timer__, color: `#fff`, text: ` completed `,}} / * * * * / __setDefaults__ default parameters () {return {type: ` success `, timer: __timer__, color: # ` FFF `, text: 'Completed', success() {}, }} /** * SetVisible__ (className = 'UI-Animate-Fade-In') {this. className = '${this.animateCss}} /** * SetVisible__ (className =' UI-Animate-Fade-In ')} ${className}`; this.visible = ! 0; this.$apply(); } /** * Set elements hidden */ __setHidden__(className = 'ui-animate-fade-out', timer = 300) { this.className = `${this.animateCss} ${className}`; this.$apply(); setTimeout(() => { this.visible = ! 1; this.$apply(); }, Timer)} /** * Display Toast component * @Param {Object} opts configuration item * @Param {String} opts. Type prompt type * @Param {Number} opts * @param {String} opts.color * @param {String} opts.text * @param {Function} opts.success callback Function after closing */ __show__(opts = {}) { let options = Object.assign({}, this.__setDefaults__(), opts) const TOAST_TYPES = this.list; TOAST_TYPES.forEach((value, key) => { if (value.type === opts.type) { options.icon = value.icon; options.className = value.className } }) this.options = options; if(! this.options.text){ return ; }; clearTimeout(this.timer); this.__setVisible__(); this.$apply(); this.timer = setTimeout(() => { this.__setHidden__() options.success&&options.success(); }, options.timer); } __info__(args=[]){ let [ message, callback, duration ] = args; this.__show__({ type: 'text', timer: (duration||__timer__), color: '#fff', text: message, success: () => {callback&&callback()} }); } __success__(args=[]){ let [ message, callback, duration ] = args; this.__show__({ type: 'success', timer: (duration||__timer__), color: '#fff', text: message, success: () => {callback&&callback()} }); } __warning__(args){ let [ message, callback, duration ] = args; this.__show__({ type: 'forbidden', timer: (duration||__timer__), color: '#fff', text: message, success: () => {callback&&callback()} }); } __error__(args){ let [ message, callback, duration ] = args; this.__show__({ type: 'cancel', timer: (duration||__timer__), color: '#fff', text: message, success: () => {callback&&callback()} }); {} __showLoading__ (options) wx. ShowLoading ({title: (options && options. The title | | "load"),}); } __hideLoading__(){ wx.hideLoading(); } onLoad(){ this.$apply() } } export default Toast; </script>
<template> <view class="demo-page"> <Toast /> <Modals /> </view> </template> <script> import wepy from 'wepy' import Toast from '.. /components/ui/Toast' import Modals from '.. /components/ui/Modals' import {fetchJson} from '.. /utils/fetch'; export default class Index extends wepy.page { config = { navigationBarBackgroundColor: "#0ECE8D", navigationBarTextStyle:"white", navigationBarTitleText: '' } components = { Toast: Toast, Modals: Modals} methods = {tapToast(){this.$invoke("Toast","__success__",[' You have successfully delivered, thank you for your support ']); } } } </script>

Storage

2,
Storage(storage) in the front end of the way we store, cookies, localStorage, sessionStorage and so on, the features are not clear, small program as we all know, data storage can only call wx.setStorage, wx.setStorageSync, The equivalent of H5 localStorage, and localStorage is not expired, this is known to all, and in many interviews, the interviewer will ask this question, how to make localStorage like a cookie, only save two hours, two days, or even only save two minutes? This is the way we’ve been doing it in our project, and it’s also useful in our mini-program:

class storage { constructor(props) { this.props = props || {} this.source = wx||this.props.source; } get(key) { const data = this.source, Timeout = (data. GetStorageSync (` ${key} __expires__ `) | | 0) / / expire if (Date. Now () > = timeout) {this. Remove (key) return; } const value = data.getStorageSync(key) return value} The expiration time (minutes) set (key, value, the timeout) {let data = this. Source let _timeout = the timeout | | 120; data.setStorageSync(key,(value)); data.setStorageSync(`${key}__expires__`,(Date.now() + 1000*60*_timeout)); return value; } remove(key) { let data = this.source data.removeStorageSync(key) data.removeStorageSync(`${key}__expires__`) return undefined; } } module.exports = new storage();

Feel very simple, in fact, everyone looked after all “oh, that can also like” see, it’s just a thought, is a tip, every time when stored in an aging time stamp at the same time, and before to get the data, first compared with the current time, if less than the current time has expired, returns an empty data directly.

Interface API

3,
Interface APIThe maintenance in no
nodejsBefore, it seems that the front-end for processing in different environments with the corresponding API, do more is to use the domain name for judgment, of course, some of the advanced practice, back-end when page rendering, save a variable into the cookie or the output on the page of a global API variable (based on without the separation of front and back side). To small program is also the case, each time to manually change the environment, then a project may have a different business, to call a different domain name
api, and there are different environment distinction, how to maintain it better?

// exports = {wabApi:{host:"https://dev-ali.southsu.com/XX/api/**",}, // exports = {wabApi:{host:"https://dev-ali.southsu.com/XX/api/**",}, questionApi:{ host:"https://dev-ali.bin.com/question/api/**/question", }, mockApi:{ host:"https://easy.com/mock/594635**c/miniPrograms" }, inWelApi: { host: "https://dev.**.com/Wab/api/escene/v2" } };
import dev from './env/dev'; // import uat from './env/pre'; // import PRD from './env/ PRD '; Var ENV = "PRD "; //'dev | uat | prd'; let _base_ = { dev, uat, prd }[ENV]; var config = { ENV, baseAPI:{... _base_, env: env}, appID:"wx*****b625e", // company account (index) appID isAuthorization:true, 'logId': authorization 'gVDSMH**** haas4qssotb-gzgzohsz ', 'logKey': 'pxFOg jjn3jyjovr ',, 'z**Insu' // survey number}; export const __DEBUG__ = (ENV! ="prd"); export default config;
Import wepy from 'wepy' import _login_ from './login'; import config,{__DEBUG__} from './config'; import 'wepy-async-function'; Export const fetchJSON = (options)=>{/* * Public data processing before request * @Param {String} url request address * @Param {String} Type request Type * @ Param {String} sessionID user userToken * @param {Boolean} openLoad on Load tooltip, default on, true- on, Components/UI /Toast * @Param {Object} header Reset the request header * @Param {Boolean} isMandatoryWhether to force user authorization to obtain user information */ StaticToast = getCurrentPages()[getCurrentPages().length-1]; let { url,openLoad=true, type, data={},header={}, ... others } = options||{}; let sessionId = (Storage.get(__login__.server+'_userToken')||""); /*Start */ var regExp = /\/(.*?) \//, hostkey = url.match(regExp)[1]; let baseUrl = config.baseAPI[hostkey].host; url = url.replace(regExp, '/'); /*End */ __DEBUG__&&console.log('#--baseUrl:', baseUrl); __DEBUG__ && console. The log (' # - request address: '` ${baseUrl} ${url} `); __DEBUG__ && console. The log (' -- -- -- -- -- -- -- -- -- -- line -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- '); openLoad&&StaticToast.__showLoading__(); return new Promise((resolve, reject) => { return wepy.request({ url:`${baseUrl}${url}`, method:(type || 'POST'), data, header:{ "t9oken":sessionId, 'content-type': 'application/json', // 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', ... header }, success:(res)=>{ StaticToast.__hideLoading__(); return resolve(resHandler(res,options)); }, error:(err,status)=>{ StaticToast.__hideLoading__(); return reject(errorHandler(err,options,err.statusCode)); }}); })

Business invocation example:

/ / request finally get to https://easy.com/mock/594635 * * c/miniPrograms/service/XXX (domain different environment is different, FetchJSON ({type:"post", // url:"/mockApi/service/XXX", data:{name:" sunan "}, Success :res=>{console.log(' Hello, I'm Sunan ',res)}});

It’s time to fill the pit

4, to fill a hole time, wepy framework of each component in the life cycle of a callback onload, as long as it is introduced the components, did whatever you view rendering, he can perform, cause some business logic without it also carried out to produce abnormal (of course for the < applet > sure that I’m not a pan back ~ ^ ~), detailed see link:
https://github.com/Tencent/we… ,
https://github.com/Tencent/we…I don’t know if anyone can solve it

rich-text

5, rich-text, a small program component, although there is a little bit of use, but have to say what is it for ah? Other I will endure, A label, A label ah, attribute no, that also it what use ah, you do not want me to jump, I also need to use you? B, I, SPAN, EM… Which one can’t I use? Don’t know whether this component design played the brain by a donkey, may god bless, I’m here to scold him, don’t be seen, haha ~), and the content of the business needs the background configuration with links, can’t, come on, make it, make it to the dead, all tergiversation is your excuse technology low (you see, you see, how others can jump, How do others do it? Give me a cut and I can chop the product into crumbs), hence the filling pit behind:

<template> <view class="test-page"> <button @tap="cutting"> </button> <view wx:if="{{result.length>0}}" class="parse-list"> <view class="parse-view" wx:for="{{result}}" wx:key="unique" wx:for-index="index" wx:for-item="items"> <block wx:if="{{items.children&&items.children.length}}"> <block wx:for="{{items.children}}" wx:for-item="child" > <text wx:if="{{child.type == 'link'}}" class="parse-link" @tap="goToTap({{child.link}})">{{child.value}}</text> <text class="parse-text" wx:else>{{child.value}}</text> </block> </block> <text class="parse-text" wx:else>{{items.value}}</text> </view> </view> <Toast /> <Modals /> </view> </template> <script> import wepy from 'wepy' import { connect } from 'wepy-redux' import Toast from '.. /components/ui/Toast' import Modals from '.. /components/ui/Modals' import {fetchJson} from '.. /utils/fetch'; import Storage from ".. /utils/storage"; function wxHtmlParse(htmlStr=''){ if(! htmlStr){ return [] }; const httpExp =/(http:\/\/|https:\/\/)((\w|=|\? |\.|\/|\&|-)+)/g; // const aExp=/<a.[^>]*? >([(^<a|\s\S)]*?) <\/a>/ig; // let cuttingArr = htmlStr. Split (/[\n]/); let result = []; / / have a tag HTML processing let itemParse = (itemHtml = ' ') = > {let itemCutting = itemHtml. Split (aExp) | | []; let itemResult = []; for(var i = 0; i<itemCutting.length; i++){ let _html = itemCutting[i]; if(_html! ==''){ let itemData = { value:_html, type:'text', class:"parse-text" }; let matchTag = itemHtml.match(aExp)||[]; If (matchTag.length){let ItemIndex = matchTag.findindex ((k,v)=>(k.Indexof (_html)! = = 1)); if(itemIndex>=0){ let link = matchTag[itemIndex].match(httpExp)[0]; itemData.type = 'link'; itemData.link = link; itemData.class = "parse-link"; }; }; itemResult.push(itemData) } }; return itemResult; }; cuttingArr.map((k,v)=>{ let itemData = {type : "view",class:"parse-view"}; let isATag = k.match(aExp); if(isATag){ itemData.children = itemParse(k); }else{ itemData.value = k; }; result.push(itemData); return k; }); return result; }; export default class Index extends wepy.page { config = { navigationBarBackgroundColor: "#0ECE8D", navigationBarTextStyle:"white", navigationBarTitleText: "applet parsing a tag in data"} Components = {Toast: Toast, Modals: Modals} data = {HTML :' Hello, I am South Su, \n Occupation: Front Sieging Lion (also known as Chetu Cub), \n Height: 176cm, \n Gender: Male, \n Sexual Orientation: Female, \n Company: At present, he is working in a business division of Shenzhen branch of an Internet financial company which is a joint venture of Tencent, Ali and Ping An.,\n Profile: Bao Jianfeng is from honing the plum flowers since the bitter cold. He is careful to be himself! , gitHub:https://github.com/meibin08/, \ n interest: running, badminton, climb, music, read a book, share their meager knowledge to help others... \n Other: Want to know more? Add < a href = "https://segmentfault.com/a/1190000010017486/" > 386485473 < / a > communication group, Also can call me < a href = "https://github.com/meibin08/" > 134 xx852xx5 < / a >, ', result:[]} methods = {cutting(e){this.result = wxHtmlParse(this. HTML); console.log(`result`,this.result); this.$apply(); }, } } </script>

PS: complete example source code to ~, feel good remember Star, Star, Watch oh, thank you!

Today’s share here, wrote quite a long time, recently began to try to write a blog, a novice on the road, if there is something wrong in the article, please you great god ax. If you think this article is helpful to you, please remember thumb up, if you think it is good, remember to pay attention to our public number!

Guess you also like:

Interview on the pit, are here ~ you should do the summary of the front end performance optimization! How to set an expiration time for localStorage? How to draw a sports car with CSS3 how to draw understand your 3D Rubik’s Cube? Immutability of SVG Sprites by React official use of immutability sharing!

Author: Su Nan –
Chief pit filling officer


Communication Group: 912594095, Official Account:
honeyBadger8


This article is original and the copyright belongs to the author. Commercial reprint please contact
@it · Flathead AllianceAuthorized, non-commercial reprint please indicate the original link and source.