Since the runtime standard for applets has recently been reworked, I will write a separate article to clarify the important features of applets

The ultimate goal is to build a tree, put all this information into the tree, and finally get a subset of wechat

Json configuration:

  1. app.json
{
  "pages": ["pages/index/index"."pages/logs/index"].// Matches the first one by default
  "window": {
    "navigationBarBackgroundColor": "#ffffff".// Top navigation bar background color
    "navigationBarTextStyle": "black".// Top navigation bar text color
    "navigationBarTitleText": "Wechat Interface Function Demonstration".// Top navigation bar text content
  },
  "tabBar": {
    "list": [{"pagePath": "pages/index/index".// Page path
        "text": "Home page".// The fine print below
        "iconPath": "img/news.svg"./ / the default diagram
        "selectedIconPath": "img/news-sel.svg" // The selected image
      },
      {
        "pagePath": "pages/logs/logs"."text": "Log"}},"usingComponents": { // Public components
    "component-tag-name": "path/to/the/custom/component" 
  },
  "useExtendedLib": { // Reduce precompilation
    "kbone": true."weui": true
  },
  "debug": true.// Enable debug mode to generate useful logs
  "version": "v3".// You can use this field for version control
}
Copy the code

That’s what I think is important in app.json. In addition to supporting these fields, we need to deal with some minor details

1.Tabbar ICONS need to support SVG, PNG bitmaps will be distorted2.UseExtendedLib can be mademoduleFederation, to reduce precompilation3.Add a version field for version controlCopy the code
  1. [page].json
{  
  "navigationBarBackgroundColor": "#ffffff"."navigationBarTextStyle": "black"."navigationBarTitleText": "Wechat Interface Function Demonstration"."enablePullDownRefresh" : "true".// Start the pull-down refresh and trigger the onPullDownRefresh callback
  "onReachBottomDistance": 50.// The distance to trigger the onReachBottom callback
  "usingComponents": { // Page component
    "component-tag-name": "path/to/the/custom/component" 
  },
  "disableScroll": "true" // Disable the IOS bounce-back and onPageScroll methods
}
Copy the code

The page field is much simpler, with the exception of a few window fields that override app.json, only the useComponents field is important

A few things to watch out for:

1.App. json also supports uniform configuration of the fields listed above2.The drop-down refresh, bottom, and Scroll configurations are all specific to the page and need to be distinguished from the scroll viewCopy the code

2. App interface

  1. App()
App({
  onLaunch (options) {
    // When the app starts
  },
  onShow (options) {
    // When app is activated
  },
  onHide () {
    // App is inactivated
  },
  onError (msg) {
    // Error collection
  },
  globalData: {}, // globaldata
})
Copy the code
  1. getApp()
const app = getApp()
console.log(app.globalData)
Copy the code

Applets don’t have a lot of stuff on the App instance, but some tool components are still attached

Page interface

  1. Page()
Page({
  data: {
    count: 0
  },
  onLoad: function(options) {
    / / page load
  },
  onShow: function() {
    / / page show
  },
  onReady: function() {
    / / page is ready
  },
  onHide: function() {
    / / hide the page
  },
  onUnload: function() {
    / / page unload
  },
  
  onPullDownRefresh: function() {
    // Pull down the refresh callback
  },
  onReachBottom: function() {
    // Bottom correction
  },
  onShareAppMessage: function () {
    // Basically useless sharing
  },
  onPageScroll: function() {
    // scrollTo
  },
  onResize: function() {
    // Resize on PC
  },
  onTabItemTap(item) {
    // TAB tap callback
    console.log(item.index)
    console.log(item.pagePath)
    console.log(item.text)
  },
  // Common events
  viewTap: function() {
    this.setData({
      text: 'Set some data for updating view.'
    })
    // serialize to jSON-patch
    this.setData({
      "a.b.c[0]": 'Set some data for updating view.'})}})Copy the code

There are many events in Page, but they are mainly divided into three categories:

1.Life cycle -> in general2.Pull down, hit bottom, scroll callback3.Data, setData, normal eventsCopy the code

One of the most overlooked is the JSON-patch format of this.setData, which is the basis for the later custom component observer

  1. getCurrentPages()
const stack = getCurrentPages()
Copy the code

The page stack

This is a stack that you get with getCurrentPages, where the first element is the home page and the last element is the current page

API Stack behavior
load Home page into the stack
wx.navigetTo Into the stack
wx.redirectTo Top of stack replacement
wx.navigateBack Cycle out of the stack
wx.switchTab Clear the stack, and then the target page is pushed
reload Clear the stack, and then the current page is pushed

The above stack behavior is related to the lifecycle, but in general, as long as the page is in the stack, the lifecycle goes show and hide, or load and unload if it is not in the stack

We’ll sort this out later

4. Component interface

  1. Component()
Component({

  behaviors: [].properties: {
    myProperty: { / / the property name
      type: String.value: ' '
    },
    myProperty2: String // A simplified definition
  },

  data: {}, // Private data that can be used for template rendering

  lifetimes: {
    // Lifecycle
    attached: function () {},moved: function () {},detached: function () {},},pageLifetimes: {
    // The lifecycle of the page on which the component is located
    show: function () {},hide: function () {},resize: function () {},},methods: {
    onMyButtonTap: function(){
      this.setData({
        'A[0].B': 'myPrivateData'})},triggerParentEvent(){
      this.triggerEvent('myevent', myEventDetail, myEventOption)
    }
  }
  
  observers: {
    "A[0].B": function(newVal, oldValue) {
        console.log(newVal)
    }
  }
})
Copy the code

Component is bolder than Page in terms of properties and observers

Properties and data share the same template scope. In general, they cannot have the same key. In wechat, Data overwrites props, while in VUE, an error is reported

I prefer the VUE treatment

observers

Observers are the same as the previous Watch, but with much improved performance, and I suspect copy-on-write using Proxy

It is worth mentioning that this piece directly compares the JSON-patch of setData and the Json-patch of observer

Json-patch not only improves the performance of observer, but also improves the performance of setData thread delivery

  1. Behavior()
const b = Behavior({
  behaviors: [].properties: {
    myBehaviorProperty: {
      type: String}},data: {
    myBehaviorData: {}},attached: function(){},
  methods: {
    myBehaviorMethod: function(){}}})Copy the code

It takes the same parameters as custom components and generally has three merge strategies:

1.Queues, such as lifecycle -> Behavior -> Component -> Child -> parent -> Front -> back2.Merge objects such as data, observer -> Component -> Behavior -> parent -> Child -> back -> front3.Replace, event, Properties -> rules same2
Copy the code

It is worth mentioning that the order of the life cycles here is bubbling, so let’s go on to tease out the life cycles

Life cycle

This should be mentioned separately because applets are two-threaded, and Page, Component, and even Behavior are lifecycle dependent

  1. Page life cycle, this is the simplest:
Onload: logic layer loaded, stack onready: view layer to load, equivalent to didmount onshow: native side show -- -- -- -- | onunload: Uninstall the logic layer, the stack | onshow and onhide switch back and forth | onhide: native hidden side -- -- -- --Copy the code

The onshow/onhide cycles are the same as Berial’s mount/unmount cycles

They switch back and forth, and IN Berial I used a stateful queue to do this

  1. Component lifecycle

Wechat’s Component is a view-only implementation, and its lifecycle is originally web-Component lifecycle, so this thing…

Attached: The render layer is loaded, equivalent to didmountdetachedThe render layer is unmounted, equivalent to didunmountCopy the code
  1. The order of the life cycle between the father and the child

In React, the life cycle sequence of the father and son is diving and then bubbling

<cmp-a>
  <cmp-b>
    <cmp-c></cmp-c>
  </cmp-b>
</cmp-a>

cmp-a - componentWillMount
cmp-b - componentWillMount
cmp-c - componentWillMount
cmp-c - componentDidMount
cmp-b - componentDidMount
cmp-a - componentDidMount
Copy the code

The order of the applet is the same, its attached equivalent to componentDidMount, and naturally also from child to parent

Fourth, the WXS

This thing is in the view layer, I guess it emulates a CJS standard and runs with New Function

There’s nothing to say. It’s like…

Building data Structures

Basically, that’s it, and once you’ve sorted everything out, you can meditate on what the structure looks like

First it must be a tree, and then it looks something like this:

App
  - [ // this is a stack
    - Page1
       - [
         - Component1
           -[
            - Component3
           -]
         - Component2
       - ]
    - Page2
  - ]
  
1.The overall structure is a tree2.Pages is a stack3.Behaviors is a tree4.The life cycle is a queueCopy the code

With this structure, it is easy to fill cases, such as:

export function getCurrentPages(){
  reutn app.pageStack.values()
}
Copy the code

One line of code, aha

After this cleaning, I have a better understanding of the overall architecture of applets, which is equivalent to a low-profile version of VUE

I can’t reveal the implementation details, but I think I can build a satisfactory structure

Looking at the sky, the first time to write such a long article, feel really can not gather together ten thousand words, forgive me, we all have to make a living duck……