Dear friends, hello. I am a MilFun. 👻 👻 👻

I have to say that this project has been done for a long time. I met some problems in the development process, so I will share them with you. In all aspects of comprehensive consideration, I abandoned the major multi-terminal development framework, the use of native small program framework for development.

Predecessors dig pits, posterity suffer, I wish you as soon as possible to become daniu! 👻 👻 👻

👻 Custom dynamic Tabbar navigation bar

In the default applets, to define tabbar, you need to configure the following JSON in app.json:

"tabBar": {..."list": [{"text": "Home page"."iconPath": "/public/images/index.png"."selectedIconPath": "/public/images/index-act.png"."pagePath": "pages/job/index"}... ] }Copy the code

Once configured, it cannot be modified. You can call setTabBarItem to set the text and image path of the button. You cannot dynamically set the forward address or tabbar number.

The solution

We need to create a new middle page to control all tabbars, and write all the pages that tabbar is associated with as components, so that we can just write a tabbar style fix at the bottom of this page, and click on different tabs to display different components.

Json file

{
  "usingComponents": {
    "home" : "/pages/job/index"./ / home page
    "company" : "/pages/company/company"./ / the company
    "message" : "/pages/chat/index"./ / message
    "mine" : "/pages/mine/index"./ / to me
    "tabbar" :  "/milfun/widget/custom-tab-bar".// Customize the tabbar component}}Copy the code

WXML file

<! In WXML, set the page as a component -->
<home wx:if="{{activeTab == 'home'}}">Home page</home>
<company wx:if="{{activeTab == 'company'}}">The company</company>
<message wx:if="{{activeTab == 'message'}}">The message</message>
<mine wx:if="{{activeTab == 'mine'}}">my</mine>

<! -- WXML, custom tabbar component
<tabbar list="{{tabList}}" bindmytab="tabChange"></tabbar>
Copy the code

Js file

Page({
  data: {
    activeTab:'home'	// company, message, mine
  },
  onLoad: function (options) {
    let tmp = 1;	// Tabbar is used to control the display of different scenarios
    if( tmp === 1) {// Display the first set of tabbars
      this.setData({
        tabList:[
          {
            "name": "..."."text": "..."."iconPath": "..."."selectedIconPath": "..."."pagePath": "..."},... ] })}else{	// Display the second tabbar
		this.setData({
	        tabList] : [{},... }}}})Copy the code

The above shows the middle page writing method, then how to change the normal page into a component page?

Change the page to component writing

The main difference is that the js file inside the writing method is different, so we only look at the JS part:

Normal writing
Page({
  data: {},onLoad: function (options) {},onShow: function (options) {},func1:function(e){
    console.log(e)
  },
  func2:function(e){
    console.log(e)
  },
})
Copy the code
Components are written
Component({
  options: { // To use global CSS styles
      addGlobalClass: true,},data: {},
  /* * called when the component is created, equivalent to onLoad */ above
  attached: function (options) {},/* * Internal component method, equivalent to the custom method */ above
  methods: {
	func1:function(e){
	    console.log(e)
	},
	func2:function(e){
	    console.log(e)
	},
  }
})
Copy the code

This allows us to implement dynamic Tabbar, which allows us to modify tabList data at any time.

👻 The input box pops up and slides on the page

Our solution to this problem is to manually set the position of the input box.

Js file

// Input box gets focus
foucus:function (e) {
   this.setData({typerHeight: e.detail.height})
},
// Input box loses focus
blur:function () {
   this.setData({typerHeight: 0})},Copy the code

WXML file

<view class="tc-board"  style="bottom:{{typerHeight}}px" >.</view>
Copy the code

This way, when the input field gets focus, it will get the height of the keyboard, and then set the bottom view style of the input field to the height that you get, and it will fit perfectly on top of the input field. When the input box loses focus, the height is set to 0 and the input box view returns to the bottom of the page.

👻 Asynchronous request callback + Token authentication

To avoid writing verbose nested if else statements or callback functions in your business

/ / method
onLoad:function (e) {
   / / if nested
   if() {if() {if() {// do something }}}// Callback trap
   func1(data,func(){
		func2(data,func(){
			func3(data,func(){
				// do something})})})},Copy the code

What I did was add a promise to the method, for example 🥗 :

Public function JS file

/** * Unified POST request interface *@param {*} E "url, data, contentType, noOuth" * /
function post(e){
  // The token is stored in the cache and retrieved as needed
  let header = { 'Content-Type': contentType, 'Authorization':'Bearer ' + getCache('accessToken')}// Encapsulate it in promise
  return new Promise(function (resolve, reject) {
    wx.request({
      url:  config.domain + e.url , // domain is placed in config
      data:e.data,
      method: 'POST'.header: header,
      success: res= > {
        // console.log(res)
        if(res.data.code == 200 ){
          resolve(res.data)		// Request successful, data returned
        }
        else{
          wx.showToast({
              title: res.msg,
              icon: 'none'.duration: 1500}); reject(res.data.msg)// Request error, display error}},fail: res= > {	// The request failed
        wx.showToast({
          title:  'Request sending failed'.icon: 'none'.duration: 1500}); }})})}Copy the code

Page JS file

/ / method
onLoad:function (e) {
   fun.post({ url:'... '.data: {... } }) .then(res= > console.log(res) )		/ / step one
   .then( res= > console.log(res) )		/ / in step 2
   .then( res= > console.log(res) )		/ / step 3
   .catch( res= > console.log(res) )	// Catch exceptions
},
Copy the code

It’s clear, elegant and awesome!

👻 Unified interface management

With the above POST interface, we will have a lot of request interfaces in the development. If they are all written in the page, it will be difficult to manage. If there is any modification, we will have to find the past page by page, which is quite troublesome.

Create a new JS in the module directory to store all interface information. Why under modules? Considering that there may be different subcontracting, it will be too much if they are all written together, and it will bring inconvenience to management if they are divided into too many details, please operate according to the specific project.

The API interface manages files in a unified manner

** url: just URL * contentType: default:false(use urlencoded) or true(use json) * noOuth: ** * coded * contentType: default:false(use urlencoded) or true(use json) * noOuth: default:false( hase Authorization ) or true( no Authorization ) */
const constApi = {
	// Get user information
	getUserInfo : {		// Define the name of the interface call
		url: 'api/v1/userinfo'
	},
	// Get user Settings
	getUserSetting: {
		url: 'api/v1/usersetting'.outh:true	// Authentication is required}}/** ** call * on the external interface@param {*} Name Key * in the API file@param {*} Data Data to post */
const http = async function(key,data){
    let api = constApi[key];
    let response = await fun.post({
        url:api.url,
        data:data,
        contentType:api.contentType,
        outh:api.noOuth
    })
    return response
}

export default http
Copy the code

Method of use

// Import the API file
import Api from './api-index.js'

onLoad:async function (e) {
	A / / usage
	Api('getUserInfo ', {userId:1.userPwd:123456. }) .then(res= > console.log(res) )
	...

	2 / / usage
	let tmp = await Api('getUserInfo', {... })this.setData({ list: tmp })
},
Copy the code

If the interface is changed, or the address is changed, you don’t have to go around looking for pages that use the interface and change it one by one. It only needs to be modified and managed in api-index.js.

This time, I will share these with you, and I will continue to share useful development experience with you. The pit that has been climbed is not to climb again.

Thank you! 👻 👻 👻