我用原型鏈來寫一個省市區連動的方法,我將變數放進初始的函數中,以便我用原型鏈拓展時使用。初始化時沒問題的,但在我用onchange選擇省或市時就出問題了,selectProvince和selectCity的屬性options找不到,我在往上查找了一下,發現selectProvince和selectCity在用onchange時根本沒有檢測到,我明明在AddressInit裡面初始化了,但卻沒偵測到,求解?
程式碼:
//這是一小段的json
var provinceList = [{
name: '北京',
cityList: [{
name: '市辖区',
areaList: ['东城区', '西城区', '崇文区', '宣武区', '朝阳区', '丰台区', '石景山区', '海淀区', '门头沟区', '房山区', '通州区', '顺义区', '昌平区', '大兴区', '怀柔区', '平谷区']
}, {
name: '县',
areaList: ['密云县', '延庆县']
}]
}];
//這是html
<select class="select-input" name="selectProvince" id="selectProvince"></select>
<select class="select-input" name="selectCity" id="selectCity"></select>
<select class="select-input" name="selectArea" id="selectArea"></select>
//這是js
var AddressInit = function(selectProvince, selectCity, selectArea, defaultProvince, defaultCity, defaultArea){
this.selectProvince = document.getElementById(selectProvince);
this.selectCity = document.getElementById(selectCity);
this.selectArea = document.getElementById(selectArea);
this.defaultProvince = defaultProvince || '';
this.defaultCity = defaultCity || '';
this.defaultArea = defaultArea || '';
}
AddressInit.prototype = {
constructor: AddressInit,
//初始化
init: function(){
for (var i = 0; i < provinceList.length; i++) {
this.selectAddOption(this.selectProvince, provinceList[i].name, provinceList[i]);
}
this.selected(this.selectProvince, this.defaultProvince);
this.changeProvince();
this.selectProvince.onchange = this.changeProvince;
},
//判断是否有选中的值
selected: function(select,str){
for(var i = 0; i < select.options.length; i++) {
if (select.options[i].value == str) {
select.selectedIndex = i;
return;
}
}
},
//添加option
selectAddOption: function(select, str, obj) {
var option = document.createElement("option");
select.options.add(option);
option.innerText = str;
option.value = str;
option.obj = obj;
},
//改变省
changeProvince: function(){
console.log(selectCity);
this.selectCity.options.length = 0;
this.selectCity.onchange = null;
if (this.selectProvince.selectedIndex == -1) return;
var item = this.selectProvince.options[this.selectProvince.selectedIndex].obj;
for (var i = 0; i < item.cityList.length; i++) {
this.selectAddOption(this.selectCity, item.cityList[i].name, item.cityList[i]);
}
this.selected(this.selectCity, this.defaultCity);
this.changeCity();
this.selectCity.onchange = this.changeCity;
},
//改变市
changeCity: function(){
this.selectArea.options.length = 0;
if (this.selectCity.selectedIndex == -1) return;
var item = this.selectCity.options[this.selectCity.selectedIndex].obj;
for (var i = 0; i < item.areaList.length; i++) {
this.selectAddOption(this.selectArea, item.areaList[i], null);
}
this.selected(this.selectArea, this.defaultArea);
}
}
var ccc = new AddressInit('selectProvince', 'selectCity', 'selectArea');
ccc.init();
回呼函數需要正確的 this 環境。
把這行
改成
如樓上所言,是this指向出了問題:
this.selectProvince.onchange = this.changeProvince;
你的意思是指select的change事件的處理函數為
this.changeProvince
, 即對其的一個引用。實際也就是如下:
看得出問題了嗎?事件處理函數中的
this
指的是dom对象,即document.getElementById(selectProvince)
它上面當然沒有你需要的東西了。可以如樓上所言的換為
this.selectCity.onchange = this.changeCity.bind(this)
this.selectCity.onchange = this.changeCity;
这样写 只是表示selectCity.onchange 也是this.changeCity
这个函数,在js中,this的指向是实际运行时才决定,在onchange事件触发时,this.changeCity
函数内的this
为dom元素,所以就出错了。bind
方法可以替换函数内的this
指向,產生一個新的函數。即
this.changeCity.bind(this)
这句在运行时,已经将this.changeCity
函数内的this
替换为了当前的this
(這個this是指你的實例物件),從而達到你所需要的效果。