在有限的時間中,要學會一個前端框架不容易,也沒有一個框架是萬能的,但總要有個開始,筆者在進幾年一直在 extjs 的世界打滾,已有三四年的經驗,最近負責的專案除了使用 extjs,後端使用 grails,發現好處多多,就開發過程中的經驗與大家分享,從實際的例子還有兩個框架遇到得整合問題一一介紹
關於 extjs 的多語系處理,我們可以參考下列網址:Quick add multiple language to extjs + grails application,或者你可以使用別人寫的 extjs-locale-loader
基本的概念是, 你可以將你的語系資料定義在一個全域的 json Object,如此一來就可以在需要顯示對應語系的地方替換成 json object 裡面的某個屬性,但是在使用 Architect 時,有些屬性不一定可以透過他進行調整,比如說我們希望調整 Panel.title,在 Architect 你只能在 title 的屬性輸入文字屬性不能輸入變數,就算輸入了也會被當字串處理,這狀況確實令人苦惱,不過在遍尋相關資料後,總算讓筆者找到解法,就在官方的文件中關於 config_panel 說明中 **Using Variables with Configs** 章節,概念上是:title 雖然不能調整資料的類型,但我們可以在任一元件新增 Process config
他會建立一個函式,在裡面可以對 config 進行裡面的欄位調整,光看文件的說明很難想像到底是如何運作,我們可以來看實際產生的程式碼,在還未加入 Process config
之前:
Ext.define('foodprint.view.ItemEditor', {
extend: 'Ext.tab.Panel',
alias: 'widget.itemeditor',
itemId: 'itemEditor',
activeTab: 0,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'panel',
layout: {
align: 'stretch',
type: 'vbox'
},
title: 'list',
items: [
{
xtype: 'itemgrid'
}
]
},
{
xtype: 'panel',
layout: {
align: 'stretch',
type: 'vbox'
},
title: '資料維護',
items: [
{
xtype: 'itemviewer',
flex: 1
}
]
}
]
});
me.callParent(arguments);
}
});
很標準的寫法,我們在 initComponent 將我們需要的加入的元件定義好,其中包括 title 是一個文字 'list',也就是我們沒辦法利用 Arcitect 修改的地方,接著我們來看加入 Process config
之後的程式碼:
Ext.define('foodprint.view.ItemEditor', {
extend: 'Ext.tab.Panel',
alias: 'widget.itemeditor',
itemId: 'itemEditor',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
me.processLocalized({
xtype: 'panel',
layout: {
align: 'stretch',
type: 'vbox'
},
title: 'list',
items: [
{
xtype: 'itemgrid'
}
]
}),
{
xtype: 'panel',
layout: {
align: 'stretch',
type: 'vbox'
},
title: '資料維護',
items: [
{
xtype: 'itemviewer',
flex: 1
}
]
}
]
});
me.callParent(arguments);
},
processLocalized: function(config) {
config.title=foodprint.string.list;
return config;
}
});
一旦加入了 Process config
之後可以看到在 initComponent
這個函式中他將 json object 作為參數傳入 processLocalized
如此一來我們就可以在該函式進行所謂的語系替換,也就可以做到將 title 替換成變數,就解決了沒辦法調整 title 資料型態的窘境。
接著,我們就可以定義我們的語系檔,範例如下:
var foodprint = {};
foodprint.string = {};
foodprint.string.list = "瀏覽清單";
並且在 Architect 中引入該 js 檔案,如圖:
至於動態載入不同的語系檔,這邊就不做探討,那是另一個議題,網路上也有一些解法,就先留給各位讀者研究囉。
另外關於語系的處理,我們可以用到 extjs 對於 javascript 的String 類別的強化,參考 API:Ext.String-method-format,對於一些訊息的呈現我們可以將相關參數傳進去,如此在定義語系時,變數的位置就可以被空下來,使用 extjs 原生的函式進行替換,使用方式可參考範例:
var cls = 'my-class',
text = 'Some text';
var s = Ext.String.format('<div class="{0}">{1}</div>', cls, text);
// s now contains the string: '<div class="my-class">Some text</div>'
一開始發現此問題時,直覺反應是這也太不方便了吧!不過在體驗了這樣的作法之後,又覺得這樣做真的很神奇,好處是語系的替換不會散佈在程式碼各處,透過不同函式負責不同的處理,一旦需要新增語系也可以有一致的處理方式,另外在 Architect 進行開發時,畫面上的呈現也可以是簡單易讀的明確文字,確實是兼顧可讀性的處理方式,給大家參考,若有更好的方式也請讓我知道!
Ext JS 教學內容由思創軟體提供,共同作者 @lyhcode 與 @smlsun 目前在校園及企業從事 JavaScript(含 Node.js, Ext JS)與 Java(含 Groovy, Grails, Gradle) 教育訓練及顧問工作。