iT邦幫忙

0

簡化JQUERY程式碼

<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');
1
小魚
iT邦高手 1 級 ‧ 2019-08-06 18:19:40

如果內容幾乎都一樣,
可以試試change事件呼叫同一個function,
然後將ID帶入那個function.

然後你有些地方改有些地方沒改...

1
淺水員
iT邦新手 2 級 ‧ 2019-08-06 23:43:27

之前也討論過類似的問題不過當時是純JS寫的。
JQ在某些地方的確是可以讓程式碼看起來更簡單,不過目前看起來是比較偏結構的問題。
我是這樣分析需求的:
從提問的程式碼來看,比段似乎相似程式碼差異之處有:

  1. 要掛載 change 事件的 select 元素
  2. 當 change 事件發生之後,必須清空的下層 select 元素
  3. 當 change 事件發生之後,要送出 ajax 的 url
  4. 當 change 事件發生之後,要送出 ajax 的 parameter
  5. 當 ajax 回傳資料後,需要更新的 select 元素

因此,function select 只有一個 id 參數應該是不夠的。

觀察 select 的層級:

  1. select#house_state
  2. select#house_county
  3. select#house_city

觀察規則:

  1. 當 select#house_state 變動時:
    • 透過 ajax(url=php/house_county.php;param=state_code) 更新下層的 select#house_county
    • 更下層元素清空(select#house_city)
  2. 當 select#house_county 變動時
    • 透過 ajax(url=php/house_city.php;param=county_code) 更新下層的 select#house_city
    • 更下層元素清空(無更下層元素)

從上面這些再去想應該怎麼去寫出想要的程式。
程式碼大概長這樣

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']);
2
ccutmis
iT邦研究生 1 級 ‧ 2019-08-07 11:25:37

範例先上

<!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再來求簡化優化。

看更多先前的回應...收起先前的回應...
cheer0101 iT邦新手 5 級 ‧ 2019-08-07 11:35:02 檢舉

感謝感謝大大回答 但我想問 如果第三層資料量快三萬多筆 我也要先從資料庫撈出來寫成陣列嗎?

ccutmis iT邦研究生 1 級 ‧ 2019-08-07 11:53:30 檢舉

第三層資料量快三萬多筆...你是在FedEX上班嗎!!??
/images/emoticon/emoticon77.gif
'我也要先從資料庫撈出來寫成陣列嗎?'
當然這是一種方法(感覺不太好)
這裡可以把第三層選單更新的部份改為用AJAX,
但你也需考慮到效能的問題,或者想想有沒有其它更好的作法。

太陽底下沒有新鮮事,但總有更好的路。
/images/emoticon/emoticon82.gif

cheer0101 iT邦新手 5 級 ‧ 2019-08-07 12:05:38 檢舉
$('#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可以請大大幫我解惑一下嗎? 謝謝

ccutmis iT邦研究生 1 級 ‧ 2019-08-07 12:22:24 檢舉
$(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取得資料的部份就留給樓主練習了,加油~

ccutmis iT邦研究生 1 級 ‧ 2019-08-07 12:29:15 檢舉

https://zh.wikipedia.org/wiki/HTTP_404

url:'php/'+$id+'.php',

先改成純字串,確認那個php是存在的,例如:

url:'php/queryCityItems.php',

常見的是路徑或檔名有誤。

0
kkdayy_55330
iT邦新手 5 級 ‧ 2019-08-23 12:25:56

請問

<script
  src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
  integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8="
  crossorigin="anonymous"></script>
<script>

這段當中的crossoriginintegrity 是什麼意思呢?

我要發表回答

立即登入回答