naver / egjs-component Goto Github PK
View Code? Open in Web Editor NEWA class used to manage events in a component like DOM
Home Page: https://naver.github.io/egjs-component
A class used to manage events in a component like DOM
Home Page: https://naver.github.io/egjs-component
@vreality64 commented on Mon Feb 20 2017
I'll mention 3 things.
I have one controller and two modules. everything is class inherited from eg.Component
.
// Controller, Module A, Module B
var instance = new eg.Class.extend(eg.Component, {
// ...
});
I tried handle custom event state between modules and controller using customEvent.stop()
function. But stop was not worked.
Trigger Docs: If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring.
Here are code.
// Controller has Module A. Module A has Module B.
// every callback function is wrapped `$.proxy` with `this` context.
// this.module.on('eventName', $.proxy(callback, this));
// In Controller
moduleA.on('beforeSelect', function (event) {
event.stop();
});
// In Module A
moduleB.on('beforeSelect', function (event) {
this.trigger('beforeSelect', event); // reuse event object
});
// In Module B
this.on('click', function (event) {
if (this.trigger('beforeSelect')) {
this.select('data');
}
})
Code describes that if controller calls event.stop()
then doesn't execute moduleB.select()
. because stop()
makes trigger
return false
.
I think reusing custom event is common case. normally custom event has data, so it was broadcasted to system.
But when it reused, isCanceled
variable was overridden.
trigger: function(eventName, customEvent) {
// event(data) Object are alive.
customEvent = customEvent || {};
// ...
// isCanceled variable is overridden.
var isCanceled = false;
// ...
return !isCanceled;
},
If intended, it is notable.
I changed middle module. not re-used event object
// [Before] In Module A
moduleB.on('beforeSelect', function (event) {
this.trigger('beforeSelect', event); // reuse event object
}
// [Changed] In Module A
moduleB.on('beforeSelect', function (event) {
var stop = !this.trigger("beforeSelect"); // not re-used event object
if (stop) {
event.stop();
}
}
I made JS fiddle example. you can reproduce my situation.
I can't sure what is right, so just want to know decision history. what philosophy / thoughts leads this conclusion?
@mixed commented on Mon Feb 20 2017
@vreality64
Thank you for your report. I am going to anwser it soon. ๐
@mixed commented on Tue Feb 21 2017
I think that This case is very important issue. Sometimes Component has not to fire event. So if trigger add option like boolean for event fire condition. I think differently It is duplicate feature(stop
method). So. It need more idea.
Version information should be exposed on documentation like below.
You should apply following rules.
https://github.com/naver/egjs-flicking/blob/master/src/index.js#L7
In the @egjs/flicking module, this @egjs/component
is imported as follows for the type definition.
import * as Component from "@egjs/component";
Currently, we use esModuleInterop
ts-compiler option in TypeScript 2.7.x version. So, the current version of typscript and import method are not appropriate.
How about supporting esModule like @egjs/axes?
class A extends Component{
}
class B extends Component{
}
new A();
new B();
Component.getInstanceAll();
// [instanceA, instanceB]
class A extends Component{
}
class B extends Component{
}
const a = new A();
new B();
Component.getInstanceAll();
// [instanceA, instanceB]
a.destory();
Component.getInstanceAll();
// [instanceB]
๊ฐ์ฒด๊ฐ 'next' ์์ฑ์ด๋ ๋ฉ์๋๋ฅผ ์ง์ํ์ง ์์ต๋๋ค.
(IE11)
Sometimes I have to listen all event in component.
class Test extends Component{
foo(){
this.trigger("foo",1);
}
bar(){
this.trigger("bar",2);
}
}
const test = new Test();
test.subscribe( data => {
console.log(data);
// {"name":"foo","data":1}
// {"name":"bar","data":2}
});
test.foo();
test.bar();
import Component from "./Component";
import ComponentEvent from "./ComponentEvent";
(Component as any).ComponentEvent = ComponentEvent;
export default Component;
import Component, * as modules from './index';
for (const name in modules) {
(Component as any)[name] = (modules as any)[name];
}
declare const module: any;
module.exports = Component;
export default Component;
export * from './index';
eventHandler can be set. also options propertys.
If you don't want to set property, make property as private.
ref.
http://www.2ality.com/2016/01/private-data-classes.html
homepage link in package.json is broken. it shows 404 error.
I think it have to be https://naver.github.io/egjs-component.
In 2.1.0 version
declare class Component {
// ...
on(eventName: string, handlerToAttach: (event: { [key: string]: any }) => any): Component;
// ...
}
I think this part should be changed as follows, I will ask you to review that part.
declare class Component {
// ...
on(eventName: string, handlerToAttach: (event: { [key: string]: any }) => any): this;
// ...
}
=> : Component
is to be : this
In 2.1.0-snapshot
, already has this part applied.
By the way, should not namespace
part remain the same?
declare namespace Component {
// ...
function on(eventName: string, handlerToAttach: (event: { [key: string]: any }) => any): this;
// ...
}
declare namespace Component {
// ...
function on(eventName: string, handlerToAttach: (event: { [key: string]: any }) => any): Component;
// ...
}
I will request a review of that part. Thanks.
trigger
is not handling all handlers when some handlers are removed while calling it.
Use multiple once
handlers and check whether they are all called by a single trigger().
When Component triggered event, It has not found component instance in event listener.
So, Below case is inconvenience.
class Test {
constructor(){
this.bind();
}
bind(){
const scroll = new ScrollComponent();
scroll.on("change",this.change.bind(this));
}
change(e){
// I can not found scroll instance.
}
}
class Test {
constructor(){
this.bind();
}
bind(){
const scroll = new ScrollComponent();
scroll.on("change",this.change.bind(this));
}
change({currentTarget}){
currentTarget; // It is scroll instance.
}
}
Almost Component design is affected by DOM interface. ref So. We decided to use currentTarget of DOM interface.
Returns the object whose event listener's callback is currently being invoked.
As-is:
To-be:
If eventType
is given inside event props, it will overwrite actual event name
const evt = new ComponentEvent("correct_name", {
eventType: "wrong_name"
});
evt.eventType // "wrong_name"
Change webpack to rollup
In package.json,
xml2js
should be included in "devDependency" instead of "dependency"
When I use many Components I tired to manage events.
there are suggestion that is event propagation.
It is not absolutely necessary, but I think it would be good to apply.
First, let me share my experience.
the experience was limited to UI development.
i think the UI has a hierarchical structure in general, whether it is physical or conceptual.
so when i applied this component to UI, events also had to be designed to follow the hierarchy.
when, i designed to
SearchPage (independent component)
ใด SearchInput
ใด Filter
ใด Category
the event structure was as follow,
SearchPage (independent) - onSubmit, onClear, onFilter, onSort,...
ใด SearchInput - onSubmit, onClear
ใด Filter - onFilter
ใด Sort - onSort
and implemented this as below.
class SearchPage extends eg.Component {
constructor() {
super();
this.context = {};
this.searchInput = new SearchInput(); // child component
this.filter = new Filter(); // child component
// intercepts event
this.searchInput.on('submit', (event) => {
// bubbling
event.pageContext = context;
this.trigger(event.eventType, event)
});
}
}
const searchPage = new SearchPage();
searchPage.on('submit', (event) => {
// todo - external module
})
but I thought it would be better if the component itself provided it systematically.
because the deeper the component, the more it will equal callback hell.
thanks for reading.
It is an ongoing document, but we need to check it.
https://w3ctag.github.io/design-principles
provide type definition.
Component not supported options since 2.1.0. So. Docs have to change description.
I think that Currently option
method is unnecessary feature. Because Almost Component update attribute directly option object.
Sometimes Component have to know changing value of options. I suggest event and method.
class SomeThing extends Component{
constructor(){
// setup prop
this.prop({
witdh : 100,
height : 200
});
}
}
const someThing = new SomeThing();
someThing.on("propChange", (data) => {
console.log(data);
/*
{
width : {
prevValue : 100,
newValue : 200
}
}
*/
});
someThing.prop("width",200);
This idea affected by DOM.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.