Skip to content

Data Binding ​

Data binding is a core concept in mini program development that allows developers to connect data with the view layer, enabling data-driven UI updates. This guide introduces the basic concepts and advanced techniques of data binding in mini programs.

Basic Data Binding ​

Text Binding ​

Use double curly braces to bind data to text content:

html
<view>{{message}}</view>
javascript
Page({
  data: {
    message: 'Hello World'
  }
})

Attribute Binding ​

The same double curly braces syntax can be used to bind data to component attributes:

html
<image src="{{imageUrl}}" class="{{isActive ? 'active' : ''}}"></image>
javascript
Page({
  data: {
    imageUrl: '/assets/images/logo.png',
    isActive: true
  }
})

Conditional Rendering ​

Use wx:if, wx:elif, and wx:else directives to conditionally render content:

html
<view wx:if="{{condition === 'A'}}">Condition A is met</view>
<view wx:elif="{{condition === 'B'}}">Condition B is met</view>
<view wx:else>Other conditions</view>
javascript
Page({
  data: {
    condition: 'A'
  }
})

Additionally, you can use the hidden attribute to control element visibility:

html
<view hidden="{{!showContent}}">Visible when content is shown</view>

Note: wx:if controls display by adding/removing nodes, while hidden only sets the CSS display property. For frequently toggled content, using hidden performs better; for infrequently toggled content, wx:if is more appropriate.

List Rendering ​

Use the wx:for directive to render list data:

html
<view wx:for="{{items}}" wx:key="id">
  {{index}}: {{item.name}}
</view>
javascript
Page({
  data: {
    items: [
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      { id: 3, name: 'Item 3' }
    ]
  }
})

By default, the loop item variable is named item and the index is index. You can use wx:for-item and wx:for-index to customize variable names:

html
<view wx:for="{{items}}" wx:for-item="product" wx:for-index="idx" wx:key="id">
  {{idx}}: {{product.name}}
</view>

Templates and References ​

You can use templates to reuse code snippets:

html
<!-- Define template -->
<template name="productItem">
  <view class="product">
    <image src="{{imageUrl}}"></image>
    <view class="name">{{name}}</view>
    <view class="price">${{price}}</view>
  </view>
</template>

<!-- Use template -->
<block wx:for="{{products}}" wx:key="id">
  <template is="productItem" data="{{...item}}"></template>
</block>
javascript
Page({
  data: {
    products: [
      { id: 1, name: 'Product 1', price: 99, imageUrl: '/assets/product1.png' },
      { id: 2, name: 'Product 2', price: 199, imageUrl: '/assets/product2.png' },
      { id: 3, name: 'Product 3', price: 299, imageUrl: '/assets/product3.png' }
    ]
  }
})

Data Updates ​

setData Method ​

In mini programs, use the setData method to update data and trigger view updates:

javascript
Page({
  data: {
    count: 0,
    userInfo: {
      name: '',
      age: 0
    }
  },
  
  incrementCount() {
    this.setData({
      count: this.data.count + 1
    })
  },
  
  updateUserName(name) {
    this.setData({
      'userInfo.name': name
    })
  }
})

Data Path Expressions ​

setData supports using data path expressions to update specific values in nested objects or arrays:

javascript
// Update properties in an object
this.setData({
  'userInfo.name': 'John',
  'userInfo.age': 30
})

// Update elements in an array
this.setData({
  'items[0].name': 'Updated Item 1',
  'items[1].price': 299
})

Performance Optimization ​

setData is the most commonly used but also the most likely to cause performance issues in mini programs. Follow these principles:

  1. Reduce the frequency of setData calls

    javascript
    // Not recommended: Frequent setData calls
    this.setData({ value1: 'a' })
    this.setData({ value2: 'b' })
    
    // Recommended: Combine multiple updates
    this.setData({
      value1: 'a',
      value2: 'b'
    })
  2. Reduce the amount of data passed

    javascript
    // Not recommended: Update the entire object
    this.setData({
      userInfo: this.data.userInfo
    })
    
    // Recommended: Only update changed properties
    this.setData({
      'userInfo.name': 'John'
    })
  3. Avoid frequently updating invisible data

    For content rendered conditionally with wx:if, you can avoid updating its data when it's not visible.

Two-Way Data Binding ​

Mini programs don't natively support true two-way data binding, but you can simulate it through event handling:

html
<input value="{{inputValue}}" bindinput="handleInput" />
<view>Current input: {{inputValue}}</view>
javascript
Page({
  data: {
    inputValue: ''
  },
  
  handleInput(e) {
    this.setData({
      inputValue: e.detail.value
    })
  }
})

Computed Properties and Watchers ​

Mini programs don't natively support computed properties and watchers, but you can implement similar functionality through custom methods:

Simulating Computed Properties ​

javascript
Page({
  data: {
    price: 100,
    quantity: 2
  },
  
  onLoad() {
    this.updateTotal()
  },
  
  updatePrice(newPrice) {
    this.setData({
      price: newPrice
    })
    this.updateTotal()
  },
  
  updateQuantity(newQuantity) {
    this.setData({
      quantity: newQuantity
    })
    this.updateTotal()
  },
  
  updateTotal() {
    this.setData({
      total: this.data.price * this.data.quantity
    })
  }
})

Simulating Watchers ​

javascript
Page({
  data: {
    userInput: ''
  },
  
  handleInput(e) {
    const newValue = e.detail.value
    this.setData({
      userInput: newValue
    })
    
    // Watch for value changes and perform operations
    this.watchUserInput(newValue)
  },
  
  watchUserInput(newValue) {
    if (newValue.length > 5) {
      wx.showToast({
        title: 'Input too long',
        icon: 'none'
      })
    }
  }
})

Enhanced Data Binding with Component Libraries ​

Some third-party component libraries provide enhanced data binding capabilities:

WePY Framework ​

WePY framework provides Vue-like data binding syntax:

html
<template>
  <view>{{message}}</view>
  <input v-model="userInput" />
</template>

<script>
import wepy from 'wepy'

export default class MyPage extends wepy.page {
  data = {
    message: 'Hello WePY',
    userInput: ''
  }
  
  computed = {
    reversedMessage() {
      return this.message.split('').reverse().join('')
    }
  }
  
  watch = {
    userInput(newValue, oldValue) {
      console.log(`Input changed from ${oldValue} to ${newValue}`)
    }
  }
}
</script>

Taro Framework ​

Taro framework provides React-like data binding:

jsx
import React, { useState, useMemo } from 'react'
import { View, Input } from '@tarojs/components'

function MyComponent() {
  const [message, setMessage] = useState('Hello Taro')
  const [userInput, setUserInput] = useState('')
  
  // Computed property
  const reversedMessage = useMemo(() => {
    return message.split('').reverse().join('')
  }, [message])
  
  // Watcher effect
  useEffect(() => {
    console.log(`Input changed: ${userInput}`)
  }, [userInput])
  
  return (
    <View>
      <View>{message}</View>
      <View>{reversedMessage}</View>
      <Input 
        value={userInput} 
        onInput={e => setUserInput(e.detail.value)} 
      />
    </View>
  )
}

Best Practices ​

  1. Keep Data Models Simple

    • Avoid deeply nested structures
    • Use flattened data structures
  2. Break Down Components Appropriately

    • Split complex pages into multiple components
    • Each component maintains its own data state
  3. Use Keys to Improve List Rendering Performance

    • Always provide wx:key for wx:for
    • Use unique and stable identifiers as keys
  4. Avoid Complex Calculations in Templates

    • Pre-process data in JavaScript
    • Store results in data
  5. Use Block to Wrap Multiple Elements

    • The <block> element doesn't create actual DOM nodes
    • Use it for conditional rendering or looping over multiple elements
html
<block wx:if="{{showItems}}">
  <view>First item</view>
  <view>Second item</view>
  <view>Third item</view>
</block>

Next Steps ​

Now that you understand data binding in mini programs, you can continue learning about:

Connecting Multiple Platforms, Empowering Innovation