背景:樓主目前在一家做電子商務的公司上班,公司已有成熟的商城系統,社區系統,以及CMS框架。
而做社區的,最大的就是騰訊。今年大概三月份的時候,騰訊推出了微社區。推出了就推出了吧,這也沒啥。關鍵是需要使用的人微信服務號超過10000人關注這就受不了了。我們不能為了使用這個平台而去刷關注吧。而巧的是,這個平台讓我們老總給看見了。老總用了幾次,甚是歡喜啊。說是未來是移動手機端的時代,手機用戶會大大多於PC客戶端用戶。而我們主要又是賣產品的,總不能叫客戶去用騰訊的產品吧,而且人騰訊還不讓一般人用。這可如何是好呢?在我們技術團隊面前念叨了好幾次之后,終於忍不住了,咱們自己照着它開發一套吧。
咱們自己開發一套?有沒有搞錯?騰訊那么多人的團隊開發出來的產品,要我們這幾個人去搞?圖1是拉鈎網的微社區。
以上是通過Chrome模擬的Iphone5的界面,Chrome的這一功能真的很強大啊,可以通過瀏覽器直接模擬各種移動端設備。設置方法:先按F12打開調試面板,然后按Esc啟動以下畫面,然后就可以切換設備了,完成之后點擊Emulate,這樣瀏覽器就可以直接當移動設備了。如圖2:
說到Chrome,之前有段時間服務一直無法訪問,現在又可以了,IP:74.125.205.113。
這個事情從三月份就提出來了啊,由於期間各種任務,都抽不出時間,所以一直拖到了6月中旬。那時候恰好我手上的工作忙得差不多了,於是老總發話了,你來吧。
由於此時項目組其他同事都還在忙別的活,而老總又覺得這個東西沒啥功能,所以我就只能硬着頭皮來了。在網上好好的走了一下他的流程。發現具體的功能如下:
加入小組,發表發話,評論話題,分享話題,贊和取消贊,個人主頁,他人主頁,Ta的話題,我的話題,我的消息,帖子詳情,話題分類,話題列表……應我們老總的強烈要求,還得加上個人中心,更改頭像,更改密碼,登錄功能,注冊功能。
還好之前PC端SNS部分做得還算熟練,仔細分析了一下技術上基本沒什么難點。而數據庫表和底層代碼都可復用之前PC端的,所以我更是信誓旦旦的承諾,沒問題!就這樣單槍匹馬的就上陣了,后來那個悔啊……
實現的詳細過程就不細說了,有問題的幾個地方這里記錄下。
第一:發布話題,下圖(圖3)是發布話題頁面,這是騰訊官網的。
從這個圖中我們可以看到,這個發表話題是可以發表表情,圖片(騰訊官網可以發8張),以及文字的,並且對文字的長度做了限制。做發話題的時候遇到了三個問題,一個是我們之前數據庫涉及和底層代碼發表話題時僅支持1張圖片,這部分由於時間問題就沒做修改;一個是這個字數限制:我們都知道textBox可以通過MaxLength屬性來設置最大輸入字符數。可是通過這個屬性設置的一個最大問題就是,不區分中英文。而我們體驗一下騰訊的官網就可以知道,他這個字數限制是區分中英文的。之后的解決方案是:綁定這個textBox的input propertychange事件,同時通過腳本計算可輸入長度,以下腳本是計算輸入字符的長度(區別中英文),但是這樣無法避免粘貼時字數超過限制,上圖就出現了負數;另外一個問題至今還未解決,哪位同僚有解決方案提供將感激不盡。我們看到那個表情是分不同頁的,也就是說可以滑動的!就是這個滑動,至今為找到解決方案。在網上有人說監測TouchStart、TouchMove和TouchEnd事件可以解決,可是試過之后發現結果不太理想啊。所以我這邊暫時的解決方案就是點擊下邊小圓點來實現切換。以下是監測輸入字符的長度:

//字符長度判斷 function textareastrlen(str) { var len; var i; len = 0; for (i = 0; i < str.length; i++) { if (str.charCodeAt(i) > 255) { len += 2; } else { len++; } } if (len % 2 != 0) { len = len + 1; } return parseInt(len / 2); }
第二個就是查看圖片:(以下左圖是騰訊官網的圖片查看效果,右圖是我做出的效果)
開始也是想模擬騰訊的這種效果,直接在上邊加一個遮罩層。后來發現這樣有問題,騰訊這個只要細看也可以看出問題,遮罩層下邊的內容其實在移動。另外一個缺陷就是圖片點擊放大后,位置控制不好,在PC端位置居中了可是到了手機上位置硬是不能居中,后來無奈之下用了之前用的一款神器插件:PhotoSwipe,這是一款很強大的圖片查看器,還可以自動滑動,詳細介紹請看Demo。
第三個就是今天要給源碼的分頁問題。一般在PC上我們要分頁都是通過上一頁和下一頁來實現的,可是在手機端如果還通過這種方式分頁的話用戶的體驗會大大的下降,所以就通過當下滑到一定程度的時候自動加載下一頁面。而那個程度怎么監測呢,我們可以通過頁面上的某個元素來檢查。實現思路:首先加載部分數據,當下滑到某個元素可見的時候,如果還有數據,則新發送請求,然后追加在當前頁面。以下是頁面代碼:

@foreach (var item in Model.TopicList) { <div class="topicBox" id="t_@(Model.Topic.TopicID)"> </div> }
注意,由於這里是一個foreach循環,所以我可以監測最后一個class為topicBox的div元素,如果他出現在當前可視區域了,則說明該向后台發請求了。監測是否在可視區域代碼:

//判斷元素是否進入可視區域 function see(objLiLast) { //瀏覽器可視區域的高度 var see = document.documentElement.clientHeight; //滾動條滑動的距離 var winScroll = $(this).scrollTop(); //距離瀏覽器頂部的 var lastLisee = $(objLiLast).offset().top; return lastLisee < (see + winScroll) ? true : false; }
發送請求代碼:

var page = 1; var pageTotal = parseInt($("#allpage").val()); //是否請求出AJAX的“開關”; var onOff = true; $(window).scroll(function () { //拖動滾條時,是否發送AJAX的一個“開關” $(".topicBox").each(function () { //引用最后一個div var lastLi = $(".topicBox:last"); //調用是否進入可視區域函數 var isSee = see(lastLi); if (isSee && onOff && page < pageTotal) {//最底部元素可見,開關開啟而且還有下拉 $("#loadNext").show(); //顯示正在加載圖標 onOff = false; $.ajax({ url: "@(ViewBag.BasePath)Home/GetPageData", type: "POST", dataType: "Json", data: { page: page+1 }, asyc: false, success: function (result) { if (result.status == "success") { var data = result.result; for (var i = 0; i < data.length; i++) { if (data[i].imageUrl) {//有圖片 $("#allThreadList").append('xxx'); } else {//無圖片 $("#allThreadList").append('xxx'); } $("#t_" + data[i].topicId).append('<div class="topicList" id="topic_' + data[i].topicId + '"><ul id="replyList_' + data[i].topicId + '" class="replyUl" itemid="' + data[i].topicId + '"> </ul> </div>'); var replyList = data[i].replyList; if (replyList) { if (replyList.length > 3) {//3條評論以上 for (var j = 0; j < 3; j++) { $("#replyList_" + data[i].topicId).append('<li id="p_6_13" uid="6419340" author="ff。"><a href="javascript:;" class="sW fl"><span>' + data[i].replyList[j].replynickName + ':</span>' + data[i].replyList[j].replyContent + '</a></li>'); } $("#topic_" + data[i].topicId).append('<p id="rCount_6" class="more"><a href="@(ViewBag.BasePath)MSNS/Home/TopicReply/' + data[i].topicId + '?viewName=TopicDetail">更多</a>共<span class="replyCount" itemid="' + data[i].topicId + '">' + data[i].replyList[j].replyCount + '</span>條評論</p>'); } else {//評論數小於三條 for (var h = 0; h < replyList.length; h++) { $("#replyList_" + data[i].topicId).append('<li id="p_6_13" uid="6419340" author="ff。"><a href="javascript:;" class="sW fl"><span>' + data[i].replyList[h].replynickName + ':</span>' + data[i].replyList[h].replyContent + '</a></li>'); } } } }; } $("#loadNext").hide(); //隱藏正在加載 onOff = true; page ++; } }); } }); });
這是前台請求的代碼,注:因為請求回來需要追加的元素較多,所以這里代碼會有點亂,但是不影響功能。后台代碼:

groupInfo.TopicList = new PagedList<Model.SNS.GroupTopics>( bllTopic.GetTopicListPageByGroup(GroupId, startIndex, endIndex, false) , page, pagesize, toalcount); if (groupInfo.TopicList != null && groupInfo.TopicList.Count > 0)//有話題 { Model.SNS.GroupTopics groupTopics; JsonObject jsonObject; JsonObject reply; HttpCookie cookie; List<JsonObject> replyList=new List<JsonObject>(); List<JsonObject> resultList=new List<JsonObject>(); foreach (Model.SNS.GroupTopics item in groupInfo.TopicList)//遍歷話題列表 { groupTopics = groupTopicsBll.GetModelByCache(item.TopicID); jsonObject=new JsonObject(); if (null != groupTopics) { if (null != CurrentUser) { cookie = Request.Cookies["topicFav_" + groupTopics.TopicID + CurrentUser.UserID]; if (null != cookie) //取消贊 { jsonObject.Put("support", "support"); } else { jsonObject.Put("support", "nosupport"); } } jsonObject.Put("uid", groupTopics.CreatedUserID); jsonObject.Put("topicId", groupTopics.TopicID); jsonObject.Put("nickName",groupTopics.CreatedNickName); jsonObject.Put("createdDate", Web.Components.DateTimeHelper.ConvertDateToTime(groupTopics.CreatedDate)); jsonObject.Put("description",Server.HtmlDecode(ViewModel.ViewModelBase.ReplaceFace(groupTopics.Description))); jsonObject.Put("imageUrl", Web.Components.FileHelper.GeThumbImage(groupTopics.ImageUrl, "T180X120_")); jsonObject.Put("ref", groupTopics.ImageUrl); jsonObject.Put("favCount",groupTopics.FavCount); List<Model.SNS.GroupTopicReply> list = bllReply.GetTopicReplyByTopic(groupTopics.TopicID, startIndex, endIndex); if (null != list && list.Count > 0) { foreach (Model.SNS.GroupTopicReply topicReply in list) { reply = new JsonObject(); reply.Put("replynickName", topicReply.ReplyNickName); reply.Put("replyContent", Server.HtmlDecode(ViewModel.ViewModelBase.ReplaceFace(topicReply.Description))); reply.Put("replyCount", list.Count); replyList.Add(reply); } jsonObject.Put("replyList", replyList); } } resultList.Add(jsonObject); } // return new Result(ResultStatus.Success,resultList); json.Put("status", "success"); json.Put("result", resultList); return Json(json); }
至此,整個滑動分頁就完成了。其他的功能開發起來都還算順利,如果對功能實現有疑問的歡迎大家一起交流,謝謝。