上一章我們實現了最基本的游戲界面和游戲的簡單入口,這一章,我們完善和制作 排行榜 功能,并為將來游戲結束時使用、記錄排行榜提供支持。
在使用 互聯網 的時候,我們基本上離不開 瀏覽器 ( browser ) 。 瀏覽器其實可以看作一個 中間人,他將 用戶無法理解、看不太懂的 腳本語言描述的程序,轉換為 用戶可以看得到的界面、接收用戶的輸入輸出動作,并通過執行腳本程序給出對應的反饋。 一般,我們把前面的 “轉換為界面” 過程稱作 “渲染” (render)。 在上一章中,我們在 .html 文件中填寫了代碼,在瀏覽器中打開這個文件,看到了界面,我們姑且稱這個“渲染”動作為“靜態渲染”,那么這一章中,我們將會看到另外一種“動態渲染”。
在程序開發過程當中,我們一般會提到“接口”,“封裝”等等概念。我理解,提出這些概念的目的,其實是在告訴我們,將程序寫的更“清晰”一些。這個“清晰”一般可以描述為兩方面:
定義“接口”,即就是將完整的、能夠重復使用的“功能”包裝(封裝)成函數、對象,并供其他邏輯 或 在其他地方調用;使用者并不需要了解“接口”內部具體的實現邏輯,只需知道接口“形式”即可使用,完成對應的功能,同時使用者 不需要對其不需了解的事情加以干涉 。我們下面也會封裝、實現一些簡單的接口來介紹上面的概念。
按照網頁的開發方式,我一般習慣按照“基本結構”->“外觀潤色”->“行為功能”這個流程進行進行開發。首先,在排行榜(上一章中 (3) 的位置)加入下面“基本結構”的 HTML 代碼:
標簽,并用
來表示一行, | 或 | 分別來表達 表頭和表體 中的單元格。 上面元素對應的屬性 class 中使用的對應內容,可暫不關心(有興趣的同學,可以 參看 中文 或 英文 的文檔)
上述代碼我們建立了一個基本的“表”,并為表體元素起名為 rank_table 便于將來對其進行操作(如,加入實際展示的數據,刷新排行榜等)。
因為我們對上層 元素設置了 text-align: center 居中對齊,表格對齊(標題被設置為左對齊了,內容區域是居中對齊的)有點亂,需要加入下面 CSS 樣式( minesweeper.css 文件中):
.block.rank .table tbody td { /* 排行榜表格內容居左(由于上層元素設置了 居中) */ text-align: left; /* left - 左對齊 right - 右對齊 center - 居中 */}
CSS 中存在樣式的“繼承”,即父級元素設置的樣式,如果適用的化,會被“繼承”應用的子元素上。
所謂適用的樣式有很多,例如 字體名 font-family 、字體大小 font-size 、顏色 color ,當然也存在一些特殊情況,這些屬性不會被繼承,例如:
這個 A 標簽的顏色不繼承 動態渲染
編寫 minesweeper-rank.js 文件,我們使用 JavaScript 程序為表格加入內容,并“ 渲染 ”出來:
(function($) { // 位置:(A) var data = [ {name:"DemoUserA", time:200}, // 直接使用 XXX 秒 來描述 耗時 {name:"DemoUserB", time:300}, // 展示的時候用程序將其變為 XX 分 XX 秒的形式 {name:"DemoUserC", time:400}, ] // 我們定義 $ 開頭的變臉用來記錄要操作的元素 var $table = $("#rank_table") // 排行榜的 “渲染” function render() { $table.empty() // 清空表格中目前的內容 for(var i=0;i"+(i+1)+" | "+data[i].name // 一行太長,可以換行寫 +" | "+renderTime(data[i].time) // this 這里指得就是當前 排行榜對象 rank // 調用 renderTime 函數生成 XX分XX秒 形式的文本 +" | ") // ! 加入內容,其實就是將 HTML 代碼文本 `append()` 添加到表格體中 } } // XXX 秒 => XX 分 XX 秒 function renderTime(time) { return parseInt(time/60) + " 分 " + (time % 60) + " 秒" } // 刷新頁面時立刻進行“渲染” rank.render() // 位置:(B)}(jQuery))
JavaScript 中可以使用 [ ... ] 形式定義數組,使用 {XXX: YYYY, XXX: YYYY} 形式定義對象;
數組一般使用 下標形式訪問,例如 data[i] ;
對象一般使用 .name 形式訪問,例如 data[i] 是一個對象,可以用 data[i].name 來訪問其姓名屬性;
持久化
為了讓排行榜能夠記錄并保留數據(不在刷新后消失),我們參照第一章 使用 localStorage 對象提供的功能來完成。我們將 (A) 處初始化的代碼改為:
// 位置: (A)var data = localStorage.getItem("rank_data")if(!data) { data = [ // 為演示方便,我們初始化一些數據 {name:"DemoUserA",time:200}, // 我們直接使用 XXX 秒 來描述用時 {name:"DemoUserB",time:300}, // 我們直接使用 XXX 秒 來描述用時 {name:"DemoUserC",time:400}, // 我們直接使用 XXX 秒 來描述用時 ] // 我們不能直接包數組數據保存到 localStorage 中,需要對他進行“序列化”,即將起變成文本; localStorage.setItem( "rank_data", JSON.stringify(data) ) // 在 JavaScript 中一般使用 JSON.stringify(obj) 將 obj 變為文本形式以便存儲 // 這種“變文本”的過程就是“序列化”}else{ // 保存了數據,讀取出來后需要“還原”: // 由于我們保存的是“序列化”的數據,我們需要將它“反序列化” data = JSON.parse(data) // JSON.parse() 與 上面 JSON.stringify() 對應,用于還原已經“序列化”的文本到其原始值}
JSON 與 localStorage 類似,也是由瀏覽器提供的進行數據“序列化”、“反序列化”的函數對象。 同時 JSON 也是一種文本描述數據的形式,具體說明可以參考 http://www.json.org/json-zh.html ;
同時 JSON 是目前最流行的數據交換方式的一種,尤其在服務器端與瀏覽器交互的“數據型接口”中被大量應用。例如大家熟知的 微信公眾平臺,就提供了 JSON 形式的接口,有興趣的同學可以看看他們的文檔 https://mp.weixin.qq.com/wiki ;
我們可以在瀏覽器中打開網頁,并按 F12 鍵打開調試界面,在 Resource 面板中,找到 localStorage 項,可以看到我們的程序已經將數據成功的寫入了:
大家可以嘗試通過這個面板修改 localStorage 的內容,刷新頁面后會發現展示的內容也會隨之發生變化。
接口
到這里,我們為排行榜定義的界面和基本顯示功能就完成了。但是,這個排行榜還沒有辦法 動態的調整 ,即將來在實際游戲完成的時候,我們需要把當前名稱的用戶成績“更新”或“加入”到排行榜里面。雖然是將來,我們需要先為游戲結束做進行這個功能時留下接口。
我們可能需要提供很多這些類似的“接口”,我們把這種接口統一放在一個名為 MineSweeperRank 的全局對象中(在位置 (B) 處加入下面的代碼):
// 位置:(B)window.MineSweeperRank = { // window 為全局命名空間,同時也代表了瀏覽器當前打開網頁的窗口 // 接口1. 加入用戶及成績進入榜單 appendUserRank: function(name, time) { // 將成績插入到 data 中的合適位置 // 從后往前,找到用時小于當前 time 的地方 for(var i=data.length-1; i>=0; --i) { if(data[i].time < time) { data.splice(i + 1, 0, {"name": name, "time": time}) // 從 i + 1 這個位置開始,刪除 0 個元素,加入 新增元素 break // 找到了速度更快的記錄,跳出循環(這時 i 應該還小于 data.length) } } if(i == data.length) { // 沒有找到比當前值更小的了,直接排在第一名 data.unshift({"name": name, "time": time}) } // 截取 data 的前 6 項(不要讓排行榜太長了) data = data.slice(0, 6) // 數據更新了,我們需要對應更新界面,即重新渲染 render() // 保存數據 localStorage.setItem( "rank_data", JSON.stringify(data) ) }, // 接口2. 清理(清空)榜單 clearRank: function() { data.splice(0, data.length) // 數據更新了,我們需要對應更新界面,即重新渲染 render() // 保存數據 localStorage.setItem( "rank_data", JSON.stringify(data) ) }, // 接口3. }
上面函數目前沒有實際的調用者,我們可以在 “開發者工具” ( F12 ) 的 Console 界面中輸入調用代碼(例如: MineSweeperRank.appendUserRank("Terry",450) ) 嘗試調用,看看效果:
從分工明確的角度,我們也給 “入口” 增加 “接口” 功能,我們將 “獲取用戶輸入的名字” 和 “開始游戲” 作為 “接口” 封裝。 注意,前者與上述 排行榜 接口 類似,是“調用”方式的接口。而后者,則是“ 觸發 ”形式的接口。
我們先將“調用”形式的接口實現(調整 minesweeper-entry.js 文件, 在結束行函數大括號內,補充如下代碼):
// 位置 (C)// 對外接口window.MineSweeperEntry = { // 接口1. 獲取當前用戶名 getName: function() { return localStorage.getItem("entry_input_name") || "無名氏" }, }// 位置 (D)
JavaScript 使用 || 表示 “邏輯或”,但與其他部分語言不同, || 返回的并非是 “布爾值”,而是條件中 第一個 真 值;
對應的還存在 && 標識 “邏輯與”,也同樣存在上面的使用方式,返回第一個 假 值,例如: var a = true && 0 變量 a 的值為 0 而非 false;
從分工上說,我們將 獲取姓名 接口定義在 “入口”,從 職責上說 我們將 “未輸入姓名,處理為 ‘無名氏’” 這個邏輯封裝在了接口內部,使用者就不用關心了。
請大家嘗試使用 Chrome 瀏覽器提供的 開發者工具 ( F12 或菜單 三 -> 更多工具 -> 開發者工具 )。它能夠提供界面元素 (HTML/CSS) 的調試、 代碼(JavaScript)調試,頁面性能測試,網絡監控等等功能,甚至很多功能連一些正式的前端開發人員都不太了解。有興趣的同學可以去看看 http://devtoolstips.com/ ,這個網站總結和演示了很多開發者工具的使用技巧,值得學習。
附件
本章目前完成的完整代碼可以在這里下載壓縮包
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com
(二)排行榜(定義和使用函數、對象)-掃雷網頁小游戲_html/css_WEB-ITnose
(二)排行榜(定義和使用函數、對象)-掃雷網頁小游戲_html/css_WEB-ITnose:上一章我們實現了最基本的游戲界面和游戲的簡單入口,這一章,我們完善和制作 排行榜 功能,并為將來游戲結束時使用、記錄排行榜提供支持。 在使用 互聯網 的時候,我們基本上離不開 瀏覽器 ( browser ) 。 瀏覽器其實可以看作一個 中間人,他將 用戶無
Top
主站蜘蛛池模板:
69国产成人综合久久精品91
|
日本国产最新一区二区三区
|
免费观看性欧美大片
|
最近免费中文字幕大全免费版视频
|
国产成人精品一区二区三区…
|
欧美 第一页
|
一区二区三区四区免费视频
|
免费一看一级毛片
|
在线免费国产
|
插插插叉叉叉
|
视频在线一区
|
欧美日韩国产在线播放
|
亚洲精品美女久久久aaa
|
日本a中文字幕
|
青青色在线视频
|
成人99国产精品一级毛片
|
欧美色乱|
亚洲欧美一区二区三区国产精品
|
九九热精品在线观看
|
色婷婷国产
|
国产日韩欧美精品在线
|
日本欧美一区二区三区不卡视频
|
国产l精品国产亚洲区在线观看
|
欧美日韩国产综合视频在线看
|
久久91精品国产91久久户
|
亚洲第一视频网
|
91一区二区三区四区五区
|
国产在线不卡视频
|
欧美日韩国产成人精品
|
国产精品资源在线观看
|
精品亚洲一区二区
|
香蕉视频啪啪
|
久久久久国产成人精品亚洲午夜
|
99国产精品高清一区二区二区
|
亚洲视频一区二区
|
成人a免费视频播放
|
亚洲国产成人久久一区久久
|
久久黄色毛片
|
在线观看国产欧美
|
久久频道毛片免费不卡片
|
成人一a毛片免费视频
|