Westore Documentation

repository·master·Indexed 26 days ago

https://github.com/tencent/westore

An MVVM-based layered architecture framework for WeChat Mini Programs (version 0.1.12). Westore decouples business logic (Models) from the UI (Views) using a mediator (Store) to promote Object-Oriented Programming and Responsibility-Driven Design. It features a Store class for state management and an update mechanism that uses a diffing operation to optimize setData performance by calculating the shortest path for data synchronization.

Tokens
3.7K
Snippets
8
Records
23
Agent score
88%

What's inside westore

  1. Overview of Westore Architecture

    master

    Westore implements an MVVM-like architecture (similar to MVP) designed for WeChat Mini Programs to improve maintainability and testability:

    • Model: Thick layer containing all business/game logic. Models are platform-independent and can be reused in Web, Canvas, or Games without modification.
    • Store: A thin mediator layer that manages the data required by the View and bridges the gap between the View and the Model. It holds the data object used by the View.
    • View (Passive View): A very thin layer (Page or Component) that contains no business logic. It only displays data and forwards user inputs (clicks, swipes, etc.) to the Store.
  2. Install westore via npm

    master

    To use Westore in your WeChat Mini Program project, install the core package using npm. Ensure your environment supports npm as per the official WeChat Mini Program documentation.

    npm i westore --save
  3. Implement a Page Store with the Store class

    master

    Westore uses a Store layer to act as a mediator between the View (Page/Component) and the Model. You should create one Store instance per page. The Store manages the data object and synchronizes changes from platform-independent Models to the View using the update() method.

    import { Store } from 'westore'
    import Counter from '../models/counter'
    import User from '../models/user'
    
    class HomeStore extends Store {
      constructor() {
        super()
        this.data = {
          count: 0,
          motto: 'Hello World',
          userInfo: null
        }
        // Instantiate Models
        this.counter = new Counter()
        this.user = new User({
          onUserInfoLoaded: () => {
            this.syncUserModel()
          }
        })
        this.syncCountModel()
      }
    
      // Sync Model data to the Store's data object and trigger view update
      syncCountModel () {
        this.data.count = this.counter.count
        this.update()
      }
    
      syncUserModel () {
        this.data.motto = this.user.motto
        this.data.userInfo = this.user.userInfo
        this.update()
      }
    
      increment() {
        this.counter.increment()
        this.syncCountModel()
      }
    
      decrement() {
        this.counter.decrement()
        this.syncCountModel()
      }
    
      getUserProfile() {
        this.user.getUserProfile()
      }
    }
    
    module.exports = new HomeStore
  4. Fix NPM build errors in WeChat DevTools

    master

    If you encounter the error 没有找到可以构建的 NPM 包... (No NPM package found to build), you need to configure project.config.json to help the developer tools index your npm dependencies correctly.

    Set packNpmManually to true and define the packNpmRelationList mapping your package.json to your miniprogram directory.

    {
      "packNpmManually": true,
      "packNpmRelationList": [
        {
          "packageJsonPath": "./package.json",
          "miniprogramNpmDistDir": "./miniprogram/"
        }
      ]
    }
  5. Use update in Components

    master

    The update function works identically within WeChat Mini Program Components. You can modify nested properties directly on this.data and call update(this) to trigger the view update.

    const { update } = require('westore')
    
    Component({
      data: {
        count: 1
      },
      methods: {
        plus() {
          this.data.count++
          update(this)
        },
        minus(){
          this.data.count--
          update(this)
        }
      }
    })
  6. Use the update function to replace setData

    master

    Instead of manually constructing paths for this.setData, you can directly assign values to this.data and then call the update function. This provides a more intuitive programming experience and avoids the overhead of manual path construction.

    update(target) takes the Page or Component instance as an argument and synchronizes the changes made to this.data to the view layer.

    const { update } = require('westore')
    
    // In a Page or Component
    getUserInfo(e) {
      this.data.userInfo = e.detail.userInfo
      this.data.hasUserInfo = true
      update(this)
    }
  7. Update View data using update()

    master
    Instead of calling this.setData() manually, Westore allows you to mutate the this.data object directly and then call this.update(). Westore internally performs a diffData operation to calculate the shortest path for the setData call, optimizing performance and providing a more intuitive programming experience.
  8. Configure project settings in project.private.config.json

    master

    The project.private.config.json file is used to define private project configurations for WeChat Mini Programs. Settings defined here will override the same fields in project.config.json. This file is intended for local project modifications that should not be synchronized to the main configuration.

    In the westore-example project, the setting object is used to enable compileHotReLoad.

    {
      "projectname": "westore-example",
      "setting": {
        "compileHotReLoad": true
      }
    }
  9. Configure WeChat Mini Program project settings

    master

    The project.config.json file defines the configuration for the WeChat Mini Program project. Key settings include compilation types, library versions, and various feature flags for the runtime environment.

    Note: This file is specific to the WeChat Mini Program development environment and controls how the project is compiled, audited, and deployed.

    {
      "compileType": "miniprogram",
      "libVersion": "2.19.4",
      "appid": "wxfaf6dad43f57c6bd",
      "projectname": "westore-example",
      "setting": {
        "es6": true,
        "enhance": true,
        "postcss": true,
        "minified": true,
        "useMultiFrameRuntime": true,
        "useApiHook": true,
        "useApiHostProcess": true,
        "minifyWXSS": true,
        "minifyWXML": true
      }
    }
  10. Best practices for setData performance

    master

    When working with WeChat Mini Programs, follow these performance guidelines to avoid UI lag and communication overhead between the Logic Layer (JavascriptCore) and the View Layer (WebView):

    • Frequency: Do not call setData more than 20 times per second.
    • Data Size: Ensure the data being sent (after JSON.stringify) does not exceed 256KB.
    • Redundancy: Only include data in setData that is actually used in the template rendering to avoid unnecessary processing.
    • Background State: Avoid performing setData operations when the page is in the background.
  11. Define a custom Store by extending the Store class

    master

    To create a managed state container in Westore, extend the Store<T> class where T is the interface defining your state shape. You initialize the state in the constructor by assigning an object to this.data. To trigger UI updates in a WeChat Mini Program, call this.update() after modifying state properties.

    Key lifecycle and utility methods:

    • constructor(): Initialize this.data and set up subscriptions.
    • this.update(): Notifies the system to sync the current this.data to the view.
    • this.data: The object holding the reactive state.

    Note: In the example, this.todo.subscribe() is used to react to changes in an external model and subsequently update the store's data and trigger a view update.

  12. Use the Store class to manage state and views

    master

    The Store class is the central management unit for Westore. It maintains a collection of views (pages or components) and their associated data. You can bind views to the store to enable centralized state updates.

    Binding Views

    • Single View Binding: Pass a view object to bind(view). The store will track this view using an internal ID.
    • Keyed View Binding: Pass a key and a view object bind(key, view). This allows you to reference specific views later using the provided key.

    Updating Views

    • Specific View: Call update(viewKey, callback) with the key used during binding to trigger a data update for that specific view.
    • Global Update: Call update(callback) without a key to trigger a data update across all registered views in the store.