Polymer 2触发事件时Local DOM元素出现TypeError问题求助
问题分析与解决办法
这个问题的核心是函数执行时的this指向丢失,导致_disableBtn里的this不是你的<app-search>组件实例,而是触发search事件的输入框元素,所以this._doneBtn会返回undefined。下面具体拆解原因和解决办法:
为什么会出现这个问题?
当你给输入框绑定search事件时,如果是通过原生addEventListener手动绑定且未处理函数上下文,函数执行时的this会默认指向触发事件的DOM元素(也就是你的搜索输入框),而非组件本身。这就是你看到console.log(this)出现两个不同实例的原因——一个是组件实例,一个是输入框元素。
解决办法(按推荐优先级排序)
1. 用Polymer模板绑定的标准方式(最省心)
如果你是在组件的HTML模板里使用<paper-input>,直接在模板上通过on-search绑定事件,Polymer会自动帮你把函数的this绑定到组件实例:
<!-- 在你的<app-search>模板里 --> <paper-input id="searchInput" on-search="_disableBtn" on-input="_onInput" placeholder="输入搜索内容..." ></paper-input> <paper-button id="doneBtn" disabled>搜索</paper-button>
对应的JS部分,你甚至不需要手动获取按钮引用——Polymer会自动把带id的元素挂载到this.$对象上,代码可以简化成:
class AppSearch extends Polymer.Element { static get is() { return 'app-search'; } _disableBtn() { // this.$.doneBtn就是你的按钮元素,无需在ready()里手动查询 this.$.doneBtn.disabled = true; } _onInput(e) { this.$.doneBtn.disabled = !e.target.value.trim(); } } customElements.define(AppSearch.is, AppSearch);
2. 手动绑定事件时,强制绑定组件上下文
如果因为某些原因必须用JS代码手动绑定search事件,一定要通过箭头函数或者bind()把this绑定到组件实例:
ready() { super.ready(); // 用Polymer的自动节点查找,比querySelector更可靠 this._doneBtn = this.$.doneBtn; const searchInput = this.$.searchInput; // 方式一:箭头函数(继承外部作用域的this,也就是组件实例) searchInput.addEventListener('search', () => { this._disableBtn(); }); // 方式二:用bind()强制绑定this // searchInput.addEventListener('search', this._disableBtn.bind(this)); }
3. 避免错误的函数定义方式
不要用箭头函数定义Polymer的自定义方法(比如_disableBtn),因为箭头函数的this是定义时的上下文,而Polymer需要通过普通函数来绑定组件上下文:
// 正确的写法:普通函数 _disableBtn() { this._doneBtn.disabled = true; } // 错误的写法:箭头函数,会导致this指向错误 // _disableBtn = () => { // this._doneBtn.disabled = true; // }
额外排查小技巧
- 在
ready()里加console.log(this._doneBtn),确认按钮元素是否被正确获取; - 优先使用Polymer的
this.$.xxx获取DOM节点,比手动querySelector更可靠,尤其是在Shadow DOM环境下。
内容的提问来源于stack exchange,提问作者David Gaskin
相关产品推荐
相关产品推荐

