用javascript作一個(gè)通用向?qū)дf明
更新時(shí)間:2011年08月30日 16:40:19 作者:
向?qū)Э梢宰屇愕木W(wǎng)站用戶快速上手使用你的web應(yīng)用,提高網(wǎng)站的吸引力。向?qū)б话惴譃楹脦讉€(gè)步驟,每個(gè)步驟收集一些數(shù)據(jù),并且支持退回功能,所有步驟完成后可以得到每一步的收集結(jié)果。這里給大家展示一種比較通用,靈活且簡單的向?qū)Э蚣堋?/div>
1、界面設(shè)計(jì)
index.html:只提供了一個(gè)向?qū)э@示位置的占位符
<html>
<head>
<title>禮物推薦向?qū)?lt;/title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="jquery.js" type="text/javascript"></script>
<script src="wizard.js" type="text/javascript"></script>
</head>
<body>
<div id="wizard"></div>
</body>
</html>
style.css:默認(rèn)情況下向?qū)Ю镉幸粋€(gè)h2呈現(xiàn)的標(biāo)題,一個(gè)ul呈現(xiàn)的主要內(nèi)容,一個(gè)div呈現(xiàn)的按鈕條,我們簡單設(shè)計(jì)了一下他們的默認(rèn)外觀,實(shí)際應(yīng)用中大家可以自由的美化它們。
body{
margin:0;
}
/*向?qū)萜?/
#wizard{
height:400px;
width:600px;
background-color:#999;
}
/*向?qū)У闹黧w內(nèi)容,用列表展示*/
#wizard ul{
margin:10px;
height:80%;
}
/*橫向顯示列表內(nèi)容*/
#wizard li{
display:inline-block;
margin:10px;
cursor:pointer;
}
/*列表的標(biāo)題*/
#wizard h2{
margin:10px;
}
/*列表的功能條,如返回按鈕*/
#wizard .bar{
margin:10px;
clear:both;
}
2、準(zhǔn)備每一步驟
向?qū)Э梢苑譃槊恳徊襟E,每個(gè)步驟需要呈現(xiàn)內(nèi)容,捕捉用戶選擇,提供標(biāo)題等功能,我們讓每一步都自己負(fù)責(zé)自己的事情,但要符合我們規(guī)定的一些契約。
每一個(gè)步驟用一個(gè)函數(shù)表示,第一個(gè)參數(shù)data_key是選擇本步驟數(shù)據(jù)的關(guān)鍵字,一般用于上一個(gè)步驟的結(jié)果決定下一個(gè)步驟顯示數(shù)據(jù)的情況,第二個(gè)參數(shù)result_callback是個(gè)回調(diào)函數(shù),就是在本步驟獲取結(jié)果時(shí)調(diào)用,它用于和向?qū)ь愡M(jìn)行通信,向?qū)ь愒诘玫缴弦徊降慕Y(jié)果后存儲(chǔ)結(jié)果并跳向到下一步。
該函數(shù)返回一個(gè)二元組,第一個(gè)元素是本步驟的標(biāo)題,第二個(gè)元素是本步驟主體部分的UI。
我們的示例是一個(gè)禮物推薦系統(tǒng),共分三步,第一步選擇送禮對象,第二步選擇關(guān)鍵字,其中第一步的選擇結(jié)果會(huì)影響到第二步顯示,第三步選擇價(jià)格區(qū)間,如下就是代碼的實(shí)現(xiàn),其中繪制界面和事件捕捉用了jquery來簡化操作。
function step1(data_key, result_callback){
var targets = ['女朋友','男朋友','父親','媽媽','孩子'];
var warpper = $('<ul></ul>')
$.each(targets, function(k,v){
$('<li>'+v+'</li>').click(function(){result_callback(v)}).appendTo(warpper);
});
return ['第一步:請選擇送禮物的對象',warpper];
}
function step2(data_key, result_callback){
var tags = {
'女朋友':['創(chuàng)意','可愛','浪漫','激情','實(shí)用','數(shù)碼',
'自制','毛絨玩具','衣服','包包'],
'男朋友':['男士用品','溫馨','實(shí)用','數(shù)碼','創(chuàng)意','衣物'],
'父親' :['男士用品','健康','植物','衣物'],
'媽媽' :['溫馨','健康','創(chuàng)意','護(hù)膚品','實(shí)用'],
'孩子' :['玩具','學(xué)習(xí)用品','實(shí)用','數(shù)碼']
};
var warpper = $('<ul></ul>')
$.each(tags[data_key], function(k,v){
$('<li>'+v+'</li>').click(function(){result_callback(v)}).appendTo(warpper);
});
return ['第二步:請選擇關(guān)鍵詞',warpper];
}
function step3(data_key, result_callback){
var price_level = ['便宜','普通','稍貴','貴重'];
var warpper = $('<ul></ul>')
$.each(price_level, function(k,v){
$('<li>'+v+'</li>').click(function(){result_callback(v)}).appendTo(warpper);
});
return ['第三步:請選擇價(jià)格區(qū)間',warpper];
}
3、向?qū)ь惖膶?shí)現(xiàn)
向?qū)ь愐O(shè)置向?qū)诘腄OM元素,要執(zhí)行的步驟列表,向?qū)瓿珊髨?zhí)行的回調(diào),向?qū)н€應(yīng)該提供上一步和下一步的方法,所以我們用一個(gè)類來表示向?qū)?,在?gòu)造函數(shù)里傳入DOM容器,步驟列表和回調(diào)函數(shù),用prototype給類增加三個(gè)方法。render用來呈現(xiàn)某一步驟的UI,并在本步驟收集結(jié)果的回調(diào)里推向下一步,如果本步驟是最后一步,則調(diào)用向?qū)?zhí)行完成的回調(diào)函數(shù)。
另外兩個(gè)next和back函數(shù)分別是執(zhí)行上一個(gè)步驟和下一個(gè)步驟,這兩個(gè)函數(shù)實(shí)用index的私有變量來維持整個(gè)向?qū)У臓顟B(tài)
function Wizard(container, steps, callback){
this.container = container; //向?qū)萜?
this.steps = steps; //向?qū)Р襟E
this.callback = callback; //向?qū)?zhí)行完畢執(zhí)行的回調(diào)
this.collect_data = []; //保存向?qū)恳徊襟E的結(jié)果
this.index = -1; //當(dāng)前執(zhí)行在那一步驟
}
//繪制某一步驟
Wizard.prototype.render = function(step, this_result){
var me = this;
//執(zhí)行該步驟并得到該步驟的UI
var to_append = step(this_result,function(result){
me.collect_data.push(result); //收集本步驟結(jié)果
//向?qū)?zhí)行完畢時(shí)調(diào)用回調(diào)函數(shù),否則執(zhí)行下一步
if(me.collect_data.length == me.steps.length)
me.callback(me.collect_data);
else
me.next(result);
});
//繪制本步驟的UI
this.container.empty();
this.container.append("<h2>"+to_append[0]+"</h2>");
this.container.append(to_append[1]);
if(this.index > 0){
//后退按鈕
this.container.append($("<div class='bar'><a href='javascript:;'>后退</a></div>")
.click(function(){me.back()}
));
}
}
//執(zhí)行下一步
Wizard.prototype.next = function(this_result){
if(this.index >= this.steps.length -1)
return;
var step = this.steps[++this.index];
this.render(step,this_result);
}
//后退到上一步
Wizard.prototype.back = function(){
if(this.index <= 0)
return;
var step = this.steps[--this.index];
//步驟回到上一步,但上一步的數(shù)據(jù)需要上上一步的結(jié)果來決定
this.collect_data = this.collect_data.slice(0, this.index);
this.render(step, this.collect_data[this.index - 1]);
}
4、小結(jié)
本向?qū)ЫY(jié)構(gòu)簡單,可定制性強(qiáng),結(jié)合了javascript的函數(shù)式編程特性和面向?qū)ο蟮奶匦?,體現(xiàn)了javascript的強(qiáng)大和便利。
其中wizard類里界面繪制的部分和步驟函數(shù)里界面繪制的部分還是存在一些耦合,繼續(xù)重構(gòu)的話,可以把所有繪制界面的部分再抽象到一起,使界面改動(dòng)更方便。
index.html:只提供了一個(gè)向?qū)э@示位置的占位符
復(fù)制代碼 代碼如下:
<html>
<head>
<title>禮物推薦向?qū)?lt;/title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="jquery.js" type="text/javascript"></script>
<script src="wizard.js" type="text/javascript"></script>
</head>
<body>
<div id="wizard"></div>
</body>
</html>
style.css:默認(rèn)情況下向?qū)Ю镉幸粋€(gè)h2呈現(xiàn)的標(biāo)題,一個(gè)ul呈現(xiàn)的主要內(nèi)容,一個(gè)div呈現(xiàn)的按鈕條,我們簡單設(shè)計(jì)了一下他們的默認(rèn)外觀,實(shí)際應(yīng)用中大家可以自由的美化它們。
復(fù)制代碼 代碼如下:
body{
margin:0;
}
/*向?qū)萜?/
#wizard{
height:400px;
width:600px;
background-color:#999;
}
/*向?qū)У闹黧w內(nèi)容,用列表展示*/
#wizard ul{
margin:10px;
height:80%;
}
/*橫向顯示列表內(nèi)容*/
#wizard li{
display:inline-block;
margin:10px;
cursor:pointer;
}
/*列表的標(biāo)題*/
#wizard h2{
margin:10px;
}
/*列表的功能條,如返回按鈕*/
#wizard .bar{
margin:10px;
clear:both;
}
2、準(zhǔn)備每一步驟
向?qū)Э梢苑譃槊恳徊襟E,每個(gè)步驟需要呈現(xiàn)內(nèi)容,捕捉用戶選擇,提供標(biāo)題等功能,我們讓每一步都自己負(fù)責(zé)自己的事情,但要符合我們規(guī)定的一些契約。
每一個(gè)步驟用一個(gè)函數(shù)表示,第一個(gè)參數(shù)data_key是選擇本步驟數(shù)據(jù)的關(guān)鍵字,一般用于上一個(gè)步驟的結(jié)果決定下一個(gè)步驟顯示數(shù)據(jù)的情況,第二個(gè)參數(shù)result_callback是個(gè)回調(diào)函數(shù),就是在本步驟獲取結(jié)果時(shí)調(diào)用,它用于和向?qū)ь愡M(jìn)行通信,向?qū)ь愒诘玫缴弦徊降慕Y(jié)果后存儲(chǔ)結(jié)果并跳向到下一步。
該函數(shù)返回一個(gè)二元組,第一個(gè)元素是本步驟的標(biāo)題,第二個(gè)元素是本步驟主體部分的UI。
我們的示例是一個(gè)禮物推薦系統(tǒng),共分三步,第一步選擇送禮對象,第二步選擇關(guān)鍵字,其中第一步的選擇結(jié)果會(huì)影響到第二步顯示,第三步選擇價(jià)格區(qū)間,如下就是代碼的實(shí)現(xiàn),其中繪制界面和事件捕捉用了jquery來簡化操作。
復(fù)制代碼 代碼如下:
function step1(data_key, result_callback){
var targets = ['女朋友','男朋友','父親','媽媽','孩子'];
var warpper = $('<ul></ul>')
$.each(targets, function(k,v){
$('<li>'+v+'</li>').click(function(){result_callback(v)}).appendTo(warpper);
});
return ['第一步:請選擇送禮物的對象',warpper];
}
function step2(data_key, result_callback){
var tags = {
'女朋友':['創(chuàng)意','可愛','浪漫','激情','實(shí)用','數(shù)碼',
'自制','毛絨玩具','衣服','包包'],
'男朋友':['男士用品','溫馨','實(shí)用','數(shù)碼','創(chuàng)意','衣物'],
'父親' :['男士用品','健康','植物','衣物'],
'媽媽' :['溫馨','健康','創(chuàng)意','護(hù)膚品','實(shí)用'],
'孩子' :['玩具','學(xué)習(xí)用品','實(shí)用','數(shù)碼']
};
var warpper = $('<ul></ul>')
$.each(tags[data_key], function(k,v){
$('<li>'+v+'</li>').click(function(){result_callback(v)}).appendTo(warpper);
});
return ['第二步:請選擇關(guān)鍵詞',warpper];
}
function step3(data_key, result_callback){
var price_level = ['便宜','普通','稍貴','貴重'];
var warpper = $('<ul></ul>')
$.each(price_level, function(k,v){
$('<li>'+v+'</li>').click(function(){result_callback(v)}).appendTo(warpper);
});
return ['第三步:請選擇價(jià)格區(qū)間',warpper];
}
3、向?qū)ь惖膶?shí)現(xiàn)
向?qū)ь愐O(shè)置向?qū)诘腄OM元素,要執(zhí)行的步驟列表,向?qū)瓿珊髨?zhí)行的回調(diào),向?qū)н€應(yīng)該提供上一步和下一步的方法,所以我們用一個(gè)類來表示向?qū)?,在?gòu)造函數(shù)里傳入DOM容器,步驟列表和回調(diào)函數(shù),用prototype給類增加三個(gè)方法。render用來呈現(xiàn)某一步驟的UI,并在本步驟收集結(jié)果的回調(diào)里推向下一步,如果本步驟是最后一步,則調(diào)用向?qū)?zhí)行完成的回調(diào)函數(shù)。
另外兩個(gè)next和back函數(shù)分別是執(zhí)行上一個(gè)步驟和下一個(gè)步驟,這兩個(gè)函數(shù)實(shí)用index的私有變量來維持整個(gè)向?qū)У臓顟B(tài)
復(fù)制代碼 代碼如下:
function Wizard(container, steps, callback){
this.container = container; //向?qū)萜?
this.steps = steps; //向?qū)Р襟E
this.callback = callback; //向?qū)?zhí)行完畢執(zhí)行的回調(diào)
this.collect_data = []; //保存向?qū)恳徊襟E的結(jié)果
this.index = -1; //當(dāng)前執(zhí)行在那一步驟
}
//繪制某一步驟
Wizard.prototype.render = function(step, this_result){
var me = this;
//執(zhí)行該步驟并得到該步驟的UI
var to_append = step(this_result,function(result){
me.collect_data.push(result); //收集本步驟結(jié)果
//向?qū)?zhí)行完畢時(shí)調(diào)用回調(diào)函數(shù),否則執(zhí)行下一步
if(me.collect_data.length == me.steps.length)
me.callback(me.collect_data);
else
me.next(result);
});
//繪制本步驟的UI
this.container.empty();
this.container.append("<h2>"+to_append[0]+"</h2>");
this.container.append(to_append[1]);
if(this.index > 0){
//后退按鈕
this.container.append($("<div class='bar'><a href='javascript:;'>后退</a></div>")
.click(function(){me.back()}
));
}
}
//執(zhí)行下一步
Wizard.prototype.next = function(this_result){
if(this.index >= this.steps.length -1)
return;
var step = this.steps[++this.index];
this.render(step,this_result);
}
//后退到上一步
Wizard.prototype.back = function(){
if(this.index <= 0)
return;
var step = this.steps[--this.index];
//步驟回到上一步,但上一步的數(shù)據(jù)需要上上一步的結(jié)果來決定
this.collect_data = this.collect_data.slice(0, this.index);
this.render(step, this.collect_data[this.index - 1]);
}
4、小結(jié)
本向?qū)ЫY(jié)構(gòu)簡單,可定制性強(qiáng),結(jié)合了javascript的函數(shù)式編程特性和面向?qū)ο蟮奶匦?,體現(xiàn)了javascript的強(qiáng)大和便利。
其中wizard類里界面繪制的部分和步驟函數(shù)里界面繪制的部分還是存在一些耦合,繼續(xù)重構(gòu)的話,可以把所有繪制界面的部分再抽象到一起,使界面改動(dòng)更方便。
相關(guān)文章
Javascript的異步函數(shù)和Promise對象你了解嗎
這篇文章主要為大家詳細(xì)介紹了Javascript異步函數(shù)和Promise對象,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03JS中函數(shù)科里化的背景與應(yīng)用實(shí)例教程
在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中,柯里化是一種將使用多個(gè)參數(shù)的一個(gè)函數(shù)轉(zhuǎn)換成一系列使用一個(gè)參數(shù)的函數(shù)的技術(shù),下面這篇文章主要給大家介紹了JS中函數(shù)科里化的背景與應(yīng)用實(shí)例的相關(guān)資料,需要的朋友可以參考下2022-06-06關(guān)于JS中setTimeout()無法調(diào)用帶參函數(shù)問題的解決方法
這篇文章主要介紹了關(guān)于JS中setTimeout()無法調(diào)用帶參函數(shù)問題的解決方法,提供了2種解決方法供大家對比參考,需要的朋友可以參考下2016-06-06javascript與asp.net(c#)互相調(diào)用方法
js與C#之間相互調(diào)用的一些方法2009-12-12HTML+CSS+JavaScript做女朋友版的刮刮樂(一看就會(huì))
這篇文章主要介紹了HTML+CSS+JavaScript做女朋友版的刮刮樂(一看就會(huì))本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08