我用原型链来写一个省市区联动的方法,我将变量放进初始的函数中,以便我用原型链拓展时使用。初始化时没问题的,但是在我用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();
ringa_lee2017-05-19 10:26:13
回调函数需要正确的 this 环境。
把这行
this.selectCity.onchange = this.changeCity;
改成
this.selectCity.onchange = this.changeCity.bind(this);
滿天的星座2017-05-19 10:26:13
如楼上所言,是this指向出了问题:
this.selectProvince.onchange = this.changeProvince;
你的意思是指select的change事件的处理函数为 this.changeProvince
, 即对其的一个引用。
实际也就是如下:
document.getElementById(selectProvince).onchange = function(){
console.log(selectCity);
this.selectCity.options.length = 0; // 触发时报错this.selectCity为undefined 因为this是dom元素
this.selectCity.onchange = null; // 触发时报错this.selectCity为undefined
if (this.selectProvince.selectedIndex == -1) return; // 触发时报错this.selectProvince为undefined 下面的this基本都有问题 事件处理函数中this为dom元素,而不是你的实例对象。
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;
}
能看出问题了吗?事件处理函数中的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是指你的实例对象),从而达到你需要的效果。