有一天,老闆說要 UI 大整改,還好我有所準備。
之前就埋怨過,設定、cg 等頁面用 TyranoScript 編寫,看起來不好理解,而且頁面層級還老分不清,還不如直接寫 HTML 呢,今天就來分析一下怎麼用 HTML 寫一個新頁面。
我們從已有的 “非腳本” 頁面入手,例如默認的 Load 頁面,全局搜索 displayLoad
就能找到,在 kag.menu.js 文件中。
this.kag.html('load', { array_save: array, novel: $.novel }, function(
html_str
) {
var layer_menu = that.kag.layer.getMenuLayer()
var j_save = $(html_str)
j_save.find('.save_list').css('font-family', that.kag.config.userFace)
j_save.find('.save_display_area').each(function() {
$(this).click(function(e) {
var num = $(this).attr('data-num')
that.snap = null
that.loadGame(num)
var layer_menu = that.kag.layer.getMenuLayer()
layer_menu.hide()
layer_menu.empty()
var layer_title = that.kag.layer.getTitleLayer()
layer_title.hide()
layer_title.empty()
if (that.kag.stat.visible_menu_button == true) $('.button_menu').show()
})
})
j_save.find('.button_smart').hide()
if ($.userenv() != 'pc') {
j_save.find('.button_smart').show()
j_save.find('.button_arrow_up').click(function() {
var now = j_save.find('.area_save_list').scrollTop()
var pos = now - 160
layer_menu
.find('.area_save_list')
.animate({ scrollTop: pos }, { queue: false })
})
j_save.find('.button_arrow_down').click(function() {
var now = j_save.find('.area_save_list').scrollTop()
var pos = now + 160
j_save
.find('.area_save_list')
.animate({ scrollTop: pos }, { queue: false })
})
}
that.setMenu(j_save)
})
新建頁面的核心就是 kag.html
函數,此函數位於 kag.js:
{
html: function(html_file_name, data, callback) {
var that = this
data = data || {}
if (this.cache_html[html_file_name]) {
if (callback) {
var tmpl = $.templates(this.cache_html[html_file_name])
var html = tmpl.render(data)
callback($(html))
}
} else {
if (!this.kag.stat.sysview) {
this.kag.stat.sysview = {
save: './tyrano/html/save.html',
load: './tyrano/html/load.html',
backlog: './tyrano/html/backlog.html',
menu: './tyrano/html/menu.html',
}
}
var path_html = this.kag.stat.sysview[html_file_name]
$.loadText(path_html, function(text_str) {
var tmpl = $.templates(text_str)
var html = tmpl.render(data)
that.cache_html[html_file_name] = text_str
if (callback) callback($(html))
})
}
}
}
html 函數的參數分別是:
- 文件名稱
- 傳入的數據
- 回調函數
觀察 displayLoad 可知,加載 load 頁面需要傳入頁面名稱 load,一個包含存檔內容的對象,以及參數為 html 文件內容的回調函數。這裡有一個槽點,callback 傳入的 $(html) 根本不是參數所寫的 html_ “str” 而是經過 jQuery 處理的對象。
回到在 html 函數中,$.loadText
使用 ajax 獲取本地 html 文件;而 $.templates
和 tmpl.render
等函數均出自開源渲染引擎 jsrender。
在 load.html 中,我們可以看到模板的使用:
<div class="save_list">
{{for array_save}}
<div class="save_display_area save_list_item" data-num="{{:num}}">
<span class="save_list_item_thumb">
{{if img_data != ""}}
<img class="pic" src="{{:img_data}}" />
{{/if}}
</span>
<span class="save_list_item_thumb">
{{if img_data == ""}}
<div class="pic">無數據</div>
{{/if}}
</span>
<div class="save_list_item_area">
<div class="save_list_item_date">{{:save_date}}</div>
<div class="save_list_item_text">{{:title}}</div>
</div>
</div>
{{/for}}
</div>
但是我不打算用 jsrender 作為模板引擎,因為我還要引入 Vue 順便蹭一蹭 MVVM 的便捷。
於是我們可以改寫一個更簡單的 html 函數:
{
htmlPure: function(html_file_name, data, callback) {
var that = this
data = data || {}
if (this.cache_html[html_file_name]) {
if (callback) {
callback(this.cache_html[html_file_name])
}
} else {
var path_html = this.kag.stat.sysview[html_file_name]
$.loadText(path_html, function(text_str) {
that.cache_html[html_file_name] = text_str
if (callback) callback(text_str)
})
}
},
}
htmlPure 函數去除了模板引擎渲染,直接將 html 字符串傳入回調函數。(可以選擇保留 jsrender,但是為了不和 Vue 的模板衝突,需要修改 Vue 的 delimiters)
在新增 htmlPure 函數後,還要新建一個創建新頁面的標籤,這裡命名為 showExtendPage
:
tyrano.plugin.kag.tag.showExtendPage = {
pm: {},
start: function(pm) {
var that = this
this.kag.stat.is_skip = false
this.kag.htmlPure(pm.name, null, function(html_str) {
var extendPage = $(html_str)
var layer_extend = that.kag.layer.layer_extend
layer_extend[0].style.zIndex = pm.zindex || 9999999999
layer_extend[0].innerHTML = ''
layer_extend.fadeIn()
layer_extend.append(extendPage)
})
this.kag.ftag.nextOrder()
},
}
這就是使用自定義頁面的思路,在把腳本文件更換為 html 文件後整個人得到了解放,不用思考腳本跳轉的回調和層級清除問題,調用 showExtendPage 標籤即可使頁面淡入。