<div id="wrap">
<form action="<?php $_SERVER['PHP_SELF'] ?>" method="post">
<label>地址 : <input type="text" name="house_address" required></label>
<label>州 :
<select id='house_state' name="house_state" required>
<option value=""></option>
<?php do{ ?>
<option value="<?php echo $row_state['state_code'] ?>"><?php echo $row_state['state_name'] ?></option>
<?php }while($row_state = mysqli_fetch_assoc($result_state)) ?>
</select>
</label>
<label>城市 :
<select id="house_county" name="house_county" required>
</select>
</label>
<label>區 :
<select id="house_city" name="house_city" required>
</select>
</label>
<label><input type="submit" value="確認修改"></label>
</form>
</div>
<script src="js/jquery.js"></script>
<script>
$(document).ready(function(){
$('#house_state').on('change',function(){
$('#house_city').html(''); //清除"區"的資料
$.ajax({
url:'php/house_county.php',
type:'post',
data:{
state_code : $(this).val()
},
datatype:'html'
}).done(function(data){
if(data){
$('#house_county').html(data);
}
})
});
$('#house_county').on('change',function(){
$.ajax({
url:'php/house_city.php',
type:'post',
data:{
county_code : $(this).val()
},
datatype:'html'
}).done(function(data){
if(data){
$('#house_city').html(data);
}
})
});
想請問窩該如何簡化程式碼
以下是我試做的 但是無法執行 不知道是哪裡有問題
function select(id){
var ID = $('#'+id);
ID.on('change',select);
function select(){
$url = "php/"+ID.attr('id')+".php";
$.ajax({
url : $url,
type : 'post',
data : {
city_code : ID.val()
},
datatype:'html'
}).done(function(data){
if(data){
$('#house_city').html(data);
}
})
}
}
select('house_state');
如果內容幾乎都一樣,
可以試試change事件呼叫同一個function,
然後將ID帶入那個function.
然後你有些地方改有些地方沒改...
之前也討論過類似的問題不過當時是純JS寫的。
JQ在某些地方的確是可以讓程式碼看起來更簡單,不過目前看起來是比較偏結構的問題。
我是這樣分析需求的:
從提問的程式碼來看,比段似乎相似程式碼差異之處有:
因此,function select 只有一個 id 參數應該是不夠的。
觀察 select 的層級:
觀察規則:
從上面這些再去想應該怎麼去寫出想要的程式。
程式碼大概長這樣
function initSelectEvent(idArray)
{
for(let i=0;i<idArray.length-1;++i) {
$('#house_'+idArray[i]).on('change', createCallback(i));
}
function createCallback(idx)
{
return function() {
let pId=idArray[idx];
let cId=idArray[idx+1];
//清空下層 select
for(let i=idx+1;i<idArray.length;++i) {
$('#house_'+idArray[i]).html('');
}
//ajax 更新下一層 select
let param={};
param[pId+'_code']=$(this).val();
$.ajax({
url:'php/house_'+cId+'.php',
type:'post',
data:param,
datatype:'html'
}).done(function(data){
$('#house_'+cId).html(data);
});
}
}
}
initSelectEvent(['state','county','city']);
範例先上
<!doctype html>
<html>
<head><meta charset='utf-8' /><title>TEST</title>
<script
src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8="
crossorigin="anonymous"></script>
<script>
let addr_arr=[
/*第一層*/
['California','0'],['Virginia','1'],['Utah','2'],
/*第二層*/
['County1_Ca','0_0'],['County2_Ca','0_1'],['County3_Ca','0_2'],
['County1_Vi','1_0'],['County2_Vi','1_1'],['County3_Vi','1_2'],
['County1_Ut','2_0'],['County2_Ut','2_1'],['County3_Ut','2_2'],
/*第三層*/
['City1_C1','0_0_0'],['City2_C1','0_0_1'],['City3_C1','0_0_2'],
['City1_C2','0_1_0'],['City2_C2','0_1_1'],['City3_C2','0_1_2'],
['City1_C3','0_2_0'],['City2_C3','0_2_1'],['City3_C3','0_2_2'],
['City1_V1','1_0_0'],['City2_V1','1_0_1'],['City3_V1','1_0_2'],
['City1_V2','1_1_0'],['City2_V2','1_1_1'],['City3_V2','1_1_2'],
['City1_V3','1_2_0'],['City2_V3','1_2_1'],['City3_V3','1_2_2']
];
$(document).ready(function() {
initStateMenu('house_state','');
$('#house_state,#house_county').change(function() {
initStateMenu((this.id=='house_state'?'house_county':'house_city'),this.value);
});
});
function initStateMenu(targetSel,arg){
$('#'+targetSel).html('').append(new Option('NOT CHOOSE',''));
if(targetSel=='house_county') $('#house_city').html('');
let searchArg=(arg==''?'_':arg+'_');
addr_arr.forEach(function(element) {
if(searchArg=='_'&&element[1].indexOf(searchArg)<0){
$('#'+targetSel).append(new Option(element[0],element[1]));
}else if((searchArg!='_'&&element[1].substring(0,searchArg.length)==searchArg&&element[1].length-searchArg.length==1)){
$('#'+targetSel).append(new Option(element[0],element[1]));
}
});
}
</script>
</head>
<body>
<div id="wrap">
<form action="" method="post">
<label>地址 : <input type="text" name="house_address" required></label>
<label>州 :
<select id='house_state' name="house_state" required>
<option value=""></option>
</select>
</label>
<label>城市 :
<select id="house_county" name="house_county" required>
</select>
</label>
<label>區 :
<select id="house_city" name="house_city" required>
</select>
</label>
<label><input type="submit" value="確認修改"></label>
</form>
</div>
</body></html>
說明:
上列的範例直接存為.htm再用chrome瀏覽即可看到效果。大概看懂樓主要的就是多層選單以jquery處理,我有幾個建議給您參考:
1.javascript碼跟jquery碼的位置你放得怪怪的,例如:
前略…
</div>
<script src="js/jquery.js"></script>
<script>
$(document).ready(function(){
…後略
通常匯入jquery.js與$(document).ready這個是放在head區塊的,你可以參考我給的範例,如果你是要把javascript放在body區最底下的話,那$(document).ready這東西就是沒意義的寫法,詳情請自行搜尋'jquery document ready'。
2.AJAX用起來是很酷,但不是萬靈丹,何時用如何用要謹愼:
以你本文裡貼的源碼來說,在php頁面載入的時候會先跑一次sql抓取出上層選單裡的options,然後在選單有變動的時候就會用ajax去call php,變動一次就呼叫一次php,其實很容易增加伺服器的負擔,特別是在用的人多的時候。我在這裡的作法(想法)是頁面載入時把地區資料(從DB取得)寫成javascript陣列 let addr_arr=[...];
裡面的元素有地區名跟地區階層,舉例來說['加州','0']代表的是最頂層選單元素,而['某區','0_1']則代表是加州的子階層元素,依此類推,我這裡用的0,1,2只是方便您好理解,實際從DB撈資料時可以用zip code代替,例如['加州','760']等等,這樣就不用每次動到選單就要頻繁向伺服器要資料。當然我不是要你不用AJAX,只是提醒你會用跟可以用跟必須用之間的差別。以這個例子我個人是認為無需用到AJAX。
3.建議先把基本程式語法掌握好,再鑽研複雜的部份。程式不能WORK跟程式簡化之優先順序,通常會是先求WORK再來求簡化優化。
感謝感謝大大回答 但我想問 如果第三層資料量快三萬多筆 我也要先從資料庫撈出來寫成陣列嗎?
第三層資料量快三萬多筆...你是在FedEX上班嗎!!??
'我也要先從資料庫撈出來寫成陣列嗎?'
當然這是一種方法(感覺不太好)
這裡可以把第三層選單更新的部份改為用AJAX,
但你也需考慮到效能的問題,或者想想有沒有其它更好的作法。
太陽底下沒有新鮮事,但總有更好的路。
$('#house_state').on('change',createCallback);
function createCallback() {
$id = $(this).attr('id');
$value = $(this).val();
$.ajax({
url:'php/'+$id+'.php',
type:'POST',
data:{
county_code : $value
},
datatype:'html'
}).done(function(data){
if(data){
$('#house_city').html(data);
}
})
};
我用我的邏輯寫了這個 但是執行時會出現404可以請大大幫我解惑一下嗎? 謝謝
$(document).ready(function() {
initStateMenu('house_state','');
$('#house_state,#house_county').change(function() {
if(this.id=='house_state'){
initStateMenu('house_county',this.value);
}else{
console.log('城市TEXT:'+$('#house_county :selected').text());
console.log('城市VALUE:'+$('#house_county :selected').val());
/* 這邊寫你要作的第三層選單AJAX程式 看要帶text或val作data都行 */
}
});
});
上面這個修改結果:第一二層選單從陣列addr_arr取得,第三層選單則用ajax call php取得(看要帶text或value作data都行)
當然原先的addr_arr就不需再撈第三層出來了,如下:
let addr_arr=[
/*第一層*/
['California','0'],['Virginia','1'],['Utah','2'],
/*第二層*/
['County1_Ca','0_0'],['County2_Ca','0_1'],['County3_Ca','0_2'],
['County1_Vi','1_0'],['County2_Vi','1_1'],['County3_Vi','1_2'],
['County1_Ut','2_0'],['County2_Ut','2_1'],['County3_Ut','2_2']
];
其它部份javascript無需變動。第三層選單AJAX取得資料的部份就留給樓主練習了,加油~
https://zh.wikipedia.org/wiki/HTTP_404
url:'php/'+$id+'.php',
先改成純字串,確認那個php是存在的,例如:
url:'php/queryCityItems.php',
常見的是路徑或檔名有誤。
請問
<script
src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8="
crossorigin="anonymous"></script>
<script>
這段當中的crossorigin
和 integrity
是什麼意思呢?