I use the prototype chain to write a method of linking provinces and municipalities. I put the variables into the initial function so that I can use the prototype chain to expand. There was no problem during initialization, but something went wrong when I used onchange to select a province or city. The attribute options of selectProvince and selectCity could not be found. I looked up and found that selectProvince and selectCity were not detected at all when using onchange. Yeah, I obviously initialized it in AddressInit, but it wasn't detected. Could you please give me a solution?
Code:
//This is a short piece of json
var provinceList = [{
name: '北京',
cityList: [{
name: '市轄區(qū)',
areaList: ['東城區(qū)', '西城區(qū)', '崇文區(qū)', '宣武區(qū)', '朝陽區(qū)', '豐臺區(qū)', '石景山區(qū)', '海淀區(qū)', '門頭溝區(qū)', '房山區(qū)', '通州區(qū)', '順義區(qū)', '昌平區(qū)', '大興區(qū)', '懷柔區(qū)', '平谷區(qū)']
}, {
name: '縣',
areaList: ['密云縣', '延慶縣']
}]
}];
//This is 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>
//This is 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();
認(rèn)證0級講師
The callback function requires the correct this environment.
Put this line
this.selectCity.onchange = this.changeCity;
changed to
this.selectCity.onchange = this.changeCity.bind(this);
As mentioned above, there is a problem with this pointer:
this.selectProvince.onchange = this.changeProvince;
You mean that the handler function of select's change event is this.changeProvince
, which is a reference to it.
Actually, it is as follows:
document.getElementById(selectProvince).onchange = function(){
console.log(selectCity);
this.selectCity.options.length = 0; // 觸發(fā)時報錯this.selectCity為undefined 因為this是dom元素
this.selectCity.onchange = null; // 觸發(fā)時報錯this.selectCity為undefined
if (this.selectProvince.selectedIndex == -1) return; // 觸發(fā)時報錯this.selectProvince為undefined 下面的this基本都有問題 事件處理函數(shù)中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;
}
Can you see the problem? this
指的是dom對象,即document.getElementById(selectProvince)
in the event handler function certainly doesn’t have what you need.
can be replaced by this.selectCity.onchange = this.changeCity.bind(this)
this.selectCity.onchange = this.changeCity;
這樣寫 只是表示selectCity.onchange 也是 this.changeCity
這個函數(shù),在js中,this的指向是實際運(yùn)行時才決定,在onchange事件觸發(fā)時,this.changeCity
函數(shù)內(nèi)的this
為dom元素,所以就出錯了。bind
方法可以替換函數(shù)內(nèi)的this
points to generate a new function.
is this.changeCity.bind(this)
這句在運(yùn)行時,已經(jīng)將this.changeCity
函數(shù)內(nèi)的this
替換為了當(dāng)前的this
(this this refers to your instance object), so as to achieve the effect you need.