在事件调用的组件方法中访问组件 属性
Access to component property inside a component method called by an event
我有一个组件,当在任何地方单击 window 时都会切换。
为了实现这一点,我将组件方法作为全局事件绑定到 body
元素。
此外,我需要在组件方法中访问组件 属性,该组件方法由绑定到 body
元素的点击事件调用。
但是没用:
app/components/example-component.js:
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
didInsertElement() {
console.log('start didInsertElement() ************************************************************');
console.log('- "this" is the Ember.js component:');
console.log(this.$());
console.log('- "this.exampleProperty" has the Ember.js component value:');
console.log(this.exampleProperty);
Ember.$('body').click(this.exampleMethod).click();
console.log('end didInsertElement() ************************************************************');
},
exampleMethod(event) {
console.log('start exampleMethod() ************************************************************');
console.log('- "this" is the DOM element that has triggered the event:');
console.log(Ember.$(this));
// console.log(this.$()); This doesn't work
console.log('- "this.exampleProperty" is undefined:');
console.log(this.exampleProperty);
console.log('end exampleMethod() ************************************************************');
},
});
如何让它工作?
好吧,我有一个可行的解决方案,但我觉得它不是很优雅。
Ember.js 组件必须作为事件数据传递给回调函数:
app/components/example-component.js:
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
didInsertElement() {
console.log('start didInsertElement() ************************************************************');
console.log('- "this" is the Ember.js component:');
console.log(this.$());
console.log('- "this.exampleProperty" has the Ember.js component value:');
console.log(this.exampleProperty);
Ember.$('body').click(this, this.exampleMethod).click();
console.log('end didInsertElement() ************************************************************');
},
exampleMethod(event) {
console.log('start exampleMethod() ************************************************************');
console.log('- "this" is the DOM element that has triggered the event:');
console.log(Ember.$(this));
// console.log(this.$()); This doesn't work
console.log('- "this.exampleProperty" is undefined:');
console.log(this.exampleProperty);
console.log('- To access the component\'s "this.exampleProperty" the event data must be used:');
const exampleComponent = event.data;
console.log(exampleComponent.exampleProperty);
console.log('end exampleMethod() ************************************************************');
},
});
这里有 Ember Twiddle.
虽然这是一个可行的解决方案,但我发现它丑陋且不切实际。所以如果你有更好的方法,请post.
还有其他选项我觉得更糟糕,比如将组件 属性 传递给事件数据而不是整个组件,但是如果 属性 更新,事件数据不会这样'得到零钱。
不确定它是否提供了您正在寻找的更简洁的方法,但 .bind(this)
可能会有所帮助。
// Using bind:
Ember.$('body').click(this, this.exampleMethod.bind(this)).click();
// Results in the below working as you desire:
this.$(); //returns jQuery.fn.init [div#ember256.ember-view, context: div#ember256.ember-view]
Ember.get(this, 'exampleProperty'); //returns 'example value'
每个组件都有 click
处理程序,只要单击组件就会调用它。但是在您的情况下,您希望在单击 body
元素时触发组件方法,因此您的方法就是要走的路。但唯一缺少的部分是 bind
和清除事件。
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
exampleMethodHandler: null,
init() {
this._super(...arguments);
//bind function will return the function with scope changed to this.
this._exampleMethodHandler = Ember.run.bind(this, this.exampleMethod);
},
didInsertElement() {
this._super(...arguments);
Ember.$('body').on('click', this._exampleMethodHandler);
},
willDestroyElement() {
this._super(...arguments);
//Need to clear the registered event handler.
if (this._exampleMethodHandler) {
Ember.$('body').off('click', this._exampleMethodHandler);
}
},
exampleMethod() {
//Here this will refers to component,
console.log('ComponentProperty access as usual ",this.get('exampleProperty'),event);
},
});
注意:我缓存了绑定函数返回的函数引用,因为我们需要提供完全相同的引用来拆除。
所以
Ember.$('body').on('click',this.exampleMethod.bind(this))
Ember.$('body').off('click', this.exampleMethod);
以上不会拆除附加的事件处理程序,因为两个引用不同。
我想在 but without the 之后提供 bind()
的完整示例,并避免使用额外的处理程序对象,例如 exampleMethodHandler
:
app/components/example-component.js:
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
didInsertElement() {
this._super(...arguments);
// create a new function with 'this' as bound argument
this.exampleMethod = this.exampleMethod.bind(this);
// bind exampleMethod() function to event without arguments
Ember.$('body').click(this, this.exampleMethod).click();
},
willDestroyElement() {
this._super(...arguments);
// unbind exampleMethod() function from event successfully without arguments
Ember.$('body').off('click', this.exampleMethod);
},
exampleMethod() {
// inside exampleMethod() 'this' is the Ember.js component
// as bound before, not the DOM element that has triggered the event
console.log('Ember.js property: ", this.get('exampleProperty'));
},
});
The bind()
function creates a new bound function (BF). A BF is an
exotic function object (a term from ECMAScript 2015) that wraps the
original function object. Calling a BF generally results in the
execution of its wrapped function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
因此,如果使用 bind()
创建一个新函数,如果它是匿名使用的,则以后不能重新引用它。因此,这不起作用:
// bind() creates a new function which here is anonymous
Ember.$('body').click(this, this.exampleMethod.bind(this));
// this.exampleMethod() is not the former anonymous function
Ember.$('body').off('click', this.exampleMethod);
// here things are worse as a new anonymous function is created
Ember.$('body').off('click', this.exampleMethod.bind(this));
为了以后能够引用新的绑定函数,必须将其命名为:
// create new bound function and store it in 'this.exampleMethod'
this.exampleMethod = this.exampleMethod.bind(this);
// bound function this.exampleMethod() referenced
Ember.$('body').click(this, this.exampleMethod);
// same bound function this.exampleMethod() referenced again
Ember.$('body').off('click', this.exampleMethod);
我有一个组件,当在任何地方单击 window 时都会切换。
为了实现这一点,我将组件方法作为全局事件绑定到 body
元素。
此外,我需要在组件方法中访问组件 属性,该组件方法由绑定到 body
元素的点击事件调用。
但是没用:
app/components/example-component.js:
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
didInsertElement() {
console.log('start didInsertElement() ************************************************************');
console.log('- "this" is the Ember.js component:');
console.log(this.$());
console.log('- "this.exampleProperty" has the Ember.js component value:');
console.log(this.exampleProperty);
Ember.$('body').click(this.exampleMethod).click();
console.log('end didInsertElement() ************************************************************');
},
exampleMethod(event) {
console.log('start exampleMethod() ************************************************************');
console.log('- "this" is the DOM element that has triggered the event:');
console.log(Ember.$(this));
// console.log(this.$()); This doesn't work
console.log('- "this.exampleProperty" is undefined:');
console.log(this.exampleProperty);
console.log('end exampleMethod() ************************************************************');
},
});
如何让它工作?
好吧,我有一个可行的解决方案,但我觉得它不是很优雅。
Ember.js 组件必须作为事件数据传递给回调函数:
app/components/example-component.js:
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
didInsertElement() {
console.log('start didInsertElement() ************************************************************');
console.log('- "this" is the Ember.js component:');
console.log(this.$());
console.log('- "this.exampleProperty" has the Ember.js component value:');
console.log(this.exampleProperty);
Ember.$('body').click(this, this.exampleMethod).click();
console.log('end didInsertElement() ************************************************************');
},
exampleMethod(event) {
console.log('start exampleMethod() ************************************************************');
console.log('- "this" is the DOM element that has triggered the event:');
console.log(Ember.$(this));
// console.log(this.$()); This doesn't work
console.log('- "this.exampleProperty" is undefined:');
console.log(this.exampleProperty);
console.log('- To access the component\'s "this.exampleProperty" the event data must be used:');
const exampleComponent = event.data;
console.log(exampleComponent.exampleProperty);
console.log('end exampleMethod() ************************************************************');
},
});
这里有 Ember Twiddle.
虽然这是一个可行的解决方案,但我发现它丑陋且不切实际。所以如果你有更好的方法,请post.
还有其他选项我觉得更糟糕,比如将组件 属性 传递给事件数据而不是整个组件,但是如果 属性 更新,事件数据不会这样'得到零钱。
不确定它是否提供了您正在寻找的更简洁的方法,但 .bind(this)
可能会有所帮助。
// Using bind:
Ember.$('body').click(this, this.exampleMethod.bind(this)).click();
// Results in the below working as you desire:
this.$(); //returns jQuery.fn.init [div#ember256.ember-view, context: div#ember256.ember-view]
Ember.get(this, 'exampleProperty'); //returns 'example value'
每个组件都有 click
处理程序,只要单击组件就会调用它。但是在您的情况下,您希望在单击 body
元素时触发组件方法,因此您的方法就是要走的路。但唯一缺少的部分是 bind
和清除事件。
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
exampleMethodHandler: null,
init() {
this._super(...arguments);
//bind function will return the function with scope changed to this.
this._exampleMethodHandler = Ember.run.bind(this, this.exampleMethod);
},
didInsertElement() {
this._super(...arguments);
Ember.$('body').on('click', this._exampleMethodHandler);
},
willDestroyElement() {
this._super(...arguments);
//Need to clear the registered event handler.
if (this._exampleMethodHandler) {
Ember.$('body').off('click', this._exampleMethodHandler);
}
},
exampleMethod() {
//Here this will refers to component,
console.log('ComponentProperty access as usual ",this.get('exampleProperty'),event);
},
});
注意:我缓存了绑定函数返回的函数引用,因为我们需要提供完全相同的引用来拆除。
所以
Ember.$('body').on('click',this.exampleMethod.bind(this))
Ember.$('body').off('click', this.exampleMethod);
以上不会拆除附加的事件处理程序,因为两个引用不同。
我想在 bind()
的完整示例,并避免使用额外的处理程序对象,例如 exampleMethodHandler
:
app/components/example-component.js:
import Ember from 'ember';
export default Ember.Component.extend({
exampleProperty: 'example value',
didInsertElement() {
this._super(...arguments);
// create a new function with 'this' as bound argument
this.exampleMethod = this.exampleMethod.bind(this);
// bind exampleMethod() function to event without arguments
Ember.$('body').click(this, this.exampleMethod).click();
},
willDestroyElement() {
this._super(...arguments);
// unbind exampleMethod() function from event successfully without arguments
Ember.$('body').off('click', this.exampleMethod);
},
exampleMethod() {
// inside exampleMethod() 'this' is the Ember.js component
// as bound before, not the DOM element that has triggered the event
console.log('Ember.js property: ", this.get('exampleProperty'));
},
});
The
bind()
function creates a new bound function (BF). A BF is an exotic function object (a term from ECMAScript 2015) that wraps the original function object. Calling a BF generally results in the execution of its wrapped function.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
因此,如果使用 bind()
创建一个新函数,如果它是匿名使用的,则以后不能重新引用它。因此,这不起作用:
// bind() creates a new function which here is anonymous
Ember.$('body').click(this, this.exampleMethod.bind(this));
// this.exampleMethod() is not the former anonymous function
Ember.$('body').off('click', this.exampleMethod);
// here things are worse as a new anonymous function is created
Ember.$('body').off('click', this.exampleMethod.bind(this));
为了以后能够引用新的绑定函数,必须将其命名为:
// create new bound function and store it in 'this.exampleMethod'
this.exampleMethod = this.exampleMethod.bind(this);
// bound function this.exampleMethod() referenced
Ember.$('body').click(this, this.exampleMethod);
// same bound function this.exampleMethod() referenced again
Ember.$('body').off('click', this.exampleMethod);