如何在dom-repeater调用的返回items的方法中访问元素作用域(this)?
解决dom-repeat的items方法中无法访问元素作用域的问题
嘿,我之前也踩过这个坑!当你把getItems()方法绑定到dom-repeat的items属性时,默认情况下方法里的this并不会指向你的元素实例——这是因为方法被当作普通函数调用,丢失了原本的上下文,所以你才没法访问this.begin这类元素属性。下面给你几种实用的解决办法:
方法一:在元素初始化时绑定方法的上下文
在元素的ready(Polymer 1.x)或者constructor/connectedCallback(Polymer 2+/3.x)生命周期钩子中,用bind()把getItems方法的this绑定到元素实例上:
// 以Polymer 2.x为例 ready() { super.ready(); // 绑定this,确保getItems里的this指向当前元素 this.getItems = this.getItems.bind(this); } getItems() { // 现在这里的this就是你的元素实例了,可以正常访问this.begin return this.sourceItems.filter(item => item.timestamp >= this.begin); }
方法二:用箭头函数定义方法(Polymer 2+/3.x 支持类语法时)
箭头函数会自动捕获词法作用域的this,所以如果你的元素是用ES6类定义的,可以直接把getItems写成箭头函数:
class MyCustomElement extends PolymerElement { static get template() { return html` <dom-repeat items="[[getItems()]]"> <!-- 你的模板内容 --> </dom-repeat> `; } // 箭头函数的this会绑定到当前元素实例 getItems = () => { return this.sourceItems.filter(item => item.date >= this.begin); } }
注意:这种方式每次渲染都会创建新的箭头函数,在列表数据量大或者频繁更新的场景下可能有轻微性能影响,简单场景下用起来很省心。
方法三:改用计算属性(推荐)
如果getItems的结果依赖于元素的某些属性(比如this.begin和原始数据数组),更符合Polymer设计理念的做法是使用计算属性。计算属性的this天然指向元素实例,而且只会在依赖的属性变化时重新计算,性能更优:
class MyCustomElement extends PolymerElement { static get properties() { return { begin: { type: Date }, sourceItems: { type: Array }, // 计算属性,依赖begin和sourceItems的变化 filteredItems: { type: Array, computed: '_computeFilteredItems(begin, sourceItems.*)' } }; } _computeFilteredItems(begin, sourceItemsChange) { const items = sourceItemsChange.base; // 获取原始数组 if (!begin || !items) return []; return items.filter(item => item.date >= begin); } }
然后在模板里直接绑定计算属性:
<dom-repeat items="[[filteredItems]]"> <!-- 你的模板内容 --> </dom-repeat>
为什么原来的方法不行?
简单来说,dom-repeat在调用你绑定的getItems()时,是直接以普通函数的方式调用的,没有指定this的指向。在严格模式下,这种调用方式的this会是undefined;非严格模式则指向全局对象,自然没法访问元素的this.begin。
内容的提问来源于stack exchange,提问作者yglodt
相关产品推荐
相关产品推荐

