[打怪升級]小程式評論回覆和發貼功能實戰(一)

前端智酷方程發表於2019-07-11

image

在學習成長的過程中,常常會遇到一些自己從未接觸的事物,這就好比是打怪升級,每次打倒一隻怪,都會獲得經驗,讓自己進步強大。特別是我們這些做技術的,逆水行舟不進則退。下面分享下小程式開發中的打怪升級經歷~

效果圖

先來看下實際效果圖,小程式開發中有時會要做一些的功能複雜的元件,比如評論回覆和發帖功能等,這次主要講的是關於評論模組的一些思路和實戰中的經驗,希望能拋磚引玉,給大家一些啟發,一同成長~

>>(最下面有實戰demo的地址,可以直接瀏覽器開啟新增至IDE工具中) <<

評論元件流程圖

根據這個demo.gif,本人做了一個簡單的流程圖,幫助大家理解。下面羅列一些開發中需要“打的怪”:

1、元件目錄結構

├─components      ---小程式自定義元件
│  ├─plugins      --- (重點)可獨立執行的大型模組,可以打包成plugins
│  │  ├─comment         ---評論模組
│  │  │  │  index.js
│  │  │  │  index.json
│  │  │  │  index.wxml
│  │  │  │  index.wxss
│  │  │  │  services.js    ---(重點)用來處理和清洗資料的service.js,配套模板和外掛
         │      
         └─submit    ---評論模組子模組:提交評論
                 index.js
                 index.json
                 index.wxml
                 index.wxss

複製程式碼

為什麼要單獨做個評論頁面頁面(submit)? 因為如果是當前頁面最下面input輸入的形式,會出現一些相容問題,比如:

  • 不同手機的虛擬鍵盤高度不同,不好絕對定位和完全適配
  • 彈窗輸入框過小輸入不方便,如果是大的textare時,容易誤觸下面評論的交。

注:目錄結構,僅供參考。

2、NODE端API介面返回結構和頁面結構

//node:API介面返回
{
    "data": {
        "commentTotal": 40,
        "comments": [
            {
                "contentText": "喜歡就關注我",   //評論內容
                "createTime": 1560158823647,    //評論時間
                "displayName": "智酷方程式",       //使用者名稱
                "headPortrait": "https://blz.nosdn.127.net/1/weixin/zxts.jpg",  //使用者頭像
                "id": "46e0fb0066666666",  //評論ID  用於回覆和舉報
                "likeTotal": 2,    //點贊數
                "replyContents": [   //回覆評論
                    {
                        "contentText": "@智酷方程式  喜歡就回復我",   //回覆評論內容
                        "createTime": 1560158986524,   //回覆時間
                        "displayName": "神祕的前端開發",   //回覆的使用者名稱
                        "headPortrait": "https://blz.nosdn.127.net/1/2018cosplay/fourth/tesss.jpg",  //回覆的使用者頭像
                        "id": "46e0fb00111111111",   //回覆評論的ID
                        "likeTotal": 2,    //回覆評論的點贊數
                        "replyContents": [],   //回覆的回覆 蓋樓
                        "replyId": "46e0fb001ec222222222",   //回覆評論的獨立ID,用於統計
                    },
                    {
                        "contentText": "@智酷方程式: 威武,學習學習",
                        "createTime": 1560407232814,
                        "displayName": "神祕的前端開發",
                        "headPortrait": "https://blz.nosdn.127.net/1/2018cosplay/fourth/tesss.jpg",
                        "id": "46e0fb00111111111",
                        "likeTotal": 0,
                        "replyContents": [],
                        "replyId": "46e0fb001ec222222222",
                    }
                ],
                "replyId": "",
                "topicId": "46e0fb001ec3333333",
            }
        ],
        "curPage": 1,  //當前頁面
        //通過ID 判斷  當前使用者點讚了 哪些評論
        "likes": [
            "46e0fb00111111111",    
            "46e0fb001ec222222222",
            "46e0fb0066666666",
        ],
        "nextPage": null, //下一頁
        "pageSize": 20,  //一頁總共多少評論
        "total": 7,   //總共多少頁面
    },
    "msg": "success",
    "status": "success"
}
複製程式碼
<!-- HTML 部分 -->
<block wx:if="{{commentList.length>0}}">
    <!-- 評論模組 -->
    <block wx:for="{{commentList}}" wx:for-item="item" wx:for-index="index" wx:key="idx">
        <view class="commentItem" catchtap="_goToReply" data-contentid="{{item.id}}" data-replyid="{{item.id}}"
            data-battle-tag="{{item.displayName}}">
            <view class="titleWrap">
                <image class="logo" src="{{item.headPortrait||'預設圖'}}"></image>
                <view class="authorWrap">
                    <view class="author">{{item.displayName}}</view>
                    <view class="time">{{item.createTime}}</view>
                </view>
                <view class="starWrap" catchtap="_clickLike" data-index="{{index}}" data-like="{{item.like}}"
                    data-contentid="{{item.id}}" data-topicid="{{item.topicId}}">
                    <text class="count">{{item.likeTotal||""}}</text>
                    <view class="workSprite icon {{item.like?'starIconHasClick':'starIcon'}}"></view>
                </view>
            </view>
            <view class="text">
                {{item.contentText}}
            </view>
        </view>
        <!-- 評論的評論 -->
        <block wx:for="{{item.replyContents}}" wx:for-item="itemReply" wx:for-index="indexReply" wx:key="idxReply">
            <view class="commentItem commentItemReply" catchtap="_goToReply" data-contentid="{{itemReply.id}}"
                data-replyid="{{item.id}}" data-battle-tag="{{itemReply.displayName}}">
                ... 和上面類似
            </view>
        </block>
    </block>
    <!-- 載入更多loading -->
    <block wx:if="{{isOver}}">
        <view class="more">評論載入完成</view>
    </block>
</block>
複製程式碼

通過node提供一個API介面,通過使用者的openId來判斷是否點贊,這裡提供一個參考的JSON結構。 JSON儘量做成array迴圈的結構方便渲染,根據ID來BAN人和管理。底部加上載入更多的效果,同時,記得做一些相容,比如預設頭像等。

3、評論中的一些微信原生互動

這裡建議很多互動如果不是必須要特別定製,可以才用微信原生的元件,效果和相容性都有保障,而且方便簡單。

對評論進行回覆/舉報

<!-- HTML部分 通過繫結事件:_goToReply 進行互動-->
<view class="commentItem" catchtap="_goToReply" data-contentid="{{item.id}}" data-replyid="{{item.id}}"
    data-battle-tag="{{item.displayName}}">
    ... 內部省略
</view>
複製程式碼
//JS部分  微信原生wx.showActionSheet 顯示操作選單互動
_goToReply(e) {
    //  上面的各種授權判斷省略...
    let self = this;
    wx.showActionSheet({
        itemList: ['回覆', '舉報'],
        success: function (res) {
            if (!res.cancel) {
                console.log(res.tapIndex);
                //前往評論
                if (res.tapIndex == 0) {
                    //判斷是否是 評論的評論
                    self._goToComment(replyid);
                }
                //舉報按鈕
                if (res.tapIndex == 1) {
                    //彈出框
                    self.setComplain(contentid);
                }
            } else { //取消選擇
                
            }
        },
        fail(res) {
            console.log(res.errMsg)
        }
    });
}
//當選擇“舉報”的時候,二次呼叫 wx.showActionSheet 方法
setComplain(contentid){
    let complainJson = ["敏感資訊", "色情淫穢", "垃圾廣告", "語言辱罵", "其它"];
    wx.showActionSheet({
        itemList: complainJson,
        success: async res => {
            if (!res.cancel) {
                //選擇好後,提交舉報
                try {
                    let complainResult = await request.postComplainReport(complainJson[index], openid, contentid);
                    if (complainResult.msg == "success") {  //提交成功後反饋

                    } else {

                    }
                } catch (e) {
                    console.log(e)
                }
            }
        }
    });
}
複製程式碼

顯示操作選單 wx.showActionSheet 方法說明

屬性 型別 說明
itemList Array. 按鈕的文字陣列,陣列長度最大為 6
itemColor string 按鈕的文字顏色
success function 介面呼叫成功的回撥函式
fail function 介面呼叫失敗的回撥函式
complete function 介面呼叫結束的回撥函式(呼叫成功、失敗都會執行)

使用這個方法,即是主流的做法,也能很好的相容不同機型,同時給予使用者“習慣性體驗”。

原生評論排序切換

評論排序切換示例

<!-- picker元件  html部分-->
<picker bindchange="bindPickerChange" value="{{index}}" range="{{array}}">
    <view class="picker">
        當前選擇:{{array[index]}}
    </view>
</picker>
複製程式碼
// js部分
Page({
    data:{
        //檢視評論型別切換
        array: ["最佳", "最新", "只看自己"],
        //選擇陣列中的第幾個顯示
        index:0
    },
    bindPickerChange(e) {
        console.log('picker傳送選擇改變,攜帶值為', e.detail.value)
        this.setData({
            index: e.detail.value
        })
    }
})
複製程式碼

picker元件是一個從底部彈起的滾動選擇器,這裡我們用它來切換不同評論的排序。每次切換都可以通過 bindchange獲得對應的變化,通過 e.detail.value獲取使用者選擇的索引值。
官方文件:
developers.weixin.qq.com/miniprogram…

4、傳參跳轉寫評論頁

let uriData = {
    logo: "xxx.jpg",
    type: "commentReply",
    title: "文章:小程式評論,動態發帖開發指北\n 作者:智酷方程式",
    openId:"xxxxxxxxxxx",
    replyId:"aaaaaa"   //使用者回覆的是哪個評論的ID
};
wx.navigateTo({ url: `/components/plugins/comment/submit/index?uriData=${encodeURIComponent(JSON.stringify(uriData))}` });
複製程式碼

這個可以用encodeURIComponent的方式處理下引數中的中文,避免跳轉發布評論頁接收資料時出現亂碼。

5、發表評論頁

發表評論頁

顯示和控制評論的字數

<!-- html部分  關於textarea 的配置 -->
<view class='feedback-cont'>
    <textarea auto-focus="true" value="{{replyName}}" maxlength="200" bindinput="textareaCtrl"
        placeholder-style="color:#999;" placeholder="留下評論,共同學習,一起進步" />
    <view class='fontNum'>{{content.length}}/200</view>
</view>
<view class='feedback-btn' bindtap='commentSubmit'>提交</view>
複製程式碼
// js部分
Page({
    data: {
        //初始化評論內容,如果是回覆則通過傳參變成 @xxxx的形式
        content: "@xxxx",
    },
    textareaCtrl: function (e) {
        if (e.detail.value) {
            this.setData({
                content: e.detail.value
            })
        } else {
            this.setData({
                content: ""
            })
        }
    }
})
複製程式碼

textarea 在小程式中改動不大,這個標籤原有的一些屬性都可以繼續使用,通過配置maxlength來控制字數,同時,設定auto-focus="true"可以讓使用者進到這個發表評論頁面時自動彈出虛擬鍵盤和游標定位在輸入的區域。

當然,也可以將發表評論評論展示區域做在一起,這個就要考慮到要麼通過“小程式API”獲取鍵盤高度,要麼將“釋出評論”置頂區域顯示,也是可以做的,只是相對考慮的點會多些。當時開發評論元件的時候,考慮開發時間短和使用者體驗,權衡後,最終決定以上方案,希望能給到大家一些參考和借鑑,在其他元件開發中觸類旁通。

[程式碼片段]評論回覆元件實戰demo

demo的微信路徑:developers.weixin.qq.com/s/oHs5cMma7…

demo的ID:oHs5cMma7N9W

如果你裝了IDE工具,可以直接訪問上面的demo路徑

通過程式碼片段將demo的ID輸入進去也可新增:

瀏覽器開啟路徑
開啟程式碼片段

總結,“元件化思想”對於無論做小程式、react/VUE還是其他專案來說,減少重複開發,提高複用性都是一個非常重要的點。評論功能其實只要理清楚整體思路,做起來難度並不大,通過一些原生元件,可以大大提高開發效率,同時保證良好的相容性。 後面一期還將分享下功能點較多的發帖元件開發。

往期回顧:
[填坑手冊]小程式Canvas生成海報(一)
[拆彈時刻]小程式Canvas生成海報(二)
[填坑手冊]小程式目錄結構和component元件使用心得

[打怪升級]小程式評論回覆和發貼功能實戰(一)

[打怪升級]小程式評論回覆和發貼功能實戰(一)

相關文章