微信小程序最近很火,火到什么程度,只要你一打開微信,就是它的身影,幾乎你用的各個APP都可以在微信中找到它的復制版,另外官方自帶的跳一跳更是將它推到了空前至高的位置。對比公眾號,就我的感覺來說,有以下區別:
廢話說了這么多,我也是最近才開始看小程序的實現方式,體驗了一把,確實比較爽,以下就是個人開發總結: 簡易的官網小程序 微信小程序官網中有個簡單的小demo,地址在這里:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html,按照它的步驟來,一定是可以運行一個和官方一樣的例子出來的,這里就不貼過程了。主要說一下個人整體感受:
開發一個類似微信UI的簡單聊天程序 只是感興趣稍微做了一下案例,其中功能可能根本就還只是九牛一毛,但是覺得有必要記錄一下,說說自己遇到的問題以及解決辦法,界面整體如下: ![]()
首先,在app.json中編寫頁面路由,如下: { "pages":[ "pages/index/index", "pages/list/list", "pages/chat/chat" ], "window":{ "backgroundTextStyle":"light", "navigationBarBackgroundColor": "#000", "navigationBarTitleText": "WeChat", "navigationBarTextStyle":"#fff" } } 這里有3個頁面,首頁放一個按鈕作為入口,列表頁表示聊天記錄,還有一個聊天頁。 列表頁沒有什么可以講的,設置列表頁的標題可以在list.json中設置即可,如下: // list.json { "navigationBarTitleText": "聊天列表" } 列表頁模擬了一些數據,然后再點擊每一條的時候,進入單個聊天頁面當中,其中需要將當前點擊的一些信息傳入下一個頁面當中,這里僅僅只有名字。 //chat.js //獲取應用實例 const app = getApp() const friends = require('./list-mock-data.js') Page({ data: { friends: friends.list }, gotoChat(event) { const currentUser = event.currentTarget.dataset.user; wx.navigateTo({ url: '../chat/chat?nickname=' + currentUser.nickname }) } })
然后進入聊天頁面,首先進入聊天頁面我想到的是,每一個氣泡加上它的頭像是否可以做成一個組件,因為只有左右的區分而已,另外如果再加上時間的話,再將時間傳遞過去就可以了。 因此chat.wxml最開始就是這樣規劃的: <block wx:for="{{ messages }}" wx:key="messages{{ index }}" > <template id="{{ item.id }}" is="bubble" data="{{ ...item }}" /> </block> template中的代碼就不展示了,最開始我寫模板的時候,是開了一個codePen,然后模擬寫出來之后,再往模板中套,保證基本的樣子差不多,然后再在模板上進行細微的改動就可以了。 聊天頁頂部的標題是通過列表頁中傳過來的,在頁面加載完成的時候,設置就好了: // chat.js // 設置昵稱 setNickName(option) { const nickname = option.nickname || 'Marry'; wx.setNavigationBarTitle({ title: nickname }); },
最開始的樣子就是這樣子的:
至此,基本的頁面形態就已經完成了。 遇到的一些問題:
每次進入頁面的時候,即使聊天內容已經超過了聊天區域,都會顯示為最開始的地方 好在天無絕人之路,看到了scroll-view中的scroll-into-view屬性,于是就想出了解決上面兩個問題的方法:
進入頁面,獲取歷史紀錄,獲取最后一條消息的ID值,記為lastId,在渲染的時候,消息列表中的每個ID值傳入組件,作為每個消息記錄的唯一標識,然后使用scroll-in-view={{ id }}就可以輕松地使最后一條消息進入視野當中 // chat.wxml <scroll-view scroll-y scroll-with-animation class="chat-content" scroll-top="{{ scrollTop }}" scroll-into-view="{{ lastId }}"> <block wx:for="{{ messages }}" wx:key="messages{{ index }}" > <template id="msg{{ index }}" is="bubble" data="{{ ...item }}" /> </block> </scroll-view> // chat.js Page({ data: { messages: [], // 聊天記錄 msg: '', // 當前輸入 lastId: '' // 最后一條消息的ID // ... }, // ... send() { // ... const data = { id: `msg${++nums}`, message: msg, messageType: 0, url: '../../images/5.png' }; this.setData({ msg: '', lastId: data.id }); } }); 這樣就可以大致實現類似于聊天的效果了,但是還有一個小問題,每次從列表中進入單個聊天頁面的時候,會有一個斜向左上方滑動的過程,原因是:頁面的轉場動畫是向左的,但是自動滾動到最后一條記錄的動作是向上的,所以會有動作疊加,既然這樣,我只需要讓滾動的過程延遲一段時間就好. // 延遲頁面向頂部滑動 delayPageScroll() { const messages = this.data.messages; const length = messages.length; const lastId = messages[length - 1].id; setTimeout(() => { this.setData({ lastId }); }, 300); },
至此問題就算是解決了,在真機模擬的時候,IOS還有一個問題,就是當點擊輸入框的時候,整體頁面會向上頂起來,這個問題我在論壇中也有看到,但是沒有找到解決辦法,如果各位有遇到,還望不吝賜教。
擴展延伸
由于當時自己的機器由于莫名的原因不能夠進行登錄,后來采用了本地開了一個websocket的服務器來實現消息的發送。服務器代碼相當簡單,只是消息的轉發而已
// server.js const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 12112 }); wss.on('connection', ws => { console.log('connection established'); ws.on('message', message => { console.log("on message coming"); ws.send(message); }); });
在chat.js中需模擬歷史消息的發送以及新加消息的發送,因此代碼整體看起來是這樣的: //chat.js //獲取應用實例 const app = getApp() const msgs = require('./chat-mock-data.js'); Page({ data: { messages: [], // 聊天記錄 msg: '', // 當前輸入 scrollTop: 0, // 頁面的滾動值 socketOpen: false, // websocket是否打開 lastId: '', // 最后一條消息的ID isFirstSend: true // 是否第一次發送消息(區分歷史和新加) }, onLoad(option) { // 設置標題 this.setNickName(option); }, //事件處理函數 onReady() { // 連接websocket服務器 this.connect(); }, onUnload() { const socketOpen = this.data.socketOpen; if (socketOpen) { wx.closeSocket({}); wx.onSocketClose(res => { console.log('WebSocket 已關閉!') }); } }, connect() { wx.connectSocket({ url: 'ws://localhost:12112' }); wx.onSocketOpen(res => { this.setData({ socketOpen: true }); // 模擬歷史消息的發送 wx.sendSocketMessage({ data: JSON.stringify(msgs), }) }); wx.onSocketMessage(res => { const isFirstSend = this.data.isFirstSend; const data = JSON.parse(res.data); let messages = this.data.messages; let lastId = ''; // 第一次為接收歷史消息, // 之后的為新加的消息 if (isFirstSend) { messages = messages.concat(data); lastId = messages[0].id; this.setData({ messages, lastId, isFirstSend: false }); // 延遲頁面向頂部滑動 this.delayPageScroll(); } else { messages.push(data); const length = messages.length; lastId = messages[length - 1].id; this.setData({ messages, lastId }); } }); wx.onSocketError(res => { console.log(res); console.log('WebSocket連接打開失敗,請檢查!') }) }, // 設置昵稱 setNickName(option) { const nickname = option.nickname || 'Marry'; wx.setNavigationBarTitle({ title: nickname }); }, // 延遲頁面向頂部滑動 delayPageScroll() { const messages = this.data.messages; const length = messages.length; const lastId = messages[length - 1].id; setTimeout(() => { this.setData({ lastId }); }, 300); }, // 輸入 onInput(event) { const value = event.detail.value; this.setData({ msg: value }); }, // 聚焦 onFocus() { this.setData({ scrollTop: 9999999 }); }, // 發送消息 send() { const socketOpen = this.data.socketOpen; let messages = this.data.messages; let nums = messages.length; let msg = this.data.msg; if (msg === '') { return false; } const data = { id: `msg${++nums}`, message: msg, messageType: 0, url: '../../images/5.png' }; this.setData({ msg: '' }); if (socketOpen) { wx.sendSocketMessage({ data: JSON.stringify(data) }) } } })
整體來說,自己的思路就像是上面的代碼所描述的,這個只是初步的構想,還有很多東西需要完善:
頭像 我只是一只小菜鳥,但我并沒有停下學習的腳步^_^ 另外,覺得這篇文章不錯,可以隨手點個贊么?求星星 |