Mastering WeChat Mini Program Development with the MINA Framework

This article introduces the MINA framework for WeChat Mini Programs, covering its view and logic layers, responsive data binding, page management, core components, API usage, project structure, runtime behavior, and provides a step‑by‑step guide to building a functional expense‑tracking mini‑app with full code examples.

Baixing.com Technical Team
Baixing.com Technical Team
Baixing.com Technical Team
Mastering WeChat Mini Program Development with the MINA Framework

Fundamentals

MINA Framework

The MINA framework, provided by WeChat, bundles many native components and APIs to simplify Mini Program development. It offers its own view description language (WXML, WXSS) and a JavaScript‑based logic layer, handling data transmission and events between view and logic.

Responsive Data Binding

The core of the framework is a reactive data‑binding system that synchronizes the view (View) and the logic layer (App Service). Updating data in the logic layer automatically updates the view.

<!-- This is our View -->
<view> Hello {{name}}! </view>
<button bindtap="onChangeName"> Click me! </button>
// This is our App Service.
// Register a Page.
Page({
  data: 'Baixing',
  onChangeName: function(e) {
    // send data change to view
    this.setData({
      name: 'MINA'
    })
  }
})

When the button is tapped, the view triggers onChangeName, the logic layer calls setData(), and the bound name updates the view from “Hello Baixing!” to “Hello MINA!”.

Page Management

The framework manages page routing and lifecycle, allowing seamless page switches; developers only need to register page data, methods, and lifecycle functions.

Basic Components

The framework provides a set of basic components with WeChat styling and logic. Developers can combine them to build powerful Mini Programs. See the component documentation at https://mp.weixin.qq.com/debug/wxadoc/dev/component.

Rich API

MINA offers many native WeChat APIs for user info, storage, payment, etc. See the API reference at https://mp.weixin.qq.com/debug/wxadoc/dev/api.

Mini Program Directory Structure

A Mini Program consists of an app and multiple pages. The app root contains three files:

app.js – entry file

app.json – global configuration (e.g., routes)

app.wxss – global stylesheet

Each page includes four files with matching names:

*.js – page logic

*.wxml – page structure using MINA components

*.wxss – page stylesheet (similar to CSS)

*.json – page configuration (e.g., pull‑down refresh)

Mini Program Runtime Mechanism

Mini Programs do not have a restart concept. Their lifecycle includes:

The app stays alive in the background for a limited time (about 5 minutes) before WeChat destroys it.

Pinned Mini Programs are not destroyed automatically.

System memory warnings also trigger destruction.

Development Practice

The following example builds a simple expense‑tracking Mini Program.

Create Project

Download the Mini Program DevTools from https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/devtools.html and create a new project (no AppID mode is used in this guide).

After entering the project name and directory, the development interface appears.

Create Page

The app has two pages: a home page showing all records and a page for adding a new record. After adding the files, the project structure looks like:

Write Code

1. Home Page Functions

Calculate total expense

Display summary of each record

Logic:

import { loadAllRecord, deleteRecordById } from '../../services/tallyService.js'
var app = getApp()
Page({
  data: {
    userInfo: {},
    list: [],
    totalMoney: 0
  },
  // Load stored daily expense records and calculate total amount.
  fetchData() {
    wx.showLoading({ title: '加载数据中...' })
    var self = this
    loadAllRecords((list) => {
      var totalMoney = 0
      list.forEach((item) => {
        totalMoney += Number(item.money)
      })
      self.setData({ list, totalMoney })
      self.customerData.isFirstShow = false
      setTimeout(() => {
        wx.hideLoading()
      }, 1000)
    })
  }
})

Structure:

<!--index.wxml-->
<view class="container">
  <view bindtap="bindViewTap" class="userinfo">
    <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
    <view class="info-view">
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
      <text class="money-text">总花费:{{totalMoney}}元</text>
    </view>
  </view>
  <view class="list-view">
    <block wx:for="{{list}}" wx:key="*this">
      <view class="tally-cell">
        <text class="detail-text">{{item.detail}}</text>
        <text class="money-text">{{item.money}}元</text>
        <text class="time-text">{{item.time}}</text>
      </view>
    </block>
  </view>
  <navigator class="add-button" url="../record/record" open-type="navigate">记一笔</navigator>
</view>

2. Record Page Functions

Record expense amount and details

Logic:

import { addNewRecord } from '../../services/tallyService.js'
var app = getApp()
Page({
  ...,
  onSaveRecord() {
    let record = {
      money: this.customerData.money,
      detail: this.customerData.detail
    }
    addNewRecord(record, (res) => {
      console.log(res)
      wx.navigateBack({})
    })
  }
})

Structure:

<!--record.wxml-->
<view class="container record-view">
  <view class="money-view">
    金额:
    <input placeholder="请输入要记录的花费金额..."
      bindblur="onMoneyBlured"
      maxlength="10"
      placeholder-style="font-size: 14px;"
      confirm-type="done"
      type="digit"
      auto-focus
      value="{{money}}"
      bindinput="onMoneyChanged"/>
  </view>
  <view class="detail-view">
    花费记录:
    <textarea class="detail-textarea"
      placeholder-style="font-size: 14px;"
      placeholder="请输入具体的花费详细吧..."
      maxlength="160"
      cursor-spacing="10"
      bindinput="onDetailChanged"/>
  </view>
  <button class="save-button"
    catchtap="onSaveRecord"
    formType="submit"
    disabled="{{ !canSave }}">保存</button>
</view>

3. Record DAO Class

Data access logic:

var records = []
import { formatTime } from '../utils/util.js'

function addNewRecord({money, detail}, callback) {
  let id = records.length
  let time = formatTime(new Date())
  let record = {id, money, detail, time}
  records.push(record)
  if (typeof callback === 'function') {
    callback(true)
  }
}

function loadAllRecord(callback) {
  if (typeof callback === 'function') {
    callback(records)
  }
}

module.exports = {
  addNewRecord,
  loadAllRecord
}

Preview

When using an AppID, click “Preview” in the DevTools to generate a QR code and scan it with a developer‑authorized WeChat account.

Running the program shows the final interface.

The complete source code is available at https://github.com/wanghongli123/BXTally.

Conclusion

WeChat Mini Programs are rapidly evolving, and this guide aims to help developers get started with MINA‑based Mini Program development.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

FrontendData Bindingmina-frameworkwechat-mini-program
Baixing.com Technical Team
Written by

Baixing.com Technical Team

A collection of the Baixing.com tech team's insights and learnings, featuring one weekly technical article worth following.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.