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:
<view>{{message}}</view>
Page({
data: {
message: 'Hello World'
}
})
Attribute Binding
The same double curly braces syntax can be used to bind data to component attributes:
<image src="{{imageUrl}}" class="{{isActive ? 'active' : ''}}"></image>
Page({
data: {
imageUrl: '/assets/images/logo.png',
isActive: true
}
})
Conditional Rendering
Use wx:if
, wx:elif
, and wx:else
directives to conditionally render content:
<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>
Page({
data: {
condition: 'A'
}
})
Additionally, you can use the hidden
attribute to control element visibility:
<view hidden="{{!showContent}}">Visible when content is shown</view>
Note:
wx:if
controls display by adding/removing nodes, whilehidden
only sets the CSS display property. For frequently toggled content, usinghidden
performs better; for infrequently toggled content,wx:if
is more appropriate.
List Rendering
Use the wx:for
directive to render list data:
<view wx:for="{{items}}" wx:key="id">
{{index}}: {{item.name}}
</view>
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:
<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:
<!-- 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>
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:
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:
// 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:
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' })
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' })
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:
<input value="{{inputValue}}" bindinput="handleInput" />
<view>Current input: {{inputValue}}</view>
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
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
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:
<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:
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
Keep Data Models Simple
- Avoid deeply nested structures
- Use flattened data structures
Break Down Components Appropriately
- Split complex pages into multiple components
- Each component maintains its own data state
Use Keys to Improve List Rendering Performance
- Always provide
wx:key
forwx:for
- Use unique and stable identifiers as keys
- Always provide
Avoid Complex Calculations in Templates
- Pre-process data in JavaScript
- Store results in data
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
- The
<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: