JavaScript使用DeviceOne開發(fā)實(shí)戰(zhàn)(三)仿微信應(yīng)用
這是一個(gè)系列的文檔,長期目標(biāo)是利用DeviceOne開發(fā)一些目前使用廣泛的優(yōu)質(zhì)手機(jī)應(yīng)用,我們會(huì)最大化的實(shí)現(xiàn)這些應(yīng)用的每一個(gè)功能和細(xì)節(jié),不只停留在簡單的UI模仿和Demo階段,而是一個(gè)基本可以使用的實(shí)際App。
在實(shí)現(xiàn)的過程中,會(huì)有很多困難,還會(huì)發(fā)現(xiàn)有一些功能目前缺乏組件支持而無法實(shí)現(xiàn),也會(huì)碰見各種移動(dòng)開發(fā)中都會(huì)碰到的常見技術(shù)問題。一步一步的操作和問題的解決可以讓開發(fā)者直觀的了解通過DeviceOne如何開發(fā)一個(gè)實(shí)際App,也可以了解移動(dòng)開發(fā)本身的很多技術(shù)細(xì)節(jié),可以讓App開發(fā)者少走很多彎路。
這個(gè)文檔主要介紹微信的模仿。
第一部分是框架的搭建
UE和UI設(shè)計(jì),通常App的開發(fā)需要產(chǎn)品人員的UE設(shè)計(jì)和美工人員的UI設(shè)計(jì),這二個(gè)步驟完成后才開始功能實(shí)現(xiàn)。我們現(xiàn)在是模仿已有的微信,這些步驟都可以省去,看下圖是美工提供的主界面UI設(shè)計(jì)圖,里面的元素的尺寸都標(biāo)記了。
1.新建項(xiàng)目:我們選擇了Simple template,選擇空模板是因?yàn)槲覀兛梢愿?xì)致的講解開發(fā)的過程。實(shí)際上這個(gè)項(xiàng)目是可以選擇Multi View with ViewShower模板更合適。
2.簡單分析一下主界面,整個(gè)主界面的尺寸是iphone6的尺寸750*1334. 分上下二個(gè)部分,底部是一個(gè)Bottom Bar導(dǎo)航欄,上面是4個(gè)獨(dú)立的界面,這4個(gè)界面永遠(yuǎn)只有一個(gè)界面顯示,其他三個(gè)界面在內(nèi)存中,靠底部的導(dǎo)航來切換,這個(gè)適合用do_ViewShower為框架的主體如下圖:
對(duì)應(yīng)這個(gè)設(shè)計(jì),我們在新建的項(xiàng)目上刪除自動(dòng)生成的button,添加一個(gè)do_ALayout組件和do_ViewShower組件,設(shè)置它們的高寬和x,y坐標(biāo):
3.接下來我們?yōu)閂iewShower增加4個(gè)分頁,在這里我還強(qiáng)調(diào)一下,實(shí)際App會(huì)多人參與,我們的代碼結(jié)構(gòu)要清晰易讀,命名盡量使用英文,實(shí)在不行使用中文全拼,包括要建立多級(jí)子目錄,不要都混在一起。在這里我們增加4個(gè)子目錄:chats, contacts, discover, me. 右鍵每個(gè)子目錄,選擇New--Other--DeviceOne--UI File,創(chuàng)建4個(gè)index.ui,對(duì)應(yīng)的index.ui.js會(huì)自動(dòng)生成。
這里注意把這4個(gè)ui文件對(duì)應(yīng)的根節(jié)點(diǎn)ALayout的高度設(shè)置為1220,因?yàn)檫@4個(gè)ui文件都是主界面的ViewShower的子view,不應(yīng)該超過ViewShower的大小。
另外為每個(gè)ui里都添加一個(gè)label,標(biāo)記中文名,只是一會(huì)兒debug看真實(shí)效果更清楚。
4.Bottom Bar內(nèi)簡單添加4個(gè)按鈕,然后添加相應(yīng)的js代碼實(shí)現(xiàn)ViewShower的頁面切換功能。這里提一個(gè)技巧,選中2個(gè)或以上組件,可以使用各種對(duì)齊方式的功能,如下圖:
5.在index.ui.js里添加ViewShower初始化的代碼和按鈕的點(diǎn)擊事件。
var viewshower = ui("viewshower"); var page = sm("do_Page"); // 為viewshower增加4個(gè)子頁面 viewshower.addViews([ { id : "chats",// 頁面的標(biāo)示 path : "source://view/chats/index.ui"http:// 頁面的路徑 }, { id : "contacts", path : "source://view/contacts/index.ui" }, { id : "discover", path : "source://view/discover/index.ui" }, { id : "me", path : "source://view/me/index.ui" } ]); // 初始化先顯示第一個(gè)頁面 viewshower.showView("chats"); var button1 = ui("do_Button_1"); button1.on("touch", function() { viewshower.showView("chats"); }); var button2 = ui("do_Button_2"); button2.on("touch", function() { viewshower.showView("contacts"); }); var button3 = ui("do_Button_3"); button3.on("touch", function() { viewshower.showView("discover"); }); var button4 = ui("do_Button_4"); button4.on("touch", function() { viewshower.showView("me"); });
6.我們來真機(jī)看看運(yùn)行效果,啟動(dòng)設(shè)計(jì)器的調(diào)試服務(wù),啟動(dòng)手機(jī)端的調(diào)試程序,最后我們看到的效果圖如下,iOS和Android界面完全一樣。點(diǎn)擊底部的4個(gè)按鈕,切換效果都是好的:
7. 這一節(jié)的內(nèi)容就到這里,框架工作完成了嗎?只能說框架的第一步工作完成,如果我們有很多同事一起開發(fā)這個(gè)App的話,我們可以把工作開始分開并行,接下來分5個(gè)部分:
* Bottom Bar的完成
* /chats/index.ui的完成
* /contacts/index.ui的完成
* /discover/index.ui的完成
* /me/index.ui的完成
多人并行工作的前提是代碼版本管理比如SVN,GIT,我們這里使用GIT,地址是https://github.com/do-project/Fake-Weixin,每一節(jié)結(jié)束后我們都會(huì)提交GIT服務(wù),你可以下載這個(gè)節(jié)點(diǎn)的代碼參考。我們也會(huì)在附件附加這一節(jié)的項(xiàng)目代碼。
下一節(jié)我們完成第一個(gè)子任務(wù),BottomBar的實(shí)現(xiàn)。
-------------------------------------------------------------
這一節(jié)主要是完成底部導(dǎo)航欄的實(shí)現(xiàn)。
0. 我們首先來分析一下界面效果圖和設(shè)計(jì)圖
整個(gè)底部導(dǎo)航分4個(gè)重復(fù)的部分,每個(gè)部分由一個(gè)圖片ImageView和底部標(biāo)題Label,以及右上角標(biāo)示,這個(gè)標(biāo)示可以用圓角Label來實(shí)現(xiàn),這個(gè)標(biāo)示缺省的時(shí)候應(yīng)該是隱藏的。
1. 第一步我們得找到對(duì)應(yīng)的圖片資源,通常開發(fā)這些資源由美工提供,我們現(xiàn)在模仿微信,最好的方式是從微信原生安裝包里獲取,不能直接靠截圖,而是打開微信ios,android安裝包,ios的安裝包是ipa和android的安裝包apk都是一個(gè)壓縮文件,解開可以獲取到一些圖片資源。目前我只需要底部8個(gè)圖標(biāo),包括未點(diǎn)中以及點(diǎn)中的高亮圖標(biāo),外面把這些圖標(biāo)放在image目錄下
2. 先刪除先前增加的4個(gè)臨時(shí)按鈕,然后按照美工提供的尺寸數(shù)據(jù)布局好新的組件,包括4個(gè)do_ImageView組件和4個(gè)Label組件以及4個(gè)右上角的Label
簡單計(jì)算可以得出ImageView的大小是60*60。這里有一個(gè)小技巧,設(shè)置好一組ImageView和Label后選中2個(gè)組件,然后右鍵“Copy”,然后再"Paste"三次,還可以選中多個(gè)組件各種對(duì)齊。
再細(xì)調(diào)一下,把圖片和文字設(shè)置好,圖片設(shè)置就是設(shè)置ImageView的source屬性,Label需要設(shè)置文字居中,設(shè)置textAlign屬性為center,設(shè)置字體,設(shè)置背景色,前景色等等,設(shè)置右上角三個(gè)Label的visible為false。中間添加一個(gè)ALayout設(shè)置背景為灰色,作為ViewShower和Bottom Bar上下的分割線. 這里要注意,右上角的正圓形Label的實(shí)現(xiàn)方式就是設(shè)置border屬性,border設(shè)置為FF0000FF,1,15 表示邊界線的顏色是紅色,寬度1,圓角半徑15(Label的寬高都是30),從而實(shí)現(xiàn)正圓。
在真機(jī)上測試一下效果,iPhone和Android手機(jī)真機(jī)的效果圖如下:
<ignore_js_op>
3. 這個(gè)時(shí)候會(huì)有2個(gè)問題,如果給ImageView上添加點(diǎn)擊事件的話,用戶必須點(diǎn)中這個(gè)圖片才能觸發(fā)點(diǎn)擊,這樣體驗(yàn)不好。第二個(gè)問題是圖片在Android上稍微有點(diǎn)變形,如果在比如iPhone4上,可能圓形會(huì)變成橢圓,這個(gè)問題是由于不同手機(jī)寬高比的差異。
要解決的辦法是:
* 把Bottom Bar所在的ALayout增加4個(gè)一樣大小的子ALayout,然后把imageview,label都放在對(duì)應(yīng)的子ALayout上,然后給子ALayout增加點(diǎn)擊事件,這樣用戶的手指只要接觸到差不多位置都能觸發(fā)事件
* 把上面的4個(gè)子ALayout的isStretch屬性改成false,這個(gè)原理可以參考文檔 ALayout的示例demo
4. 修改index.ui.js,添加代碼主要是在底部bottom bar切換按鈕的時(shí)候修改所有圖標(biāo)的顏色和字的前景色。
var button = ui("do_Button_"); var imageview = ui("do_ImageView_"); var label = ui("do_Label_"); button.on("touch", function() { showView("chats"); }); var button = ui("do_Button_"); var imageview = ui("do_ImageView_"); var label = ui("do_Label_"); button.on("touch", function() { showView("contacts"); }); var button = ui("do_Button_"); var imageview = ui("do_ImageView_"); var label = ui("do_Label_"); button.on("touch", function() { showView("discover"); }); var button = ui("do_Button_"); var imageview = ui("do_ImageView_"); var label = ui("do_Label_"); button.on("touch", function() { showView("me"); }); function showView(name) { viewshower.showView(name); if (name == "chats") { imageview.source = "source://image/tabbar_mainframeHL.png"; label.fontColor = "BBFF"; } else { imageview.source = "source://image/tabbar_mainframe.png"; label.fontColor = "FFFFF"; } if (name == "contacts") { imageview.source = "source://image/tabbar_contactsHL.png"; label.fontColor = "BBFF"; } else { imageview.source = "source://image/tabbar_contacts.png"; label.fontColor = "FFFFF"; } if (name == "discover") { imageview.source = "source://image/tabbar_discoverHL.png"; label.fontColor = "BBFF"; } else { imageview.source = "source://image/tabbar_discover.png"; label.fontColor = "FFFFF"; } if (name == "me") { imageview.source = "source://image/tabbar_meHL.png"; label.fontColor = "BBFF"; } else { imageview.source = "source://image/tabbar_me.png"; label.fontColor = "FFFFF"; } }
到此為止,底部導(dǎo)航欄基本實(shí)現(xiàn)完成,這一節(jié)比較簡單,主要是一些細(xì)致的ui拖拽調(diào)整。我們用調(diào)試版本看一下Android,iOS的效果都非常不錯(cuò)。
我們開始實(shí)現(xiàn)ViewShower的第一頁主體內(nèi)容.
---------------------------------------------------------------------------------------
接上一節(jié) 底部導(dǎo)航 ,我們這一節(jié)主要是完成微信4個(gè)主頁面的第一個(gè)頁面“微信”頁面,這一節(jié)內(nèi)容比較多,我們分多個(gè)跟帖來完成
0 老規(guī)矩,先分析一下UI,由三個(gè)大部分組成,系統(tǒng)狀態(tài)欄,工具欄和微信聊天記錄列表。
1. 系統(tǒng)狀態(tài)欄高度40,背景黑色,我們注意到微信的首頁4個(gè)子頁面都有這個(gè)系統(tǒng)狀態(tài)欄,這樣我們需要做一個(gè)整體框架的調(diào)整,沒有必要為4個(gè)子頁面都添加一個(gè)狀態(tài)欄,只需要在ViewShower上添加一個(gè)就可以,對(duì)應(yīng)的ViewShower和子頁面的高度都變成1180.
對(duì)應(yīng)設(shè)計(jì)器里index.ui, chats/index.ui, contacts/index.ui, discover/index.ui, me/index.ui 都要作相應(yīng)的height,y屬性值的變化。效果如下:
2. 我們回到chats/index.ui ,先增加工具導(dǎo)航欄(高度80)和里面的標(biāo)題和工具按鈕,這個(gè)需要增加加號(hào)的資源文件,因?yàn)檫@個(gè)文件是chats頁面專有的,所以存在image/chats/bar_add.png下。
我們看看真機(jī)效果,我們注意到頂部多出一塊黑色區(qū)域,這是設(shè)計(jì)器里的增加的狀態(tài)欄,因?yàn)檫@個(gè)頁面是從系統(tǒng)狀態(tài)欄開始往下繪制的,所以會(huì)把設(shè)計(jì)器里這一部分多出來,
要解決的方法是修改app.js,openPage增加一個(gè)statusBarState參數(shù)(API文檔),設(shè)置為transparent表示頁面從屏幕最頂端開始繪制。
var d1 = require("deviceone"); var app = d1.sm("do_App"); app.on("loaded", function() { this.openPage({ source : "source://view/index.ui", statusBarState : "transparent" }); });
再來看看真機(jī)效果圖:
3. 主體部分是一個(gè)do_ListView,接下來設(shè)置ListView的cell和數(shù)據(jù)。
ListView的cell指列表框的每一行,比如ListView有100行數(shù)據(jù),實(shí)際上可見的屏幕永遠(yuǎn)只能看到8,9行左右,所以我們手勢上下滑動(dòng)的時(shí)候并沒有創(chuàng)建100行,而是重復(fù)使用這8,9行,只不過替換里面的數(shù)據(jù)而已。我們稱之為行模板,在DeviceOne里這種模板也是一個(gè)ui文件,比如這里我們在chats子目錄下新建一個(gè)chat_cell.ui,這個(gè)ui基本界面如下:
按照美工的設(shè)計(jì)尺寸我們來拖拽UI
這里同樣需要考慮純圓變形問題,需要設(shè)置好文字大小,前景色等屬性,大家可以看到里面有多個(gè)do_Label,do_ImageView組件,由于模板ui是靠后期綁定數(shù)據(jù)的,所以在設(shè)計(jì)階段都是空白的。
接下來我們需要設(shè)計(jì)chat_cell.ui對(duì)應(yīng)的數(shù)據(jù),通常為了用戶體驗(yàn),需要盡可能的減少網(wǎng)絡(luò)交互,頁面打開的時(shí)候通常先讀取本地的數(shù)據(jù)文件,把界面顯示出來,然后再考慮是否要進(jìn)行網(wǎng)絡(luò)連接來獲取最新數(shù)據(jù),所以App開發(fā)需要仔細(xì)考慮數(shù)據(jù)的本地化讀寫和數(shù)據(jù)的時(shí)效性的平衡。
DeviceOne的傳遞數(shù)據(jù)基本上都是標(biāo)準(zhǔn)的JSON格式。如下圖,chat_cell.ui里的組件屬性和JSON數(shù)據(jù)結(jié)構(gòu)對(duì)應(yīng)的關(guān)系
對(duì)應(yīng)的映射關(guān)系的代碼在chat_cell.ui.js如下,我們可以看到映射關(guān)系的左邊是組件id.組件屬性名,右邊是數(shù)據(jù)JSON的key名稱:
//related to chat_cell.ui var root = ui("$");;//$是這個(gè)ui文件根節(jié)點(diǎn)組件的通配符,如果指定組件的id,也可以用id來獲取對(duì)象 root.setMapping({ "photo_imageview.source" : "photo", "name_label.text" : "name", "lastmessage_label.text" : "lastmessage.message", "lasttime_label.text" : "lastmessage.time", "unread_label.visible" : "unread", "unread_label.text" : "unread-count", "name_label.fontColor" : "isgroup", });
對(duì)應(yīng)的數(shù)據(jù)本應(yīng)該是第一次運(yùn)行從網(wǎng)絡(luò)上獲取之后再緩存到本地的,我們是模擬,所以先手動(dòng)生成一個(gè)文件到data/chats/chat.json
4. 我們回到chats/index.ui,我們需要給這里ui文件里的listview設(shè)置模板,綁定數(shù)據(jù)。
設(shè)置index.ui 里的listview的templates屬性為 source://view/chats/chat_cell.ui
注意:chat_cell.ui存儲(chǔ)在source/default/view/chats/chat_cell.ui,但是source://的根節(jié)點(diǎn)指的是 source/default/目錄
在index.ui.js里添加綁定數(shù)據(jù)的代碼
//related to index.ui var storage = sm("do_Storage"); var listdata = mm("do_ListData"); var listview = ui("listview"); var json_path = "data://chats/chat.json";//本地緩存的數(shù)據(jù) if (storage.fileExist(json_path)) { storage.readFile(json_path, function(data, e) { //deviceone.print(JSON.stringify(data)); listdata.addData(data); listview.bindItems(listdata); listview.refreshItems(); }) } var page = sm("do_Page"); page.on("loaded",function(){ //這個(gè)頁面加載完顯示出來后觸發(fā)這個(gè)事件 //我們可以在這個(gè)事件里去獲取最新的網(wǎng)絡(luò)數(shù)據(jù),來更新listview和data/chats/chat.json });
我們在真機(jī)上看看效果
在運(yùn)行中有幾個(gè)細(xì)節(jié):
* 上下滑動(dòng)的時(shí)候,圖片不斷的刷新,原因是我們的ImageView的source是網(wǎng)絡(luò)圖片,每次顯示的時(shí)候都是從網(wǎng)絡(luò)上獲取的,所以這里需要把chat_cell.ui里的ImageView的cacheType屬性換成"always" 意思是只從網(wǎng)絡(luò)上讀取一次就會(huì)緩存到本地,下一次不會(huì)再從網(wǎng)絡(luò)上讀取了。關(guān)于cacheType屬性參考API文檔
* ImageView也是圓角的,圓角通??梢允褂胋order屬性來設(shè)置,但是android只有ImageView不能通過border來設(shè)置圓角,ImageView還有一個(gè)專有屬性radius來設(shè)置Android才有效,這個(gè)我們以后可以改進(jìn)
5. 處理右上角的add按鈕,點(diǎn)擊彈出菜單
先給右上角ImageView的enable屬性設(shè)置為true,才可以處理點(diǎn)擊事件,在chats/index.ui.js里添加代碼
var add_button = ui("add_imageview"); add_button.on("touch", function() { var menu = ui("menu_id"); if (menu) {//如果已經(jīng)add過,就只是讓這個(gè)view顯示,而不是add一個(gè)新的 if (menu.visible == false) menu.visible = true; } else { main.add("menu_id", "source://view/chats/chat_add_menu.ui"); } });
其中chat_add_menu.ui 是彈出的菜單對(duì)應(yīng)的ui文件,這個(gè)ui文件的根節(jié)點(diǎn)大小和chat/index.ui一樣,這樣確保我點(diǎn)擊任何空白處都可以關(guān)閉這個(gè)菜單(實(shí)際上是隱藏這個(gè)菜單),我們在這個(gè)ui文件里把對(duì)應(yīng)的布局都拖拽好,其中需要添加4個(gè)資源png文件。
這里有個(gè)小技巧,頂部的三角形標(biāo)記只能通過一個(gè)ImageView加載一個(gè)三角形圖標(biāo)來實(shí)現(xiàn)。
我們再給chat_add_menu的根節(jié)點(diǎn)添加點(diǎn)擊事件,點(diǎn)擊的時(shí)候把自己隱藏,在chat_add_menu.js
var root = ui("$"); root.on("touch",function(){ root.visible = false; });
最后我們先看看真機(jī)效果,點(diǎn)擊加號(hào)彈出菜單,點(diǎn)擊任何地方都把菜單隱藏。
這一節(jié)暫時(shí)先到這里,我們先開始拖拽后幾個(gè)主頁面,那幾個(gè)頁面基本完成后再重新回到這一個(gè)頁面來細(xì)琢。
- DeviceOne 讓你一見鐘情的App快速開發(fā)平臺(tái)
- JavaScript使用DeviceOne開發(fā)實(shí)戰(zhàn)(四)仿優(yōu)酷視頻應(yīng)用
- JavaScript使用DeviceOne開發(fā)實(shí)戰(zhàn)(二) 生成調(diào)試安裝包
- JavaScript使用DeviceOne開發(fā)實(shí)戰(zhàn)(一) 配置和起步
- 微信小程序 wx.uploadFile無法上傳解決辦法
- 微信小程序 input輸入框控件詳解及實(shí)例(多種示例)
- 微信小程序中使元素占滿整個(gè)屏幕高度實(shí)現(xiàn)方法
- 微信小程序 Windows2008 R2服務(wù)器配置TLS1.2方法
- 微信小程序 textarea 詳解及簡單使用方法
- 使用DeviceOne實(shí)現(xiàn)微信小程序功能
相關(guān)文章
JS判斷數(shù)組里是否有重復(fù)元素的方法小結(jié)
這篇文章主要介紹了JS判斷數(shù)組里是否有重復(fù)元素的方法,結(jié)合實(shí)例形式分析了javascript針對(duì)數(shù)組重復(fù)元素判斷相關(guān)的遍歷、排序、遞歸等相關(guān)操作技巧,需要的朋友可以參考下2019-05-05BootStrap初學(xué)者對(duì)彈出框和進(jìn)度條的使用感覺
這篇文章主要介紹了BootStrap初學(xué)者對(duì)彈出框和進(jìn)度條的使用感覺的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06JavaScript實(shí)現(xiàn)的類字典插入或更新方法實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的類字典插入或更新方法,實(shí)例分析了javascript針對(duì)類字典的插入與更新技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07微信小程序云開發(fā)實(shí)現(xiàn)云數(shù)據(jù)庫讀寫權(quán)限
這篇文章主要為大家詳細(xì)介紹了微信小程序云開發(fā)實(shí)現(xiàn)云數(shù)據(jù)庫讀寫權(quán)限,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05微信小程序 點(diǎn)擊控件后選中其它反選實(shí)例詳解
這篇文章主要介紹了微信小程序 點(diǎn)擊控件后選中其它反選實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-02-02jstl中判斷l(xiāng)ist中是否包含某個(gè)值的簡單方法
下面小編就為大家?guī)硪黄猨stl中判斷l(xiāng)ist中是否包含某個(gè)值的簡單方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10JS實(shí)現(xiàn)簡單可拖動(dòng)的模態(tài)框
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)簡單可拖動(dòng)的模態(tài)框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07JavaScript中string轉(zhuǎn)換成number介紹
這篇文章主要介紹了JavaScript中string轉(zhuǎn)換成number介紹,本文講解了3種將string值轉(zhuǎn)換成number的方法,需要的朋友可以參考下2014-12-12微信小程序?qū)崿F(xiàn)五星評(píng)價(jià)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)五星評(píng)價(jià),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08JS基于封裝函數(shù)實(shí)現(xiàn)的表格分頁完整示例
這篇文章主要介紹了JS基于封裝函數(shù)實(shí)現(xiàn)的表格分頁,結(jié)合完整實(shí)例形式分析了javascript針對(duì)table表格數(shù)據(jù)的遍歷、讀取以及模擬分頁顯示的相關(guān)操作技巧,需要的朋友可以參考下2018-06-06