Conditional Rendering
In uni-app development, conditional rendering is a common requirement that allows you to display different content based on different conditions. This guide will introduce various conditional rendering methods and best practices.
Basic Conditional Rendering
v-if Directive
The v-if
directive is the most basic conditional rendering method, which conditionally renders elements based on expression values.
<template>
<view>
<text v-if="isLogin">Welcome back!</text>
<text v-else>Please log in</text>
</view>
</template>
<script>
export default {
data() {
return {
isLogin: false
}
}
}
</script>
v-show Directive
The v-show
directive controls element visibility by toggling CSS display property.
<template>
<view>
<text v-show="isVisible">This text can be shown or hidden</text>
<button @click="toggleVisible">Toggle</button>
</view>
</template>
<script>
export default {
data() {
return {
isVisible: true
}
},
methods: {
toggleVisible() {
this.isVisible = !this.isVisible
}
}
}
</script>
Difference Between v-if and v-show
Feature | v-if | v-show |
---|---|---|
Rendering method | Conditional rendering | Always rendered, controls visibility |
Performance | Higher switching cost | Higher initial rendering cost |
Suitable scenarios | Infrequent condition changes | Frequent condition changes |
Lifecycle hooks | Triggered on condition change | Not triggered |
Complex Conditional Rendering
Multiple Conditions
<template>
<view>
<text v-if="userType === 'admin'">Administrator Panel</text>
<text v-else-if="userType === 'user'">User Panel</text>
<text v-else-if="userType === 'guest'">Guest Panel</text>
<text v-else>Unknown User Type</text>
</view>
</template>
<script>
export default {
data() {
return {
userType: 'user'
}
}
}
</script>
Template Conditional Rendering
Use <template>
tag for conditional rendering of multiple elements:
<template>
<view>
<template v-if="showUserInfo">
<text>Username: {{ username }}</text>
<text>Email: {{ email }}</text>
<text>Phone: {{ phone }}</text>
</template>
</view>
</template>
<script>
export default {
data() {
return {
showUserInfo: true,
username: 'John',
email: 'john@example.com',
phone: '123-456-7890'
}
}
}
</script>
List Conditional Rendering
Filtering Lists
<template>
<view>
<input v-model="searchKeyword" placeholder="Search users" />
<view v-for="user in filteredUsers" :key="user.id">
<text>{{ user.name }}</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
searchKeyword: '',
users: [
{ id: 1, name: 'Alice', status: 'active' },
{ id: 2, name: 'Bob', status: 'inactive' },
{ id: 3, name: 'Charlie', status: 'active' }
]
}
},
computed: {
filteredUsers() {
return this.users.filter(user =>
user.name.toLowerCase().includes(this.searchKeyword.toLowerCase()) &&
user.status === 'active'
)
}
}
}
</script>
Conditional List Items
<template>
<view>
<view v-for="item in items" :key="item.id">
<text v-if="item.type === 'text'">{{ item.content }}</text>
<image v-else-if="item.type === 'image'" :src="item.src" />
<video v-else-if="item.type === 'video'" :src="item.src" />
</view>
</view>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, type: 'text', content: 'This is text content' },
{ id: 2, type: 'image', src: '/static/image.jpg' },
{ id: 3, type: 'video', src: '/static/video.mp4' }
]
}
}
}
</script>
Platform-Specific Conditional Rendering
Using Compilation Conditions
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<text>WeChat Mini Program specific content</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<text>H5 specific content</text>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<text>App specific content</text>
<!-- #endif -->
</view>
</template>
Runtime Platform Detection
<template>
<view>
<text v-if="isWeixin">WeChat Mini Program</text>
<text v-else-if="isH5">H5 Platform</text>
<text v-else-if="isApp">App Platform</text>
</view>
</template>
<script>
export default {
computed: {
isWeixin() {
// #ifdef MP-WEIXIN
return true
// #endif
// #ifndef MP-WEIXIN
return false
// #endif
},
isH5() {
// #ifdef H5
return true
// #endif
// #ifndef H5
return false
// #endif
},
isApp() {
// #ifdef APP-PLUS
return true
// #endif
// #ifndef APP-PLUS
return false
// #endif
}
}
}
</script>
Performance Optimization
Using Computed Properties
<template>
<view>
<view v-for="item in visibleItems" :key="item.id">
<text>{{ item.name }}</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
items: [],
showOnlyActive: true
}
},
computed: {
visibleItems() {
if (this.showOnlyActive) {
return this.items.filter(item => item.active)
}
return this.items
}
}
}
</script>
Avoiding Unnecessary Re-renders
<template>
<view>
<!-- Good: Use computed property -->
<text v-if="isUserLoggedIn">Welcome, {{ userName }}</text>
<!-- Avoid: Complex expressions in template -->
<!-- <text v-if="user && user.isLogin && user.name">Welcome, {{ user.name }}</text> -->
</view>
</template>
<script>
export default {
data() {
return {
user: {
isLogin: true,
name: 'John'
}
}
},
computed: {
isUserLoggedIn() {
return this.user && this.user.isLogin && this.user.name
},
userName() {
return this.user ? this.user.name : ''
}
}
}
</script>
Best Practices
1. Choose Appropriate Conditional Rendering Method
- Use
v-if
for infrequent condition changes - Use
v-show
for frequent condition changes - Use computed properties for complex logic
2. Avoid Complex Expressions in Templates
<!-- Good -->
<text v-if="shouldShowMessage">{{ message }}</text>
<!-- Avoid -->
<text v-if="user && user.permissions && user.permissions.includes('read') && !user.isBlocked">
{{ message }}
</text>
3. Use Key Attributes Properly
<template>
<view>
<input v-if="loginType === 'username'" key="username" placeholder="Username" />
<input v-else key="email" placeholder="Email" />
</view>
</template>
4. Consider Performance Impact
For large lists, use virtual scrolling or pagination instead of hiding elements with v-show
.
5. Maintain Code Readability
Use meaningful variable names and extract complex logic into computed properties or methods.
Common Issues and Solutions
Issue 1: v-if and v-for Used Together
<!-- Avoid -->
<view v-for="user in users" v-if="user.active" :key="user.id">
{{ user.name }}
</view>
<!-- Solution: Use computed property -->
<view v-for="user in activeUsers" :key="user.id">
{{ user.name }}
</view>
Issue 2: Conditional Rendering Causing Layout Issues
<template>
<view class="container">
<!-- Use v-show to maintain layout -->
<view v-show="showSidebar" class="sidebar">Sidebar</view>
<view class="content">Main content</view>
</view>
</template>
<style>
.container {
display: flex;
}
.sidebar {
width: 200px;
}
.content {
flex: 1;
}
</style>
Issue 3: State Not Updating After Condition Change
Ensure reactive data is properly defined and modified:
<script>
export default {
data() {
return {
// Ensure all properties are defined in data
showModal: false,
user: {
isLogin: false
}
}
},
methods: {
login() {
// Use Vue.set for nested properties if needed
this.$set(this.user, 'isLogin', true)
// Or use reactive assignment
this.user = { ...this.user, isLogin: true }
}
}
}
</script>
Summary
Conditional rendering is a powerful feature in uni-app that allows you to create dynamic and interactive user interfaces. By understanding the differences between various conditional rendering methods and following best practices, you can build efficient and maintainable applications. Remember to consider performance implications and choose the most appropriate method for your specific use case.