mobx-miniprogram-bindings

repository·master·Indexed 42 days ago

https://github.com/wechat-miniprogram/mobx-miniprogram-bindings

A helper library for binding MobX stores to WeChat Mini Programs, enabling reactive data synchronization between a MobX store and component or page data. Version 7.0.0 provides tools like storeBindingsBehavior, createStoreBindings, and TypeScript support via ComponentWithStore and BehaviorWithStore.

Tokens
3.5K
Snippets
13
Records
16
Agent score
54%

What's inside mobx-miniprogram-bindings

  1. How to bind a MobX store to a Component using behavior

    master

    The most common way to bind a store to a Component is using storeBindingsBehavior. This automatically handles the lifecycle of the binding. You can provide a single configuration object or an array of objects to bind multiple stores.

    import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
    import { store } from './store'
    
    export default Component({
      behaviors: [storeBindingsBehavior],
      storeBindings: {
        store,
        fields: {
          numA: () => store.numA,
          numB: (store) => store.numB,
          sum: 'sum',
        },
        actions: {
          buttonTap: 'update',
        },
      },
      methods: {
        myMethod() {
          this.data.sum // Accesses field from MobX store
        },
      },
    })
  2. Use TypeScript with ComponentWithStore and BehaviorWithStore

    master

    For better type inference in TypeScript, use ComponentWithStore or BehaviorWithStore.

    Requirements for correct typing:

    1. When using ComponentWithStore, do not include storeBindingsBehavior in the behaviors array.
    2. Append as const to the end of fields and actions definitions.
    3. If storeBindings is an array, append as const to the array itself.

    Note: These interfaces depend on miniprogram-api-typings ^4.0.0.

    import { ComponentWithStore } from 'mobx-miniprogram-bindings'
    
    export default ComponentWithStore({
      data: {
        someData: '...',
      },
      storeBindings: {
        store,
        fields: ['numA', 'numB', 'sum'] as const,
        actions: {
          buttonTap: 'update',
        } as const,
      },
    })
  3. Run examples in a browser

    master

    The examples in this repository can be run in both WeChat Mini Programs and web browsers. When running in a browser, the examples rely on glass-easel.

    To run an example in your browser, navigate to the specific example directory and follow these steps:

    1. Install dependencies using npm install.
    2. Build the project using npm run build to generate the web version.
    3. Open dist/index.html directly in your browser to view the result.
    npm install
    npm run build
    # Then open dist/index.html in your browser
  4. How to bind a MobX store to a Page using manual binding

    master

    Since Page constructors do not support behaviors, you must use createStoreBindings manually.

    CRITICAL: You must call the returned destroyStoreBindings() method in the onUnload (for Pages) or detached (for Components) lifecycle hook to prevent memory leaks.

    import { createStoreBindings } from 'mobx-miniprogram-bindings'
    
    Page({
      onLoad() {
        // Initialize binding
        this.storeBindings = createStoreBindings(this, {
          store,
          fields: ['numA', 'numB'],
        })
      },
      onUnload() {
        // Clean up to prevent memory leaks
        this.storeBindings.destroyStoreBindings()
      },
    })
  5. Bind MobX stores to components using `behavior`

    master

    The behavior exported from this package allows you to declaratively bind MobX stores to WeChat Mini Program components. By including this behavior in your component's behaviors array, you can use the storeBindings option within the component's definition to map store properties to component data and automatically generate action methods.

    How it works:

    1. storeBindings configuration: Define which store properties should be synced to the component's data.
    2. Automatic Actions: For every binding, the behavior automatically creates methods on the component instance that allow you to call actions defined in your MobX store.
    3. Lifecycle Management: The behavior automatically handles the synchronization of data when the store changes (attached lifecycle) and cleans up bindings when the component is destroyed (detached lifecycle).
    4. Manual Updates: You can manually trigger a synchronization of the bindings by calling this.updateStoreBindings() on the component instance.
    import { behavior } from 'mobx-miniprogram-bindings';
    
    Component({
      behaviors: [behavior],
      properties: {
        // ...
      },
      data: {
        // ...
      },
      storeBindings: {
        // Map store properties to component data
        storeA: {
          mapping: '{ a: "a" }',
          // Or use an array of bindings if multiple stores are used
        },
      },
      methods: {
        // Actions from the store will be automatically injected here
      }
    });
  6. Avoid issues with partial object updates

    master

    Updating a sub-field of an object in the store (e.g., this.someObject.someField = 'xxx') will not trigger a UI update in the component.

    To ensure the UI updates, you must replace the object entirely using Object.assign or similar methods:

    // Correct way to trigger update
    this.someObject = Object.assign({}, this.someObject, { someField: 'xxx' })
  7. Use initStoreBindings with glass-easel Chaining API

    master

    When using the glass-easel Chaining API, use initStoreBindings for a more ergonomic experience within the .init() block.

    import { initStoreBindings } from 'mobx-miniprogram-bindings'
    
    export default Component()
      .init((ctx) => {
        const { listener } = ctx
        initStoreBindings(ctx, {
          store,
          fields: ['numA', 'numB', 'sum'],
        })
        const buttonTap = listener(() => {
          store.update()
        })
        return { buttonTap }
      })
      .register()
  8. Configure storeBindings fields and actions

    master

    The binding configuration object requires the following fields:

    FieldTypeDescription
    storeMobX observableThe default MobX store. Required unless using the function form for fields without a store.
    fieldsArray or ObjectSpecifies which data fields to bind from the store.
    actionsArray or ObjectMaps store actions to this in the component/page. Required if actions is not empty.

    fields formats:

    • Array: ['numA', 'numB'] (Directly maps store property names to this.data).
    • Mapping: { a: 'numA' } (Maps store.numA to this.data.a).
    • Function: { a: () => store.numA } (Custom calculation for the field).

    actions formats:

    • Array: ['update'] (Maps store.update to this.update).
    • Mapping: { buttonTap: 'update' } (Maps store.update to this.buttonTap).
  9. Use BehaviorWithStore to create MobX-bound behaviors

    master

    Use BehaviorWithStore to create a WeChat Mini Program behavior that can be shared across multiple components to provide MobX store bindings. Similar to ComponentWithStore, it handles the injection of store data and actions and supports multiple store bindings via an array.

    import { BehaviorWithStore } from 'mobx-miniprogram-bindings';
    
    const myBehavior = BehaviorWithStore({
      storeBindings: [
        { store: storeA, fields: ['field1'] },
        { store: storeB, actions: ['action1'] }
      ],
      properties: {
        // behavior properties
      }
    });
  10. Initialize store bindings in Glass Easel using initStoreBindings

    master

    For environments using the Glass Easel engine, use initStoreBindings to set up bindings within the component lifecycle. It returns an object containing updateStoreBindings to manually trigger updates.

    It automatically handles the attached and detached lifecycles: creating the bindings on attached and destroying them on detached.

    import { initStoreBindings } from 'mobx-miniprogram-bindings';
    
    // Inside a Glass Easel context
    const bindings = initStoreBindings(ctx, {
      store: myStore,
      fields: ['field1']
    });
    
    // Manually trigger an update if needed
    bindings.updateStoreBindings();