Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
444 views
in Technique[技术] by (71.8m points)

javascript - Refactoring Angular components from many inputs/outputs to a single config object

My components often start out by having multiple @Input and @Output properties. As I add properties, it seems cleaner to switch to a single config object as input.

For example, here's a component with multiple inputs and outputs:

export class UsingEventEmitter implements OnInit {
    @Input() prop1: number;
    @Output() prop1Change = new EventEmitter<number>();
    @Input() prop2: number;
    @Output() prop2Change = new EventEmitter<number>();

    ngOnInit() {
        // Simulate something that changes prop1
        setTimeout(() => this.prop1Change.emit(this.prop1 + 1));
    }
}

And its usage:

export class AppComponent {
    prop1 = 1;

    onProp1Changed = () => {
        // prop1 has already been reassigned by using the [(prop1)]='prop1' syntax
    }

    prop2 = 2;

    onProp2Changed = () => {
        // prop2 has already been reassigned by using the [(prop2)]='prop2' syntax
    }
}

Template:

<using-event-emitter 
    [(prop1)]='prop1'
    (prop1Change)='onProp1Changed()'
    [(prop2)]='prop2'
    (prop2Change)='onProp2Changed()'>
</using-event-emitter>

As the number of properties grows, it seems that switching to a single configuration object might be cleaner. For example, here's a component that takes a single config object:

export class UsingConfig implements OnInit {
    @Input() config;

    ngOnInit() {
        // Simulate something that changes prop1
        setTimeout(() => this.config.onProp1Changed(this.config.prop1 + 1));
    }
}

And its usage:

export class AppComponent {
    config = {
        prop1: 1,

        onProp1Changed(val: number) {
            this.prop1 = val;
        },

        prop2: 2,

        onProp2Changed(val: number) {
            this.prop2 = val;
        }
    };
}

Template:

<using-config [config]='config'></using-config>

Now I can just pass the config object reference through multiple layers of nested components. The component using the config would invoke callbacks like config.onProp1Changed(...), which causes the config object to do the reassignment of the new value. So it seems we still have one-way data flow. Plus adding and removing properties doesn't require changes in intermediate layers.

Are there any downsides to having a single config object as an input to a component, instead of having multiple input and outputs? Will avoiding @Output and EventEmitter like this cause any issues that might catch up to me later?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

personally if I see I need more than 4 inputs+outputs, I will check my approach to create my component again , maybe it should be more than one component and I'm doing something wrong. Anyway even if I need that much of input&outputs I won't make it in one config, for this reasons :

1- It's harder to know what should be inside inputs and outputs,like this: (consider a component with to html inputs element and labels)

imagine if you got only 3 of this component and you should comeback to work on this project after 1 or 2 month, or someone else gonna collaborate with you or use your code!. it's really hard to understand your code.

2- lack of performance. it's way cheaper for angular to watch a single variable rather than watching an array or object. beside consider the example i gave you at first one, why you should force to keep track of labels in which may never change alongside with values which always are changing.

3- harder to track variables and debug. angular itself comes with confusing errors which is hard to debug, why should I make it harder. tracking and fixing any wrong input or output one by one is easier for me rather than doing it in one config variable which bunch of data.

personally I prefer to break my components to as small as possible and test each one. then make bigger components out of small ones rather than having just a big component.

Update : I use this method for once input and no change data ( like label )

@Component({
selector: 'icon-component',
templateUrl: './icon.component.html',
styleUrls: ['./icon.component.scss'],
inputs: ['name', 'color']
});

export class IconComponent implements OnInit {
 name: any;
 color: any;

 ngOnInit() {
 }
}

Html:

<icon-component name="fa fa-trash " color="white"></icon-component>

with this method angular wont track any changes inside your component or outside. but with @input method if your variable changes in parent component, you will get change inside component too.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...