iT邦幫忙

0

關聯下拉式選單要如何簡化javascript 程式碼?

我想簡化我的js,感覺重複的code很多,但我不知道該從哪裡下手。新手麻煩高手指點

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    </style>
</head>
<body>
    <form action="">
            <select id="country">
                <option>選擇國家</option>
                <option value="taiwan">台灣</option>
                <option value="usa">美國</option>
            </select>
            <select id="city">

            </select>
            <select  id="district">

            </select>
    </form>
    <script>
        var taiwan = [
                {
                    "CityName": "臺北市",
                    "CityEngName": "Taipei City",
                    "AreaList": [
                        {
                            "ZipCode": "100",
                            "AreaName": "中正區",
                            "AreaEngName": "Zhongzheng Dist."
                        },
                        {
                            "ZipCode": "103",
                            "AreaName": "大同區",
                            "AreaEngName": "Datong Dist."
                        }
                    ]
                },
                {
                    "CityName" : "新竹市",
                    "CityEngName" : "Hsinchu city",
                    "AreaList" : [
                        {
                            "ZipCode":300,
                            "AreaName":"東區",
                            "AreaEngName":"East Dist"
                        },
                        {
                            "ZipCode":300,
                            "AreaName":"北區",
                            "AreaEngName":"North Dist"
                        }
                    ]
                }
            ];
            console.log(taiwan[0]['AreaList'].length);
            var usa =[];

        window.onload = function(){
            document.getElementById('country').addEventListener('change',function(){
                switch(this.value){
                    case '':
                    break;
                    case "taiwan":
                    var list = taiwan;
                    break;
                    case "usa":
                    var list = usa;
                    break;
                };
                document.getElementById('city').innerHTML = '';  //清空選單
                document.getElementById('district').innerHTML = '';  //清空選單
                var option = document.createElement('option');

                option.innerHTML = '<option>'+'選擇城市'+'</option>';
                document.getElementById('city').insertBefore(option, null);
                for(i=0; i<list.length ;i++){
                    var option = document.createElement('option');
                    option.innerHTML = list[i]['CityName'];
                    option.setAttribute('value', list[i]["CityEngName"]);
                    document.getElementById('city').insertBefore(option, null);
                }
            });
            
            document.getElementById('city').addEventListener('change',function(){
                switch(this.value){
                    case '':
                    break;
                    case "Taipei City":
                    var list = taiwan[0]['AreaList'];
                    break;
                    case "Hsinchu city":
                    var list = taiwan[1]['AreaList'];
                    break;
                };
                document.getElementById('district').innerHTML = '';  //清空選單
                var option = document.createElement('option');

                option.innerHTML = '<option>'+'選擇區域'+'</option>';
                document.getElementById('district').insertBefore(option, null);
                for(i=0; i < list.length; i++){
                    var option = document.createElement('option');
                    option.innerHTML = list[i]['AreaName'];
                    document.getElementById('district').insertBefore(option, null);
                }
            });
        };
        
    </script>
</body>
</html>
Han iT邦新手 5 級 ‧ 2019-07-24 17:09:13 檢舉
小建議
var elDistrict = document.getElementById('district') ;
像這種會重複利用的抓到之後,可以存變數重複使用
每次都抓的話js都要再爬一次
然後可以用jQuery會更簡化XD
var elDistrict = $('#district') ;

其他優化交給其他大佬...
1
浩瀚星空
iT邦大師 1 級 ‧ 2019-07-24 17:15:26

說真的,能用javascript原生碼寫成這樣算不錯了。
真要簡化的話。給你幾個建議好了。

1.insertBefore的動作可以在for完後再做。你也可以直接用innerHTML處理就好。

2.省略掉 switch 的判斷。全使用指標式資料。不要單純用0 1key值處理。全用指定key。你就可預不需要用switch處理。且你用switch處理也太累了吧。

最後,其實我建議你學一下jquery的處理方式,可以讓你的程式碼更乾淨易懂。
一些需要兩三行才能處理的,透過jquery一行就可以處理了。

cheer0101 iT邦新手 5 級 ‧ 2019-07-24 17:23:54 檢舉

感謝星大,用js是因為最近在練習,所以想說盡量用js寫
我會試著改掉switch的寫法 謝謝

cheer0101 iT邦新手 5 級 ‧ 2019-07-24 20:12:00 檢舉

請問何謂 指標式資料 我找不太到 謝謝

dragonH iT邦大師 1 級 ‧ 2019-07-24 20:48:48 檢舉

星空大的意思應該是說不要寫死

根據所選值

來找到相對應的位置吧

1
dragonH
iT邦大師 1 級 ‧ 2019-07-24 17:27:35

codepen

const countrySelect = document.getElementById('country');
const citySelect = document.getElementById('city');
const districtSelect = document.getElementById('district');
let allCities = '';
let allAreas = '';
let defaultOption = '<option value = "">---請選擇---</option>';
countrySelect.innerHTML = `${defaultOption}${allCountries.map(el => `<option value = "${el.CountryEngName}">${el.CountryName}</option>`).join('')}`;
countrySelect.addEventListener('change', (e) => {
  const countryPosition = allCountries.map(country => country.CountryEngName).indexOf(e.target.value);
  allCities = countryPosition > -1
    ? allCountries[countryPosition].Cities
    : [];
  citySelect.innerHTML = `${defaultOption}${allCities.map(city => `<option value = "${city.CityEngName}">${city.CityName}</option>`).join('')}`;
  districtSelect.innerHTML = defaultOption;
});

citySelect.addEventListener('change', (e) => {
  const cityPosition = allCities.map(city => city.CityEngName).indexOf(e.target.value);
  allAreas = cityPosition > -1
    ? allCities[cityPosition].AreaList
    : [];
  districtSelect.innerHTML = `${defaultOption}${allAreas.map(area => `<option value = "${area.AreaEngName}">${area.AreaName}</option>`).join('')}`;
});

大概就這樣

主要就是
map

Template literals
的應用


換了一下寫法

這個寫法就可以往 allData 加新的資料

且不用動 code

marlin12 iT邦新手 2 級 ‧ 2019-07-25 00:09:44 檢舉

為何citySelect.addEventListener只用[台灣]的資料?
如果用戶在[國家]選擇[美國],districtSelect會否送錯資料?

dragonH iT邦大師 1 級 ‧ 2019-07-25 00:43:14 檢舉

漏掉了 已補上XD/images/emoticon/emoticon14.gif
感謝告知

不過您所說的情況不會發生

因為我一開始沒給美國資料

所以選完美國就不能選了

不過有資料就會有這個情況發生/images/emoticon/emoticon16.gif

0
conmy2002
iT邦新手 5 級 ‧ 2019-07-25 08:20:13
const options = {
 taiwan: [ /* ... */ ],
 usa: [ /* ... */ ]
}
const selectedValue = "taiwan";
const list = options[selectedValue]

另外 option 的 element 可以先寫入 fragment 已提高效能

0
淺水員
iT邦新手 2 級 ‧ 2019-07-25 13:11:18

我試著把它做成一個物件,可以透過 add 方法設定每層關聯的 key
最後再用 update 方法渲染選單
希望的使用方式如下:

new SelectChain(data)
	.add('country','CountryEngName','CountryName','CityList','請選擇國家')
	.add('city','CityEngName','CityName','AreaList','請選擇城市')
	.add('area','AreaEngName','AreaName',null,'請選擇區域')
	.update();

實作後的參考範例:codepen

我要發表回答

立即登入回答