欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

CascadeView級聯(lián)組件實現(xiàn)思路詳解(分離思想和單鏈表)

 更新時間:2016年04月12日 11:10:02   作者:流云諸葛  
本文介紹自己最近做省市級聯(lián)的類似的級聯(lián)功能的實現(xiàn)思路,為了盡可能地做到職責分離跟表現(xiàn)與行為分離,這個功能拆分成了2個組件并用到了單鏈表來實現(xiàn)關(guān)鍵的級聯(lián)邏輯,下一段有演示效果的gif圖

本文介紹自己最近做省市級聯(lián)的類似的級聯(lián)功能的實現(xiàn)思路,為了盡可能地做到職責分離跟表現(xiàn)與行為分離,這個功能拆分成了2個組件并用到了單鏈表來實現(xiàn)關(guān)鍵的級聯(lián)邏輯,下一段有演示效果的gif圖。雖然這是個很常見的功能,但是本文的實現(xiàn)邏輯清晰,代碼好理解,脫離了省市級聯(lián)這樣的語義,考慮了表現(xiàn)與行為的分離,希望本文的內(nèi)容能夠為你的工作帶來一些參考的價值,歡迎閱讀和指正。

Cascade 級聯(lián)操作

CascadeType. PERSIST 級聯(lián)持久化 ( 保存 ) 操作

CascadeType. MERGE 級聯(lián)更新 ( 合并 ) 操作

CascadeType. REFRESH 級聯(lián)刷新操作,只會查詢獲取操作

CascadeType. REMOVE 級聯(lián)刪除操作

CascadeType. ALL 級聯(lián)以上全部操作

Fetch 抓取是否延遲加載,默認情況一的方為立即加載,多的一方為延遲加載

mappedBy 關(guān)系維護

mappedBy= "parentid" 表示在children 類中的 parentid 屬性來維護關(guān)系,這個名稱必須和children 類中的 parentid屬性名稱完全一致才行。

另外需要注意,parent類中的集合類型必須是List或者Set,不能設(shè)置為ArrayList,否則會報錯

演示效果(代碼下載,注:該效果需要http才能運行,另外效果中的數(shù)據(jù)是模擬數(shù)據(jù),并不是后臺真實返回的,所以看到的省市縣的下拉數(shù)據(jù)都是一樣的):

注:本文用到了前面幾篇相關(guān)博客的技術(shù)實現(xiàn),如果有需要的話可以點擊下面的鏈接前去了解:

1)詳解Javascript的繼承實現(xiàn):提供一個class.js,用來定義javascript的類和構(gòu)建類的繼承關(guān)系;

2)jquery技巧之讓任何組件都支持類似DOM的事件管理:提供一個eventBase.js,用來給任意組件實例提供類似DOM的事件管理功能;

3)對jquery的ajax進行二次封裝以及ajax緩存代理組件:AjaxCache:提供ajax.js和ajaxCache.js,簡化jquery的ajax調(diào)用,以及對請求進行客戶端的緩存代理。

下面先來詳細了解下這個功能的要求。

1. 功能分析

以包含三個級聯(lián)項的級聯(lián)組件來說明這個功能:

1)每個級聯(lián)項可能需要一個用作輸入提示的option:

這種情況每個級聯(lián)項的數(shù)據(jù)列表中都能選擇一個空的option(就是輸入提示的那個):

也可能不需要用作輸入提示的option:

這種情況每個級聯(lián)項的數(shù)據(jù)列表中只能選數(shù)據(jù)option,選不到空的option:

2)如果當前這個頁面是從數(shù)據(jù)庫中查詢出來跟級聯(lián)組件對應(yīng)的字段有值,那么就把查詢出來的值回顯到級聯(lián)組件上:

如果查詢出來的對應(yīng)字段沒有值,那么就按第1)點需求描述的2種情況顯示。

3)各個級聯(lián)項在數(shù)據(jù)結(jié)構(gòu)上構(gòu)成單鏈表的關(guān)系,后一個級聯(lián)項的數(shù)據(jù)列表,跟前一個級聯(lián)項所選擇的數(shù)據(jù)有關(guān)聯(lián)的。

4)考慮到性能方面的問題,各個級聯(lián)項的數(shù)據(jù)列表都采用ajax異步加載顯示。

5)在級聯(lián)組件初始化完成以后,自動加載第一個級聯(lián)項的列表。

6)當前一個級聯(lián)項發(fā)生改變時,清空后面所有直接或間接關(guān)聯(lián)的級聯(lián)項的數(shù)據(jù)列表,同時如果前一個級聯(lián)項改變后的值不為空則自動加載跟它直接關(guān)聯(lián)的下一個級聯(lián)項的數(shù)據(jù)列表。清空級聯(lián)項的數(shù)據(jù)列表時要注意:如果級聯(lián)項需要顯示輸入提示的option,在清空的時候得保留該option。

7)要充分考慮性能問題,避免重復(fù)加載。

8)考慮到表單提交的問題,當級聯(lián)組件任意級聯(lián)項發(fā)生改變后,得把級聯(lián)組件所選的值體現(xiàn)到一個隱藏的文本域內(nèi),方便把級聯(lián)組件的值通過該文本域提交到后臺。

功能大致如上。

2. 實現(xiàn)思路

1)數(shù)據(jù)結(jié)構(gòu)

級聯(lián)組件跟別的組件不太一樣的是,它跟后臺的數(shù)據(jù)有一些依賴,我考慮的比較好實現(xiàn)的數(shù)據(jù)結(jié)構(gòu)是:

{
"id": 1,
"text": "北京市",
"code": 110000,
"parentId": 0
},
{
"id": 2,
"text": "河北省",
"code": 220000,
"parentId": 0
},
{
"id": 3,
"text": "河南省",
"code": 330000,
"parentId": 0
}

id是數(shù)據(jù)的唯一標識,數(shù)據(jù)之間的關(guān)聯(lián)關(guān)系通過parentId來構(gòu)建,text,code這種都屬于普通的業(yè)務(wù)字段。如果按這個數(shù)據(jù)結(jié)構(gòu),我們查詢級聯(lián)項數(shù)據(jù)列表的接口就會變得很簡單:

//查第一個級聯(lián)項的列表
/api/cascade?parentId=0
//根據(jù)第一個級聯(lián)項選的值,查第二個級聯(lián)項的列表
/api/cascade?parentId=1
//根據(jù)第二個級聯(lián)項選的值,查第三個級聯(lián)項的列表
/api/cascade?parentId=4

這個結(jié)構(gòu)對于后臺來說也很好處理,雖然在結(jié)構(gòu)上它們是一種樹形的表結(jié)構(gòu),但是查詢都是單層的,所以很好實現(xiàn)。

從前面的查詢演示也能夠看出,這個結(jié)構(gòu)能夠很方便地幫我們把數(shù)據(jù)查詢的接口和參數(shù)統(tǒng)一成一個,這對于組件開發(fā)來說是一個很方便的事情。我們從后臺拿到這個數(shù)據(jù)結(jié)構(gòu)之后,把每一條數(shù)據(jù)解析成一個option,如<option value=”北京市” data-param-value=”1”>北京市</option>,這樣既能完成數(shù)據(jù)列表的下拉顯示,還能通過select這個表單元素的作用收集到當前級聯(lián)項所選中的值,最后當級聯(lián)項發(fā)生改變的時候,還能夠獲取到選中的option,把它上面存儲的data-param-value的值作為parentId這個參數(shù),去加載下一個級聯(lián)項的列表。這也是級聯(lián)組件數(shù)據(jù)查詢和解析的思路。

但是這里面還需要考慮的是靈活性的問題,在實際的項目中,可能級聯(lián)組件的數(shù)據(jù)結(jié)構(gòu)是按id parentId這種類似的關(guān)聯(lián)關(guān)系定義的,但是它們的字段不一定是叫id parentId text code,很有可能是別的字段。也就是說:在把數(shù)據(jù)解析成option的時候,option的text還有value到底用什么字段來解析,以及data-param-value這個屬性的用什么字段的值,都是不確定的;還有查詢數(shù)據(jù)時用的參數(shù)名稱parentId也不能是死的,有的時候如果后臺人員先寫好了查詢接口,用了別的名稱,你不可能要求人家去改他的參數(shù)名稱,因為他那邊是需要編譯再部署的,相比前端更麻煩一些;還有parentId=0這個0值也是不能固定,因為實際項目中第一層的數(shù)據(jù)的parentid有可能是空,也有可能是-1。這些東西都得設(shè)計成option,一方面提供默認值,同時留給外部根據(jù)實際情況來設(shè)置,比如本文最終的實現(xiàn)中這個option都是這樣定義的:

textField: 'text', //返回的數(shù)據(jù)中要在<option>元素內(nèi)顯示的字段名稱
valueField: 'text', //返回的數(shù)據(jù)中要設(shè)置在<option>元素的value上的字段名稱
paramField: 'id', //當調(diào)用數(shù)據(jù)查詢接口時,要傳遞給后臺的數(shù)據(jù)對應(yīng)的字段名稱
paramName: 'parentId', //當調(diào)用數(shù)據(jù)查詢接口時,跟在url后面?zhèn)鬟f數(shù)據(jù)的參數(shù)名
defaultParam: '', //當查詢第一個級聯(lián)項時,傳遞給后臺的值,一般是0,'',或者-1等,表示要查詢第上層的數(shù)據(jù)

2)html結(jié)構(gòu)

根據(jù)前面的功能分析的第1條,級聯(lián)組件的初始html結(jié)構(gòu)有2種:

<ul id="licenseLocation-view" class="cascade-view clearfix">
<li>
<select class="form-control">
<option value="">請選擇省份</option>
</select>
</li>
<li>
<select class="form-control">
<option value="">請選擇城市</option>
</select>
</li>
<li>
<select class="form-control">
<option value="">請選擇區(qū)縣</option>
</select>
</li>
</ul>

<ul id="companyLocation-view" class="cascade-view clearfix">
<li>
<select class="form-control">
</select>
</li>
<li>
<select class="form-control">
</select>
</li>
<li>
<select class="form-control">
</select>
</li>
</ul>

這兩個結(jié)構(gòu)唯一的區(qū)別就在于是否配置了用作輸入提示的option。另外需要注意的是如果需要這個空的option,一定得把value屬性設(shè)置成空,否則這個空的option在表單提交的時候會把option的提示信息提交到后臺。

這兩個結(jié)構(gòu)最關(guān)鍵的是select元素,跟ul和li沒有任何關(guān)系,ul跟li是為了UI而用到的;select元素沒有任何語義,不用去標識哪個是省份,哪個是城市,哪個是區(qū)縣。從功能上來說,一個select代表一個級聯(lián)項,這些select在哪定義都不重要,我們只要告訴級聯(lián)組件,它的級聯(lián)項由哪些select元素構(gòu)成就行了,唯一需要額外告訴組件的就是這些select元素的先后關(guān)系,但是這個通常都是用元素在html中的默認順序來控制的。這個結(jié)構(gòu)能夠幫助我們把組件的功能盡可能地做到表現(xiàn)與行為分離。

3)職責分離和單鏈表的運用

從前面的部分也差不多能看出來了,這個級聯(lián)組件如果按職責劃分,可以分成兩個核心的組件,一個負責整體功能和內(nèi)部級聯(lián)項的管理(CascadeView),另一個負責級聯(lián)項的功能實現(xiàn)(CascadeItem)。另外為了更方便地實現(xiàn)級聯(lián)的邏輯,我們只需要把所有的級聯(lián)項通過鏈表連起來,通過發(fā)布-訂閱模式,后一個級聯(lián)項訂閱前一個級聯(lián)項發(fā)生改變的消息;當前面的級聯(lián)項發(fā)生改變的時候,發(fā)布消息,通知后面的級聯(lián)項去處理相關(guān)邏輯;通過鏈表的作用,這個消息可能可以一直傳遞到最后一個級聯(lián)項為止。用圖來描述的話,大致就是這個樣子:

我們需要做的就是控制好消息的發(fā)布跟傳遞。

4)表單提交

為了能夠方便地將級聯(lián)組件的值提交到后臺,可以把整個級聯(lián)組件當成一個整體,對外提供一個onChanged事件,外部可通過這個事件獲取所有級聯(lián)項的值。由于存在多個級聯(lián)項,所以在發(fā)布onChanged這個事件時,只能在任意級聯(lián)項發(fā)生改變的時候,都去觸發(fā)這個事件。

5)ajax緩存

在這個組件里面得考慮兩個層級的ajax緩存,第一個是組件這一層級的,比如我把第一個級聯(lián)項切換到了北京,這個時候第二個級聯(lián)項就把北京的數(shù)據(jù)加載出來了,然后我把第一個級聯(lián)項從北京切換到河北再切換到北京,這個時候第二個級聯(lián)項要顯示的還是北京的關(guān)聯(lián)數(shù)據(jù)列表,如果我們在第一次加載這個列表的時候就把它的數(shù)據(jù)緩存下來了,那么這次就不用發(fā)起ajax請求了;第二個是ajax請求這一層級的,假如頁面上有多個級聯(lián)組件,我先把第一個級聯(lián)組件的第一個級聯(lián)項切換到北京,瀏覽器發(fā)起一個ajax請求加載數(shù)據(jù),當我再把第二個級聯(lián)組件的第一個級聯(lián)項切換到北京的時候,瀏覽器還會再發(fā)一個請求去加載數(shù)據(jù),如果我把第一個組件第一次ajax請求的返回的數(shù)據(jù),先緩存起來,當?shù)诙€組件,用同樣的參數(shù)請求同樣的接口時,直接拿之前緩存覺得結(jié)果返回,這樣也能減少一次ajax請求。第二個層級的ajax緩存依賴上文《對jquery的ajax進行二次封裝以及ajax緩存代理組件:AjaxCache》,對于組件來說,它內(nèi)部只實現(xiàn)了第一個層級的緩存,但是它不用考慮第二個層級的緩存,因為第二個層級的緩存實現(xiàn)對它來說是透明的,它不知道它用到的ajax組件有緩存的功能。

3. 實現(xiàn)細節(jié)

最終的實現(xiàn)包含了三個組件,CascadeView、CascadeItem、CascadePublicDefaults,前面兩個是組件的核心,最后一個只是用來定義一些option,它的作用在CascadeItem的注釋里面有詳細的描述。另外在下面的代碼中有非常詳細的注釋解釋了一些關(guān)鍵代碼的作用,結(jié)合著前面的需求來看代碼,應(yīng)該還是比較容易理解的。我以前傾向于用文字來解釋一些實現(xiàn)細節(jié),后來我慢慢覺得這種方式有點費力不討好,第一是細節(jié)層面的語言不好組織,有的時候言不達意,明明想把一件事情解釋清楚,結(jié)果反而弄得更加迷糊,至少我自己看自己寫的東西就會這樣的感觸;第二是本身開發(fā)人員都具有閱讀源碼的能力,而且大部分積極的開發(fā)人員都愿意通過琢磨別人的代碼來理解實現(xiàn)思路;所以我改用注釋的方式來說明實現(xiàn)細節(jié):)

CascadePublicDefaults:

define(function () {
return {
url: '',//數(shù)據(jù)查詢接口
textField: 'text', //返回的數(shù)據(jù)中要在<option>元素內(nèi)顯示的字段名稱
valueField: 'text', //返回的數(shù)據(jù)中要設(shè)置在<option>元素的value上的字段名稱
paramField: 'id', //當調(diào)用數(shù)據(jù)查詢接口時,要傳遞給后臺的數(shù)據(jù)對應(yīng)的字段名稱
paramName: 'parentId', //當調(diào)用數(shù)據(jù)查詢接口時,跟在url后面?zhèn)鬟f數(shù)據(jù)的參數(shù)名
defaultParam: '', //當查詢第一個級聯(lián)項時,傳遞給后臺的值,一般是0,'',或者-1等,表示要查詢第上層的數(shù)據(jù)
keepFirstOption: true, //是否保留第一個option(用作輸入提示,如:請選擇省份),如果為true,在重新加載級聯(lián)項時,不會清除默認的第一個option
resolveAjax: function (res) {
return res;
}//因為級聯(lián)項在加載數(shù)據(jù)的時候會發(fā)異步請求,這個回調(diào)用來解析異步請求返回的響應(yīng)
}
});

CascadeView:

define(function (require, exports, module) {
var $ = require('jquery');
var Class = require('mod/class');
var EventBase = require('mod/eventBase');
var PublicDefaults = require('mod/cascadePublicDefaults');
var CascadeItem = require('mod/cascadeItem');
/**
* PublicDefaults的作用見CascadeItem組件內(nèi)的注釋
*/
var DEFAULTS = $.extend({}, PublicDefaults, {
$elements: undefined, //級聯(lián)項jq對象的數(shù)組,元素在數(shù)據(jù)中的順序代表級聯(lián)的先后順序
valueSeparator: ',', //獲取所有級聯(lián)項的值時使用的分隔符,如果是英文逗號,返回的值形如 北京市,區(qū),朝陽區(qū)
values: '', //用valueSeparator分隔的字符串,表示初始時各個select的值
onChanged: $.noop //當任意級聯(lián)項的值發(fā)生改變的時候會觸發(fā)這個事件
});
var CascadeView = Class({
instanceMembers: {
init: function (options) {
//通過this.base調(diào)用父類EventBase的init方法
this.base();
var opts = this.options = this.getOptions(options),
items = this.items = [],
that = this,
$elements = opts.$elements,
values = opts.values.split(opts.valueSeparator);
this.on('changed.cascadeView', $.proxy(opts.onChanged, this));
$elements && $elements.each(function (i) {
var $el = $(this);
//實例化CascadeItem組件,并把每個實例的prevItem屬性指向前一個實例
//第一個prevItem屬性設(shè)置為undefined
var cascadeItem = new CascadeItem($el, $.extend(that.getItemOptions(), {
prevItem: i == 0 ? undefined : items[i - 1],
value: $.trim(values[i])
}));
items.push(cascadeItem);
//每個級聯(lián)項實例發(fā)生改變都會觸發(fā)CascadeView組件的changed事件
//外部可在這個回調(diào)內(nèi)處理業(yè)務(wù)邏輯
//比如將所有級聯(lián)項的值設(shè)置到一個隱藏域里面,用于表單提交
cascadeItem.on('changed.cascadeItem', function () {
that.trigger('changed.cascadeView', that.getValue());
});
});
//初始化完成自動加載第一個級聯(lián)項
items.length && items[0].load();
},
getOptions: function (options) {
return $.extend({}, this.getDefaults(), options);
},
getDefaults: function () {
return DEFAULTS;
},
getItemOptions: function () {
var opts = {}, _options = this.options;
for (var i in PublicDefaults) {
if (PublicDefaults.hasOwnProperty(i) && i in _options) {
opts[i] = _options[i];
}
}
return opts;
},
//獲取所有級聯(lián)項的值,是一個用valueSeparator分隔的字符串
//為空的級聯(lián)項的值不會返回
getValue: function () {
var value = [];
this.items.forEach(function (item) {
var val = $.trim(item.getValue());
val != '' && value.push(val);
});
return value.join(this.options.valueSeparator);
}
},
extend: EventBase
});
return CascadeView;
});

CascadeItem:

define(function (require, exports, module) {
var $ = require('jquery');
var Class = require('mod/class');
var EventBase = require('mod/eventBase');
var PublicDefaults = require('mod/cascadePublicDefaults');
var AjaxCache = require('mod/ajaxCache');
//這是一個可緩存的Ajax組件
var Ajax = new AjaxCache();
/**
* 有一部分option定義在PublicDefaults里面,因為CascadeItem組件不會被外部直接使用
* 外部用的是CascadeView組件,所以有一部分的option必須變成公共的,在CascadeView組件也定義一次
* 外部通過CascadeView組件傳遞所有的option
* CascadeView內(nèi)部實例化CascadeItem的時候,再把PublicDefaults內(nèi)的option傳遞給CascadeItem
*/
var DEFAULTS = $.extend({}, PublicDefaults, {
prevItem: undefined, // 指向前一個級聯(lián)項
value: '' //初始時顯示的value
});
var CascadeItem = Class({
instanceMembers: {
init: function ($el, options) {
//通過this.base調(diào)用父類EventBase的init方法
this.base($el);
this.$el = $el;
this.options = this.getOptions(options);
this.prevItem = this.options.prevItem; //前一個級聯(lián)項
this.hasContent = false;//這個變量用來控制是否需要重新加載數(shù)據(jù)
this.cache = {};//用來緩存數(shù)據(jù)
var that = this;
//代理select元素的change事件
$el.on('change', function () {
that.trigger('changed.cascadeItem');
});
//當前一個級聯(lián)項的值發(fā)生改變的時候,根據(jù)需要做清空和重新加載數(shù)據(jù)的處理
this.prevItem && this.prevItem.on('changed.cascadeItem', function () {
//只要前一個的值發(fā)生改變并且自身有內(nèi)容的時候,就得清空內(nèi)容
that.hasContent && that.clear();
//如果不是第一個級聯(lián)項,同時前一個級聯(lián)項沒有選中有效的option時,就不處理
if (that.prevItem && $.trim(that.prevItem.getValue()) == '') return;
that.load();
});
var value = $.trim(this.options.value);
value !== '' && this.one('render.cascadeItem', function () {
//設(shè)置初始值
that.$el.val(value.split(','));
//通知后面的級聯(lián)項做清空和重新加載數(shù)據(jù)的處理
that.trigger('changed.cascadeItem');
});
},
getOptions: function (options) {
return $.extend({}, this.getDefaults(), options);
},
getDefaults: function () {
return DEFAULTS;
},
clear: function () {
var $el = this.$el;
$el.val('');
if (this.options.keepFirstOption) {
//保留第一個option
$el.children().filter(':gt(0)').remove();
} else {
//清空全部
$el.html('');
}
//通知后面的級聯(lián)項做清空和重新加載數(shù)據(jù)的處理
this.trigger('changed.cascadeItem');
this.hasContent = false;//表示內(nèi)容為空
},
load: function () {
var opts = this.options,
paramValue,
that = this,
dataKey;
//dataKey是在cache緩存時用的鍵名
//由于第一個級聯(lián)項的數(shù)據(jù)是頂層數(shù)據(jù),所以在緩存的時候用的是固定且唯一的鍵:root
//其它級聯(lián)項的數(shù)據(jù)緩存時用的鍵名跟前一個選擇的option有關(guān)
if (!this.prevItem) {
paramValue = opts.defaultParam;
dataKey = 'root';
} else {
paramValue = this.prevItem.getParamValue();
dataKey = paramValue;
}
//先看數(shù)據(jù)緩存中有沒有加載過的數(shù)據(jù),有就直接顯示出來,避免Ajax
if (dataKey in this.cache) {
this.render(this.cache[dataKey]);
} else {
var params = {};
params[opts.paramName] = paramValue;
Ajax.get(opts.url, params).done(function (res) {
//resolveAjax這個回調(diào)用來在外部解析ajax返回的數(shù)據(jù)
//它需要返回一個data數(shù)組
var data = opts.resolveAjax(res);
if (data) {
that.cache[dataKey] = data;
that.render(data);
}
});
}
},
render: function (data) {
var html = [],
opts = this.options;
data.forEach(function (item) {
html.push(['<option value="',
item[opts.valueField],
'" data-param-value="',//將paramField對應(yīng)的值存放在option的data-param-value屬性上
item[opts.paramField],
'">',
item[opts.textField],
'</option>'].join(''));
});
//采用append的方式動態(tài)添加,避免影響第一個option
//最后還要把value設(shè)置為空
this.$el.append(html.join('')).val('');
this.hasContent = true;//表示有內(nèi)容
this.trigger('render.cascadeItem');
},
getValue: function () {
return this.$el.val();
},
getParamValue: function () {
return this.$el.find('option:selected').data('paramValue');
}
},
extend: EventBase
});
return CascadeItem;
});

4. demo說明

演示代碼的結(jié)構(gòu):

其中框起來的就是演示的相關(guān)部分。html/regist.html是演示效果的頁面,js/app/regist.js是演示效果的入口js:

define(function (require, exports, module) {
  var $ = require('jquery');
  var CascadeView = require('mod/cascadeView');
  function publicSetCascadeView(fieldName, opts) {
    this.cascadeView = new CascadeView({
      $elements: $('#' + fieldName + '-view').find('select'),
      url: '../api/cascade.json',
      onChanged: this.onChanged,
      values: opts.values,
      keepFirstOption: this.keepFirstOption,
      resolveAjax: function (res) {
        if (res.code == 200) {
          return res.data;
        }
      }
    });
  }
  var LOCATION_VIEWS = {
    licenseLocation: {
      $input: $('input[name="licenseLocation"]'),
      keepFirstOption: true,
      setCascadeView: publicSetCascadeView,
      onChanged: function(e, value){
        LOCATION_VIEWS.licenseLocation.$input.val(value);
      }
    },
    companyLocation: {
      $input: $('input[name="companyLocation"]'),
      keepFirstOption: false,
      setCascadeView: publicSetCascadeView,
      onChanged: function(e, value){
        LOCATION_VIEWS.companyLocation.$input.val(value);
      }
    }
  };
  LOCATION_VIEWS.licenseLocation.setCascadeView('licenseLocation', {
    values: LOCATION_VIEWS.licenseLocation.$input.val()
  });
  LOCATION_VIEWS.companyLocation.setCascadeView('companyLocation', {
    values: LOCATION_VIEWS.companyLocation.$input.val()
  });
});

注意以上代碼中LOCATION_VIEWS這個變量的作用,因為頁面上有多個級聯(lián)組件,這個變量其實是通過策略模式,把各個組件的相關(guān)的東西都用一種類似的方式管理起來而已。如果不這么做的話,很容易產(chǎn)生重復(fù)代碼;這種形式也比較有利于在入口文件這種處理業(yè)務(wù)邏輯的地方,進行一些業(yè)務(wù)邏輯的分離與封裝。

5. others

這估計是在現(xiàn)在公司寫的最后一篇博客,過兩天就得去新單位去上班了,不確定還能否有這么多空余的時間來記錄平常的工作思路,但是好歹已經(jīng)培養(yǎng)了寫博客的習慣,將來沒時間也會擠出時間來的。今年的目標主要是拓寬知識面,提高代碼質(zhì)量,后續(xù)的博客更多還是在組件化開發(fā)這個類別上,希望以后能夠得到大家的繼續(xù)關(guān)注腳本之家網(wǎng)站!

相關(guān)文章

最新評論