仿微信app项目流程

  • 前台开发:vue
  • 后台开发:node
  • 数据库:MongoDB
  • 组件:weui

创建项目:vue脚手架

vue create friends

注册登录页面

仿微信app项目流程_第1张图片

  • 使用阿里云短信服务功能
  • 用户根据手机号获取验证码后台判断是进行登录还是注册
  • 验证手机号和验证码是否符合
  • 注册成功之后
    1)将登录或者注册成功的用户信息存储起来,以供其他页面使用
    - cookie: 存在过期时间和禁用cookie的问题
    - 本地存储:localstorage和sessionstorage:某些浏览器不支持本地存储
    - 存储到程序本身的内存中,同时可以在localstorage中存储一个备份(推荐方式,使用vuex)
    2)跳转到用户本来想要请求的页面
    // 注册或登录
    async sinup () {
     
      // 验证手机号是否合法
      const reg = /^1[3456789]\d{
     9}$/
      if (!reg.test(this.phoneNum)) {
     
        weui.toast('请填入合法的手机号码', 2000)
        return false
      }
      // 验证验证码
      if (!this.code) {
     
        weui.toast('请填入验证码', 2000)
        return false
      }
      // 发送请求,注册或者登录
      const res = await service.post('/users/signup', {
     
        phonenum: this.phoneNum,
        code: this.code
      })
     // 注册成功后跳转到登录页面
      if (res.data.code === 0) {
     
        this.$store.dispatch('setUser', res.data.data)
        // 跳转到本来想要跳转的页面(跳转到登录之前的页面)
        this.$router.go(-1)
      }
    },
    // 获取验证码
    async getCode () {
     
      // 验证手机号
      const reg = /^1[3456789]\d{
     9}$/
      if (!reg.test(this.phoneNum)) {
     
        weui.toast('请填入合法的手机号码', 2000)
        return false
      }
      // 向服务器接口发送请求
      const res = await service.get('/users/phonecode', {
     
        phonenum: this.phoneNum
      })
      console.log('login:' + res)
      // 开启定时器,60s倒计时
      this.countTimeCode()
    },

好友动态页面

仿微信app项目流程_第2张图片

  • 获取存储在vuex中的用户头像,昵称,背景图等展示出来
  • 更换背景图片:使用actionSheet组件弹出菜单中选择‘从相册选择’弹出一个选择图片文件,服务器上传成功后更新vuex的数据
  • 加载更多数据:列表默认只展示5条数据,数据加载完毕后手指滑动页面向上刷新组件继续加载更多内容
  • 下拉刷新:下拉显示小圆球设置动画效果旋转,小圆球跟着下拉移动,加载最新数据,手指松开小圆球归位
  • 手机端评论文本框显示:设置Android系统和iOS系统文本框弹起的高度
  • 点赞/取消点赞:请求后台接口实现成功后通知vuex更新列表的数据
  • 评论:点击评论展示评论文本框,设置自动获取焦点,请求后台接口,更新列表数据
  • 跳转页面:点击右上角图标进入到发表动态页面
设置小圆球
mounted () {
     
    this.$bus.$on('dataLoadReady', () => {
     
      // 为动画设置定时器
      if (this.$refs.circleIconInner) {
     
        setTimeout(() => {
     
        // 取消圆球的旋转
          this.$refs.circleIconInner.classList.remove('circle-rotate')
          // 让圆球的位置归位
          this.$refs.circleIcon.style.transition = 'all 500ms'
          this.$refs.circleIcon.style.transform = 'translate(0,-30px) rotate(0deg)'
          this.pullRefresh.isPull = false
        }, 800)
      }
    })
  },
  methods: {
     
    touchstart (e) {
     
      // 记录触摸的起始纵坐标
      this.pullRefresh.dragStart = e.targetTouches[0].clientY
    },
    touchmove (e) {
     
      const target = e.targetTouches[0]
      // 记录(手指现在位置-初始位置)/屏幕高度 计算得来的数值
      this.pullRefresh.percentage = (this.pullRefresh.dragStart - target.clientY) / window.screen.height
      // 获取scrollTop的值,只有值为0时,才会开始下拉刷新逻辑
      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
      if (scrollTop === 0) {
     
        // 必须是向下拖动
        if (this.pullRefresh.percentage < 0 && e.cancelable) {
     
          // 满足上边的两个条件,才能真正进入到下拉逻辑
          this.pullRefresh.isPull = true
          // 禁用浏览器的默认行为
          e.preventDefault()
          // 计算圆球的纵向移动距离
          const translateY = -this.pullRefresh.percentage * this.pullRefresh.moveCount
          if (Math.abs(this.pullRefresh.percentage) <= this.pullRefresh.dragEnd) {
     
            // 计算圆球的旋转角度
            const rotate = translateY / 100 * 360
            // 设置圆球的纵向位置
            this.$refs.circleIcon.style.transform = `translate(0,${
      translateY}px)  rotate(${
      rotate}deg)`
          }
        } else {
     
          // 向上拖动,就不会进入下拉刷新逻辑
          this.pullRefresh.dragStart = null
        }
      } else {
     
        // 如果没有在页面顶部执行拖动事件,则不执行下拉刷新逻辑
        this.pullRefresh.dragStart = null
      }
    },
    // 手指松开屏幕后,圆球归位,加载最新数据
    touchend (e) {
     
      if (!this.pullRefresh.isPull) {
     
        return
      }
      // console.log(Math.abs(this.pullRefresh.percentage) > this.pullRefresh.dragEnd)
      if (Math.abs(this.pullRefresh.percentage) > this.pullRefresh.dragEnd) {
     
        // 为小圆球引用动画
        this.$refs.circleIconInner.classList.add('circle-rotate')
        // 通知使用此组件的组件加载最新数据
        this.$emit('onRefresh')
      } else {
     
        // 用户下拉的距离,没有达到临界值,就自动收回
        this.$refs.circleIcon.style.transition = 'all 500ms'
        this.$refs.circleIcon.style.transform = 'translate(0,0) rotate(0deg)'
      }
      // 重置dragstart
      this.pullRefresh.dragStart = null
      this.pullRefresh.percentage = null
    }
  }

发表动态页面

仿微信app项目流程_第3张图片

  • 验证用户是否登录
  • 设置字数限制,点击发表验证内容是否为空
  • 使用weui.js中的upload组件实现图片上传功能,可进行图片预览和删除
  • 点击发表请求后台接口更改列表数据
methods: {
     
	// 设置文字输入的数量
    oninput () {
     
      if (this.content.length > 200) {
     
        this.content = this.content.substr(0, 200)
      }
      this.letterCount = this.content.length
    },
    cancel () {
     
      this.$router.go(-1)
    },
    async publish () {
     
      if (!this.content.trim()) {
     
        weui.toast('请输入内容', 1000)
        return false
      }
      // 验证输入的文字的数量
      if (this.content.length > 200) {
     
        return
      }
      // 请求接口,发表朋友圈
      const res = await service.post('/post/savepost', {
     
        content: this.content,
        picList: this.picList
      })
      if (res.data.code === 0) {
     
        this.$router.go(-1)
      }
    },
    // 查看大图
    preImg (e) {
     
      const self = this
      const style = e.target.getAttribute('style')
      const url = style.split('"')[1]
      var gallery = weui.gallery(url, {
     
        onDelete: function () {
     
          self.deleteImg(e.target, gallery)
        }
      })
    },
    // 删除图片
    deleteImg (target, gallery) {
     
      const self = this
      weui.confirm('确认删除图片吗', () => {
     
        // 从数组 picList 中删除选中的图片
        // const id = e.target.getAttribute('data-id')
        const id = target.dataset.id
        const index = self.picList.findIndex(item => {
     
          return item.id === id
        })
        self.picList.splice(index, 1)
        // 删除对应的dom元素
        target.remove()
        self.uploadCount--
      })
      gallery.hide(function () {
     
        console.log('`gallery` has been hidden')
      })
    }
  },

个人中心

仿微信app项目流程_第4张图片

  • 获取存储的数据,展示出来
  • 更新头像:点击头像,弹出upload组件的对话框上传图片,通知vuex更新新的用户信息
  • 更新昵称:点击昵称进入昵称页面,输入新的昵称点击保存同时更新数据库和本地存储的用户信息并返回到个人信息页面
  • 更新签名:点击签名进入签名页面,输入新的签名点击保存同时更新数据库和本地存储的用户信息并返回到个人信息页面
  • 更新性别:点击性别从下方弹出选择性别的选择框,选择后更新数据库和本地存储用户信息并显示
  • 私信:点击私信进入消息列表页面

私信

仿微信app项目流程_第5张图片

  • 使用关键词搜索聊天记录并展示出来
  • 显示与好友的最后一条信息
  • 点击相应好友可进入到好友聊天页面

聊天页面

仿微信app项目流程_第6张图片

  • 获取数据,展示历史聊天记录
  • 默认只显示文本框,点击加号,展示下方面板,点击照片可以发送图片
  • 运用socket.io-client + vue-socket.io插件实现实时通讯聊天
  // 页面加载时,首先当前用户登录socket,获取当前登录用户与当前指定用户的聊天记录
  created () {
     
    if (this.$store.state.currentUser && this.$store.state.currentUser._id) {
     
      // 登录socket
      this.$socket.emit('login', this.$store.state.currentUser)
    }
    // 获取历史聊天数据
    this.fetchData()
  },
  sockets: {
     
    // 当服务器端有消息推送过来的时候,这个方法就会执行,推送的数据会赋值给参数obj
    recieveMsg: function (obj) {
     
      if (obj.fromUser._id === this.toUserId) {
     
        this.addMessage({
     
          content: obj.content,
          fromUser: obj.fromUser,
          mine: false // 对方发送的消息
        })
      }
    }
  },
  /**
     * 服务器掉之后,客户端会重新连接,连接成功后会触发下面的事件
     * 我们就在这个事件中,重新登录
     */
  reconnect (obj) {
     
    if (this.$store.state.currentUser && this.$store.state.currentUser._id) {
     
      // 登录socket
      this.$socket.emit('login', this.$store.state.currentUser)
    }
  },

获取聊天历史记录

  // 获取聊天记录
    async fetchData () {
     
      const res = await service.get('message/getchathistory', {
     
        toUser: this.toUserId
      })
      if (res.data.code === 0) {
     
        this.dataList = (res.data.data)
      }
    },

好友名片

仿微信app项目流程_第7张图片

  • 在好友动态页面点击好友头像跳转到好友名片页面,跳转时将好友的id传过去
    根据的好友的id查询好友的所有信息数据,并展示在页面
  • 点击发消息进入好友聊天界面

你可能感兴趣的:(vue,前端)