我有一个搜索输入字段来接收用户输入和一个响应用户输入的变量状态按钮。注意搜索输入上的on-input
事件。
<dom-module id="app-search">
<template>
<input type="search" id="searchInput" on-input="_onInput" />
<!-- NOTE: button is set to 'disabled' when there is no value of search field -->
<paper-button disabled>Done</paper-button>
</template>
</dom-module>
在Polymer ready()
定义中,我获得了paper-button
元素的句柄(ready()
函数在所有内容之后被调用,包括在元素及其属性被初始化之后,所以它是是查询本地DOM的好时机。
ready() {
super.ready(); // must call this for Polymer to work
// get handle to paper-button element
this._doneBtn = Polymer.dom(this.root).querySelector('paper-button');
}
(顺便说一下,我知道使用this.$
可以用作Polymer.dom(this.root).querySelector()
的语法快捷方式,但该语法似乎只适用于具有id
的本地DOM,例如:this.$.searchInput
将返回带有id="searchInput"
元素的句柄。是否有人知道定位非id,常规元素的简写必须输入Polymer.dom(this.root)...
?)
我有一个功能可以检测搜索字段上的input
个事件。如果搜索字段中有值,请启用该按钮。
_onInput() {
// if search input has value
if (Boolean(this.$.searchInput.value)) {
// remove disabled attr from button
this._doneBtn.removeAttribute('disabled');
} else {
this._disableBtn();
}
}
_disableBtn() {
this._doneBtn.setAttribute('disabled', true);
}
到目前为止,这样做是为了当用户开始输入时,按钮变为启用状态;当没有值时,该按钮被禁用。
但是,按照惯例,用户还可以通过单击搜索输入右侧显示的小“x”来删除输入值。开发人员可以通过将search
事件附加到input元素来检测该事件:
ready() {
super.ready(); // must call this for Polymer to work
// get handle to paper-button element
this._doneBtn = Polymer.dom(this.root).querySelector('paper-button');
// attach 'search' event listener to search input field
// call the element's '_disableBtn' function
this.$.searchInput.addEventListener('search', this._disableBtn);
}
问题当我通过点击搜索字段有值时显示的“x”来触发事件时,this._disableBtn
函数会触发,但this._doneBtn
内部会出现_doneBtn
函数返回undefined :
Uncaught TypeError: Cannot read property 'setAttribute' of undefined
假设这可能与不正确的类型定义有关,我尝试在Polymer属性getter中声明static get properties() {
return {
_doneBtn: Object // also tried 'String'
}
}
属性:
_disabledBtn
我还尝试再次从_disableBtn() {
if (!this._doneBtn) {
this._doneBtn = Polymer.dom(this.root).querySelector('paper-button');
}
this._doneBtn.setAttribute('disabled', true);
}
函数内部查询DOM并尝试重新声明属性,但我仍然得到同样的错误:
ready()
有谁能理解这里发生了什么?这似乎与事件监听器有关。虽然在this
调用中切换声明的顺序没有区别,但DOM在解析之前可能没有完全呈现?它也可能与console.log(this)
有关。
有趣的是,当我在_disableBtn
内this
时,控制台会返回两个不同的<app-search>
实例,一个用于主机元素(this
),另一个用于目标元素解雇了这个事件:two elements point to 'this'。另外值得注意的是打印@Override
protected void onCreate(Bundle _savedInstanceState) {
super.onCreate(_savedInstanceState);
setContentView(R.layout.main);
MobileAds.initialize(this, "ca-app-pub-3940256099942544~3347511713");
mAdView = findViewById(R.id.adView);
mAdView.loadAd(new AdRequest.Builder().build());
mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId("ca-app-pub-3940256099942544/1033173712");
mInterstitialAd.loadAd(new AdRequest.Builder().build());
mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onAdLoaded() {
SketchwareUtil.showMessage(getApplicationContext(), "Tap to start");
}
});
initialize();
}
private void initialize() {
imageview1 = (ImageView) findViewById(R.id.imageview1);
imageview1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
i.setClass(getApplicationContext(), PlaylistActivity.class);
startActivity(i);
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
} else {
showMessage("Error");
Log.d("AD", "The interstitial wasn't loaded yet.");
}
}
});
}
的顺序。
我希望比我更聪明的人可以帮助解决这里发生的事情。感谢。
答案 0 :(得分:1)
我的直觉是你没有正确使用“这个”。 “this”表达是违反直觉的,因为我们倾向于自动将其与词法范围或使用“this”的位置相关联。唉,情况并非如此,因为“this”绑定不是在JIT“编译时”或“运行时”确定,而是在“通话时间”确定。
这表示调用它的上下文。因此,只需将一行代码从一个函数移动到另一个函数,“this”就可以引用其他内容。而其他东西可能没有附加“setAttribute”函数,因此“未定义”错误消息。
解决这个问题的一种方法(没有双关语意)现实是用.bind配置被调用的函数([调用该函数时我们想要“这个”的值])。
例如,而不是编写以下代码段:
} else {
this._disableBtn();
}
你会写的
} else {
this._disableBtn().bind(this);
}
你可能已经确定你在_disableBtn()函数中使用的“this”指向与“this”在“else”块中所做的目标相同的目标。
基本上,“this”值取决于原始调用站点上下文所使用的函数被调用(我不确定这是否清楚......但如果它没有意义,请重新读取它第一次飞行)。要在被调用函数中对“this”的值进行硬编码,可以在调用函数时添加.bind(要传递给被调用函数的“this”值),如:
function aFunction() {
myfunction(parameter).bind("required value of 'this' in myFunction").
}
希望这有帮助。
杰克
答案 1 :(得分:1)
在阅读@ softjake的回复后,我能够解决问题。
首先,让我们重新审视addEventListener()
函数中添加的ready()
设置:
ready() {
super.ready();
// handle to toggle button element
this._doneBtn = Polymer.dom(this.root).querySelector('paper-button');
// previous method === no worky
//this.$.searchInput.addEventListener('search', this._disableBtn);
// changed it to:
this.$.searchInput.addEventListener('search', this._disableBtn.bind(this._doneBtn));
}
这里的关键是我使用.bind(this._doneBtn)
确保this
,_disableBtn
函数范围内的this._doneBtn
而不是其他this
_disableBtn
1}}(与父元素或文档/窗口一样)。
最后,稍微调整_disableBtn() {
// previous (also no worky)
//this._doneBtn.setAttribute('disabled', true);
// changed to:
this.setAttribute('disabled', true);
}
功能:
this
由于this._doneBtn
已引用this.setAttribute(...)
,我们只需使用// GET: api/Categories
[HttpGet]
public IEnumerable<Category> GetCategories()
{
return _context.Categories;
}
。