UniApp跨平台开发实战:从零打造高仿微信小程序全栈项目

2025-08-04 0 677

一、项目架构设计

技术栈组成:

  • UniApp:跨端开发框架
  • Vue3:前端框架
  • Pinia:状态管理
  • uView UI:UI组件库
  • Node.js:后端服务

二、核心功能实现

1. 仿微信聊天界面

<template>
  <view class="chat-container">
    <scroll-view 
      scroll-y 
      :scroll-top="scrollTop"
      @scrolltoupper="loadMore"
      class="message-list"
    >
      <view 
        v-for="(msg, index) in messages" 
        :key="msg.id"
        :class="['message-item', msg.isMe ? 'me' : 'other']"
      >
        <image 
          v-if="!msg.isMe"
          class="avatar"
          :src="msg.avatar"
          mode="aspectFill"
        />
        <view class="content">
          <text class="text">{{ msg.content }}</text>
          <text class="time">{{ formatTime(msg.time) }}</text>
        </view>
      </view>
    </scroll-view>
    
    <view class="input-area">
      <input 
        v-model="inputMsg"
        placeholder="输入消息..."
        @confirm="sendMessage"
      />
      <button @click="sendMessage">发送</button>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useChatStore } from '@/stores/chat'

const chatStore = useChatStore()
const messages = ref([])
const inputMsg = ref('')
const scrollTop = ref(0)

onMounted(() => {
  loadMessages()
})

const loadMessages = async () => {
  messages.value = await chatStore.getMessages()
}

const sendMessage = () => {
  if (!inputMsg.value.trim()) return
  
  chatStore.sendMessage({
    content: inputMsg.value,
    isMe: true,
    time: Date.now()
  })
  
  inputMsg.value = ''
  scrollToBottom()
}

const scrollToBottom = () => {
  uni.createSelectorQuery()
    .select('.message-list')
    .boundingClientRect(res => {
      scrollTop.value = res.height
    })
    .exec()
}
</script>

2. 朋友圈功能实现

<template>
  <view class="moment-list">
    <view 
      v-for="moment in moments" 
      :key="moment.id"
      class="moment-item"
    >
      <view class="user-info">
        <image class="avatar" :src="moment.avatar"/>
        <text class="name">{{ moment.name }}</text>
      </view>
      
      <text class="content">{{ moment.content }}</text>
      
      <view class="image-list" v-if="moment.images.length">
        <image 
          v-for="(img, index) in moment.images"
          :key="index"
          :src="img"
          mode="aspectFill"
          @click="previewImage(moment.images, index)"
        />
      </view>
      
      <view class="footer">
        <text class="time">{{ formatTime(moment.time) }}</text>
        <view class="actions">
          <text @click="toggleLike(moment)">
            {{ moment.liked ? '取消' : '' }}点赞
          </text>
          <text @click="showComment(moment)">评论</text>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import { useMomentStore } from '@/stores/moment'

const momentStore = useMomentStore()
const moments = ref([])

const loadMoments = async () => {
  moments.value = await momentStore.getMoments()
}

const previewImage = (urls, current) => {
  uni.previewImage({
    urls,
    current
  })
}

const toggleLike = async (moment) => {
  await momentStore.toggleLike(moment.id)
  loadMoments()
}
</script>

三、性能优化方案

1. 图片懒加载

<template>
  <image 
    v-for="img in imageList"
    :key="img.id"
    :src="placeholder"
    :data-src="img.url"
    lazy-load
    @load="onImageLoad"
  />
</template>

<script>
export default {
  data() {
    return {
      placeholder: '/static/placeholder.png',
      imageList: [] // 从接口获取的图片列表
    }
  },
  methods: {
    onImageLoad(e) {
      const img = e.target
      const src = img.dataset.src
      if (src) {
        img.src = src
        img.removeAttribute('data-src')
      }
    }
  }
}
</script>

2. 数据分页加载

// 分页加载实现
export function usePagination(api, params = {}) {
  const loading = ref(false)
  const finished = ref(false)
  const list = ref([])
  const pagination = reactive({
    page: 1,
    pageSize: 10,
    total: 0
  })
  
  const loadData = async () => {
    if (loading.value || finished.value) return
    
    loading.value = true
    
    try {
      const res = await api({
        ...params,
        page: pagination.page,
        pageSize: pagination.pageSize
      })
      
      list.value = [...list.value, ...res.list]
      pagination.total = res.total
      
      if (list.value.length >= pagination.total) {
        finished.value = true
      } else {
        pagination.page++
      }
    } finally {
      loading.value = false
    }
  }
  
  return {
    loading,
    finished,
    list,
    loadData,
    refresh: () => {
      list.value = []
      pagination.page = 1
      finished.value = false
      loadData()
    }
  }
}
UniApp跨平台开发实战:从零打造高仿微信小程序全栈项目
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 uniapp UniApp跨平台开发实战:从零打造高仿微信小程序全栈项目 https://www.taomawang.com/web/uniapp/747.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务