項目功能簡介:
用戶通過手機號驗證碼進行登錄和注冊 可以瀏覽動態列表中的所有動態 登錄成功后用戶可以發表自己的動態 也可以對自己認可欣賞的動態進行點贊和評論 也可以通過動態結識志同道合的朋友 進行聊天和探討
- 前端:采用Vue框架搭建 weui進行頁面布局
- 后端:采用node.js
- 數據庫:mangoDB庫
1. 登錄注冊功能:
- 通過weui中weui-form進行的頁面布局
- 使用 /^1[3456789]\d{9}$/ 此正則表達式驗證手機號是否合法
- 用戶點擊獲取驗證碼后按鈕變成60秒倒計時
- 調用后端接口通過調用阿里云短信服務向用戶輸入的手機號碼發送驗證碼
- 驗證碼輸入后點擊同意并閱讀相關條款后 注冊/確定按鈕變成激活狀態
- 登錄成功后該頁面跳轉至上一需登錄頁面
- 將用戶信息存入store中(Vuex)
2. 主頁:
2.1 上半部分:
- 頭部導航 返回按鈕 相機標志(見主題3)
- 背景圖 頭像 用戶昵稱 如果用戶未登錄是系統隨機匹配的圖片
2.1.1 頭部:
當導航條在最頂部時此導航部分為透明,并且不顯示朋友圈文字,當用戶向下混動一定距離時,導航部分為灰色背景色顯示文字,并且相機顏色為黑色,點擊相機圖標跳轉到發布動態頁面
2.1.1.1導航欄的變色實現
- 檢測當滾動條的滾動具體大于100時為導航欄元素添加一個類名小于時取消類名
- 使用交集選擇器 判斷元素具備兩個類名時才添加背景顏色 隱藏文字 切換相機圖片
2.1.1.2點擊相機發表動態
- 判斷用戶是否登錄 上面當用戶登錄成功后會將用戶的信息存入公共可訪問的store 中,所有可以在store數據中查詢用戶是否登錄
- 如果未登錄跳轉到login登錄頁面 (見主題1)
- 若登錄后跳轉動態發表頁面 (見主題3)
2.1.2 背景圖的切換
- 點擊背景圖像運用weui.actionSheet會彈出一選擇框
- 點擊取消后選框消失
- 點擊從相冊選擇 會通過ref屬性 用代碼進行對uploader中的單擊事件的觸發
- 我們將weui-uploader這模塊隱藏不顯示
- 但uploader被單擊時會執行像主題3.3中的步驟進行圖片的上傳
onSuccess: function (ret) {// 更換用戶的背景圖像self.submit(ret)}
- 上傳成功后我們會觸發submit函數并且將ret圖片的信息作為參數進行傳遞
async submit (obj) {// 更新數據庫中的背景圖像const res = await service.post('users/update', {userId: this.$store.state.currentUser._id,bgurl: obj.data.url})// 更新本地中的北背景圖像if (res.data.code === 0) {this.$store.dispatch('setUser', {...this.$store.state.currentUser,bgurl: obj.data.url})}
- 通過調用接口 更新用戶的背景圖 成功后我們將調用store中的方法改變本地的背景圖
- 在調用store中的方法時我們傳過去的參數中是運用對象的深拷貝(…)
2.1.3 點擊頭像進入用戶中心
- 判斷用戶如果沒有登錄跳轉到login登錄頁面如果已經登錄跳轉到個人中心頁面
- 個人中心功能見主題4
2.2 下半部分
- 動態列表
- 點贊評論
- 頭像點擊查看對方信息
- 圖片的查看
2.2.1 動態列表
- 顯示的頭像信息 昵稱
- 顯示帖子的內容(如果文字較多設置只顯示三行超出隱藏)
overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 3;-webkit-box-orient: vertical;
- 顯示動態中攜帶的圖片(一張圖片按照圖片的最長邊進行成比例縮放,,多張圖片按照固定寬高設置)
<!-- 帖子中如果有多張圖片 按照列表顯示 圖片的尺寸都一樣 --><div class="img-content" v-if="data.picList.length>1"><img v-for="imgInfo in data.picList":key="imgInfo.id":preview="data._id":src="imgInfo.url"class="img-warp"></div><!-- 如果帖子中只有一張圖片 圖片可以放大顯示 要求狂傲不能超過200px --><div class="img-content-one" v-if="data.picList.length===1"><img:src="data.picList[0].url"class="img-warp-one":preview="data._id":style="initImgSize(data.picList[0])"></div>
- 帖子的發表時間,通過moment來進行時間格式化
2.2.2 點贊評論
- 點贊
- 用戶點擊 - - 的時候 出現點贊評論的標識
- 當該用戶已經點過贊時,顯示取消點贊,用戶未點贊時,顯示點贊
- 點贊宇取消點贊都是用過點擊時判斷點贊還是取消來請求后端的不同接口進行修改
- 成功后也要修改store中的本地數據
- 評論
-
獲取當前手指的坐標 并觸發bus中的showInput事件
addComment (e) {// 獲取當前點擊的坐標this.data.pageY = e.pageYthis.data.clientY = e.clientYthis.$bus.$emit('showInput', this.data)}
-
當用戶觸發showInput事件后顯示文本框
-
通過os進行檢測用戶的手機系統評論的文本框也是不同的
this.$bus.$on('showInput', (currentData) => {if (this.$refs.inputBar) {// 顯示輸入框this.showInput = true// 調用輸入框組件的focusInput事件,以彈起鍵盤this.$refs.inputBar.focusInput(currentData)// this.$refs.inputWrap.style.top = currentData.pageY + 'px'// 調整頁面的位置if (os.isIOS) {this.$refs.inputWrap.style.top = currentData.pageY + 'px'// 計算頁面的滾動距離setTimeout(() => {const y = currentData.pageY - window.keyboradHeightwindow.scroll(0, y)}, 300)}}})
- 調用輸入框組件的focusInput事件,以彈起鍵盤
- 調整頁面的位置
- 計算頁面的滾動距離
-
2.2.3 點擊圖片查看大圖
- 通過使用preview來實現圖片的查看
- preview作為元素的動態屬性 值為每組圖片公共值 這里使用發表用戶的_id
- 可以左右滑動進行切換圖片
2.2.4 點擊頭像查看作者信息
- 點擊自己的頭像則會跳轉到主題4
- 點擊其他作者的頭像則會跳轉到用戶信息(傳遞用戶id在路徑中)
- 通過傳遞過來的id進行查尋用戶信息在此進行展示
- 點擊發消息跳轉到聊天頁面(傳遞參數用戶id用戶昵稱到路徑中)主題5
2.3 上劃加載更多
2.4 下拉更新
3. 發表動態頁面
3.1 第一部分(取消發表按鈕)
3.1.1 取消按鈕————回到上一頁面
3.1.2 發布按鈕
- 驗證文字是否為空
- 文字的數量是否合法
- 請求接口進行發布
- 成功后會跳轉到主頁(見主題2)
3.2 第二部分(文本區域)
3.2.1 用戶輸入的文字數量
- 將展示用戶輸入文字數量使用動態數據,通過input事件實時得到文字數量不斷改變變量的值
3.2.2 限定用戶輸入的文字數量為100
- 采用weui中的form文本域
- 通過雙向綁定的元素得知用戶輸入的文字數量,當用戶輸入的文字數量超過100時,獲取文字的內容通過substr屬性取前一百個文字復制給雙向綁定的文字內容的變量造成超出100字不能輸入的現象。
3.3 第三部分(上傳圖片)
3.3.1 采用weui中的uploader技術進行圖片的上傳
在weui中的this指向并不是Vue實例所以在第一行中加入const self=this 讓self常量指向我們的Vue實例
const self = thisweui.uploader('#uploader', {url: service.baseURL + '/post/uploadimg',auto: true,type: 'file',fileVal: 'image',compress: {width: 1600,height: 1600,quality: 0.8},onBeforeQueued: function (files) {// `this` 是輪詢到的文件, `files` 是所有文件if (['image/jpg', 'image/jpeg', 'image/png', 'image/gif'].indexOf(this.type) < 0) {weui.alert('請上傳符合條件的圖片')return false // 阻止文件添加}if (this.size > 10 * 1024 * 1024) {weui.alert('請上傳不超過10M的圖片')return false}// 控制多元每次不能超過五張if (files.length > self.totalUploadCount) {weui.alert('最多只能上傳' + self.totalUploadCount + '張圖片,請重新選擇')return false}// 如果已經上傳五張圖片 作為不能繼續上傳if (self.uploadCount + 1 > self.totalUploadCount) {weui.alert('最多只能上傳' + self.totalUploadCount + '張圖片')return false}self.uploadCount++// return true; // 阻止默認行為,不插入預覽圖的框架},onBeforeSend: function (data, headers) {const token = document.cookie.split('=')[1]headers['wec-access-token'] = token},onProgress: function (procent) {// console.log(this, procent)// return true; // 阻止默認行為,不使用默認的進度顯示},onSuccess: function (ret) {ret.data.id = this.idself.picList.push(ret.data)},onError: function (err) {console.log('error:' + err)// return true; // 阻止默認行為,不使用默認的失敗態}})
- onBeforeQueued
選擇要上傳的圖片時觸發(驗證圖片是否符合要求)- 驗證圖片的格式
- 驗證圖片的大小不能超過10M
- 控制每次選擇圖片不能超過五張
- 控制如果已經選擇五中圖片不能繼續上傳
- onBeforeSend
圖片上傳前觸發- 我們將用戶登錄成功后存入Local Storage中的cuser(token)放到請求頭headers中
- onSuccess
圖片上傳成功后觸發- 將圖片的id存到 ret.data中
- 將圖片的所有信息添加到picList數組中
3.3.2 查看圖片
- 點擊小圖片時可以展現大圖 點擊圖片時會通過e.target拿到事件源
- 通過getAttribute(‘style’)方法獲取style中屬性background-image: url(“blob:http://192.168.0.107:8080/c1e0e8bf-4ac6-4184-a839-0cdcce473aa4”);
- 通過“ " ”進行分割得到第二個元素 也就是路徑
- 將得到的路徑復制給weui.gallery 他具有兩個參數,一個是圖片的路徑,一個是刪除圖片我們在第二個參數中調用刪除圖片的函數并且將圖片的信息以及查看大圖的 div作為參數傳遞過去(見主題3.3.3)(self指向的是this Vue的實例)
preImg (e) {const self = thisconst url = e.target.getAttribute('style').split('"')[1]var gallery = weui.gallery(url, {onDelete: function () {self.deleteImg(e.target, gallery)}})}
3.3.3 刪除圖片
deleteImg (target, gallery) {const self = thisweui.confirm('確認刪除圖片嗎', () => {const id = target.getAttribute('data-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')})}
- 運用weui中的confirm確定是否對刪除圖片
- 確定刪除:通過id找出picList數組中與之相同的圖片信息進行刪除,同時將對應的DOM元素進行刪除
- 上面執行的同時會執行hide事件,將我們現實大圖的div進行隱藏
4. 用戶個人中心
- 導航部分為公用組件 通過父子組件prop進行傳值(頭部導航的文字內容)
- 點擊<按鈕跳轉上一頁面
4.1 更換頭像
- 點擊用戶的頭像時 依靠ref屬性使用代碼觸發隱藏的上傳圖片插件的單擊事件,進而激活uploader進行圖片的上傳
- 上傳成功后分為以下兩步
onSuccess: async function (ret) {// console.log(ret)const res = await service.post('users/update', {userId: self.$store.state.currentUser._id,avatar: ret.data.url})if (res.data.code === 0) {self.$store.dispatch('setUser', {...self.$store.state.currentUser,avatar: ret.data.url})weui.toast('上傳成功', 2000)}}
- 上傳下成功后在此函數中ret中就是上傳成功圖片的所有信息
- 訪問接口并且將用戶id從store中取出以及圖片的地址一并放到請求體中 更新數據庫中的頭像
- 數據庫中的數據更新成功后 會通過調用store中的方法來改變本地的頭像地址 同樣請求體中還是使用對象的深拷貝
4.2 修改用戶昵稱
- 點擊用戶昵稱時會跳轉頁面
- 點擊提交按鈕 驗證文本框內容不能為空
- 請求后端接口修改數據庫中的昵稱
- 成功后通過store中的方法修改本地昵稱
- 最后將文本框內容清空,提示修改成功,2秒后跳轉至個人中心
4.3 更換/發表用戶個性簽名
- 點擊個性簽名時會跳轉頁面
- 展示已有的個性簽名 可更改 可添加
- 點擊提交按鈕 驗證文本框內容不能為空
- 請求后端接口修改數據庫中的個性簽名
- 成功后通過store中的方法修改本地數據
- 最后提示修改成功,2秒后跳轉至個人中心
4.4 切換性別
- 點擊性別時會彈出選項框運用weui中的actionSheet進行性別選擇
weui.actionSheet([{label: '男',onClick: async function () {const res = await service.post('users/update', {userId: self.$store.state.currentUser._id,gender: '1'})if (res.data.code === 0) {self.$store.dispatch('setUser', {...self.$store.state.currentUser,gender: '1'})weui.toast('修改成功', 1000)}}},{label: '女',onClick: async function () {const res = await service.post('users/update', {userId: self.$store.state.currentUser._id,gender: '0'})if (res.data.code === 0) {self.$store.dispatch('setUser', {...self.$store.state.currentUser,gender: '0'})weui.toast('修改成功', 1000)}}}], [{label: '取消',onClick: function () {console.log('取消')}}])
- 點擊取消則會隱藏選項框
- 點擊男,會請求后端接口將gender屬性值設置為‘1’進行更改,成功后更改本地數據
- 點擊女,會請求后端接口將gender屬性值設置為‘0’進行更改,成功后更改本地數據
5. 聊天窗口
- 通過用戶傳遞過來的用戶昵稱顯示在最上方
- 點擊返回按鈕跳轉上一頁面
- 運用vue-socket.io和socket.io-client實現前后端的聊天數據的交互
- 頁面加載時,首先當前用戶登錄socket,獲取當前登錄用戶與當前指定用戶的聊天記錄
6. 頁面之間切換的動畫效果
我們采用animate實現頁面之間的切換 animate樣式官網點擊查看 我們應該將樣式應用到所有組件切換需要必經之路–App.vue
-
首先我要安裝animate
$ npm install animate.css --save
-
在main.js中引用
import ‘animate.css’
-
需要將運用動畫的元素使用標簽包裹起來
<transition:enter-active-class="transitionIN":leave-active-class="transitionOut"><router-view/></transition>
-
里面的enter-active-class是為要切換來的(進場)設置動畫
-
leave-active-class是為要切出(出場)設置動畫,兩屬性值均為動態
-
考慮到不同的頁面切換的動畫應該不同 so我們采用偵聽器來檢測路由的變化進而對個別的頁面做出個性動畫
// 偵聽器:偵聽路由的變化進而應用不同的轉場動畫watch: {$route (to, from) {if (to.name === 'Publish') {this.transitionIN = 'animate__animated animate__slideInUp'this.transitionOut = ''} else if (from.name === 'Publish') {this.transitionIN = ''this.transitionOut = 'animate__animated animate__slideOutDown'} else {this.transitionIN = 'animate__animated animate__slideInLeft'this.transitionOut = 'animate__animated animate__slideOutLeft'}}}
- $route就是監測此時路由 里面的參數: to要跳轉到那個路由,from是從哪里來