性能优化是提升用户体验的关键因素,本文将从多个维度详细介绍uni-app应用的性能优化策略,帮助你构建流畅的跨端应用。
1. 首屏加载优化
1.1 分包加载
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | {
 "pages": [{
 "path": "pages/index/index",
 "style": { ... }
 }],
 "subPackages": [{
 "root": "pagesA",
 "pages": [{
 "path": "list/index",
 "style": { ... }
 }]
 }]
 }
 
 | 
1.2 预加载策略
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | uni.preloadSubPackage({
 name: 'pagesA',
 success: () => {
 console.log('分包预加载成功')
 },
 fail: () => {
 console.log('分包预加载失败')
 }
 })
 
 
 onLoad() {
 
 uni.preloadPage({
 url: '/pagesA/list/index'
 })
 }
 
 | 
1.3 骨架屏实现
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 
 | <!-- components/skeleton.vue --><template>
 <view class="skeleton" v-if="loading">
 <view class="skeleton-header"></view>
 <view class="skeleton-content">
 <view class="skeleton-item" v-for="i in 5" :key="i"></view>
 </view>
 </view>
 </template>
 
 <style>
 .skeleton {
 padding: 20rpx;
 }
 .skeleton-header {
 height: 40rpx;
 background: #f0f0f0;
 margin-bottom: 20rpx;
 animation: skeleton-loading 1s infinite;
 }
 .skeleton-item {
 height: 100rpx;
 background: #f0f0f0;
 margin-bottom: 20rpx;
 animation: skeleton-loading 1s infinite;
 }
 @keyframes skeleton-loading {
 0% { opacity: 1; }
 50% { opacity: 0.5; }
 100% { opacity: 1; }
 }
 </style>
 
 | 
2. 渲染性能优化
2.1 长列表优化
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 
 | <!-- 虚拟列表实现 --><template>
 <view class="list-container">
 <view
 class="list-phantom"
 :style="{ height: listHeight + 'px' }"
 ></view>
 <view
 class="list-content"
 :style="{ transform: getTransform }"
 >
 <view
 class="list-item"
 v-for="item in visibleData"
 :key="item.id"
 >
 {{ item.content }}
 </view>
 </view>
 </view>
 </template>
 
 <script>
 export default {
 data() {
 return {
 listData: [], // 完整列表数据
 itemHeight: 50, // 每项高度
 visibleCount: 10, // 可视区域显示的数量
 startIndex: 0, // 起始索引
 endIndex: 0 // 结束索引
 }
 },
 computed: {
 listHeight() {
 return this.listData.length * this.itemHeight
 },
 visibleData() {
 return this.listData.slice(this.startIndex, this.endIndex)
 },
 getTransform() {
 return `translate3d(0, ${this.startIndex * this.itemHeight}px, 0)`
 }
 },
 methods: {
 handleScroll(e) {
 const scrollTop = e.detail.scrollTop
 this.startIndex = Math.floor(scrollTop / this.itemHeight)
 this.endIndex = this.startIndex + this.visibleCount
 }
 }
 }
 </script>
 
 | 
2.2 避免频繁更新
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 | function debounce(fn, delay) {
 let timer = null
 return function(...args) {
 if (timer) clearTimeout(timer)
 timer = setTimeout(() => {
 fn.apply(this, args)
 }, delay)
 }
 }
 
 
 function throttle(fn, delay) {
 let timer = null
 let start = Date.now()
 return function(...args) {
 const current = Date.now()
 const remaining = delay - (current - start)
 if (timer) clearTimeout(timer)
 if (remaining <= 0) {
 fn.apply(this, args)
 start = Date.now()
 } else {
 timer = setTimeout(() => {
 fn.apply(this, args)
 start = Date.now()
 }, remaining)
 }
 }
 }
 
 
 export default {
 methods: {
 updateData: debounce(function() {
 
 }, 300)
 }
 }
 
 | 
3. 内存优化
3.1 及时销毁
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | export default {data() {
 return {
 timer: null,
 observer: null
 }
 },
 beforeDestroy() {
 
 if (this.timer) {
 clearTimeout(this.timer)
 this.timer = null
 }
 
 
 if (this.observer) {
 this.observer.disconnect()
 this.observer = null
 }
 }
 }
 
 | 
3.2 避免内存泄漏
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | const preloadImages = (urls) => {
 const promises = urls.map(url => {
 return new Promise((resolve, reject) => {
 const image = new Image()
 image.onload = () => {
 image.onload = null
 resolve(url)
 }
 image.onerror = () => {
 image.onerror = null
 reject(url)
 }
 image.src = url
 })
 })
 return Promise.all(promises)
 }
 
 | 
4. 网络优化
4.1 请求合并
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 
 | class RequestQueue {
 constructor() {
 this.queue = new Map()
 }
 
 async request(key, promiseCreator) {
 if (this.queue.has(key)) {
 return this.queue.get(key)
 }
 
 const promise = promiseCreator()
 this.queue.set(key, promise)
 
 try {
 const result = await promise
 this.queue.delete(key)
 return result
 } catch (err) {
 this.queue.delete(key)
 throw err
 }
 }
 }
 
 
 const requestQueue = new RequestQueue()
 
 function fetchData(id) {
 return requestQueue.request(`data_${id}`, () => {
 return new Promise(resolve => {
 setTimeout(() => {
 resolve({ id, data: 'some data' })
 }, 1000)
 })
 })
 }
 
 | 
4.2 数据缓存
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 
 | class CacheManager {constructor(expire = 5 * 60 * 1000) {
 this.cache = new Map()
 this.expire = expire
 }
 
 set(key, value) {
 this.cache.set(key, {
 value,
 timestamp: Date.now()
 })
 }
 
 get(key) {
 const data = this.cache.get(key)
 if (!data) return null
 
 if (Date.now() - data.timestamp > this.expire) {
 this.cache.delete(key)
 return null
 }
 
 return data.value
 }
 
 clear() {
 this.cache.clear()
 }
 }
 
 
 const cache = new CacheManager()
 
 async function getData(key) {
 
 const cached = cache.get(key)
 if (cached) return cached
 
 
 const data = await fetchData(key)
 cache.set(key, data)
 return data
 }
 
 | 
5. 其他优化技巧
5.1 图片优化
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | Vue.directive('lazy', {
 bind(el, binding) {
 const observer = new IntersectionObserver(entries => {
 entries.forEach(entry => {
 if (entry.isIntersecting) {
 el.src = binding.value
 observer.unobserve(el)
 }
 })
 })
 observer.observe(el)
 }
 })
 
 
 <image v-lazy="imageUrl" />
 
 | 
5.2 组件优化
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | <keep-alive>
 <component :is="currentComponent"></component>
 </keep-alive>
 
 
 const AsyncComponent = () => ({
 component: import('./heavy-component.vue'),
 loading: LoadingComponent,
 error: ErrorComponent,
 delay: 200,
 timeout: 3000
 })
 
 | 
6. 性能监控
6.1 页面性能监控
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | const performance = {
 mark(name) {
 if (typeof performance !== 'undefined') {
 performance.mark(name)
 }
 },
 
 
 measure(name, startMark, endMark) {
 if (typeof performance !== 'undefined') {
 performance.measure(name, startMark, endMark)
 const measures = performance.getEntriesByName(name)
 return measures[0].duration
 }
 return 0
 },
 
 
 report(data) {
 
 console.log('性能数据:', data)
 }
 }
 
 | 
7. 总结
- 合理使用分包加载
- 实现虚拟列表
- 优化更新机制
- 注意内存管理
- 做好网络优化
- 监控性能指标
如果觉得文章对你有帮助,欢迎点赞、评论、分享,你的支持是我继续创作的动力!