I am working in web application project which is made in Polymer 2.0, All Custom elements extends some Mixins. Some of those Mixins just provide utility functions to custom elements just like Date Time Utility functions or any Math related functions. My question is whether to use mixins & extends them to custom elements or just wrap them in plain java-script file and load that java-script file on index.html or entry point of application and use as global scope just like we use lodashjs or underscore.js.
The problem i find with Mixins is it always get applied to prototype chain of each custom element class object, So i end up those same utility methods with each custom element of my application.
Please suggest me best approach for Utilities in Polymer related apps.
That is a rather tough question to answer properly... as the real answer is just "both are valid solutions - it depends on your use case". Which I guess is not helping too much. So let's give you some context.
For real utilities, it is probably best to put them in a class as a static function.
class MathHelper {
static addOne(value) {
return value + 1;
}
}
class ElOne extends HTMLElement {
connectedCallback() {
this.innerHTML = `5 + 1 = ${MathHelper.addOne(5)}`;
}
}
customElements.define('el-one', ElOne);
<el-one></el-one>
Mixins, on the other hand, can serve a similar need but should be more "connected" to the Element they are used on.
(Sorry for the terrible example but from the top of my head I could not come up with something better)
const MathMixin = superclass => class extends superclass {
addOneTo(prop) {
this[prop] += 1;
}
}
class ElTwo extends MathMixin(HTMLElement) {
constructor() {
super();
this.number = 5;
}
connectedCallback() {
this.addOneTo('number');
this.innerHTML = `5 + 1 = ${this.number}`;
}
}
customElements.define('el-two', ElTwo);
<el-two></el-two>
Conclusion:
Class:
if possible use it
maybe even use static functions
it's easier to test and to maintain
Mixin:
if you need to enhance another class e.g. to allow
myElemenet.changeLanguage('de'), ...
if you need any other state of the class
I hope this clears it up at least a bit. If you have more concrete examples what needs to be implemented we could propose a recommended way of implementation.
Related
When implementing a method used only within a specific component class, it can be declared as a static method and an instance method, and I wonder the difference between the two.
Declaring methods of classes used across applications, such as the Util class, static is common, but I wonder if it is the right way to declare static just because it does not refer to this within a particular component class.
According to my research, the static method of class is disadvantageous in terms of memory because the memory remains intact even if the component's life cycle ends. If so, isn't it more advantageous to use it as an instance method even if it's only used within a specific class and not referenced to this?
class MyComponent {
// ex1) instance method
private isValidInput(text) {
return !!text.trim()
}
// ex1) static method
private static isValidInput(text) {
return !!text.trim()
}
}
When implementing component classes using Angular, I wondered if I would implement util functions that are only used in specific component classes as static or instance methods.
I was looking for a way to bind react class methods to this in the constructor all at once, because I got tired of typing this._anotherFunction = this._anotherFunction.bind(this) 10 times for each component.
I haven't seen anyone else posting solutions for this and thought it would be useful to share my answer.
Interested to see if anyone else has similar implementations, or if there are any issues with the way I implemented.
Given the following React class functions:
_showModal() {}
_hideModal() {}
// etc.
In the constructor I added:
// bind all of the class's methods to the class
bindClassMethods.bind(this)([
'_showModal',
'_hideModal',
// etc.
]);
Here's the re-usable util function I wrote to pull this off:
export function bindClassMethods(classMethods = []) {
if (!_.isArray(classMethods)) {
console.error(`Need to pass an array to bindClassMethods().`);
return;
}
classMethods.map(fnc => {
if (!this[fnc]) {
console.error(
`Warning: func ${fnc} is not defined! It probably has been removed from this class' methods.`
);
} else {
this[fnc] = this[fnc].bind(this);
}
});
}
I found the console logs useful for reminding myself when I forgot to remove or update a function binding.
Revisiting this issue - the previous suggestion to use arrow functions as class properties have some drawbacks, including performance implications. (Albeit an arguably negligible performance implication, but one worth noting).
New Proposed Solution:
create a new class that extends Component, e.g. ComponentAutoBind
any sub-component that extends ComponentAutoBind will automatically have its own methods bound to the class instance
exclude React lifecycle methods from binding
See this gist for proposed solution
Working codepen example
I realize that extending Component may not be best practice but my implementation is only affecting the constructor - all other Component class properties are untouched.
Here are some links for the unconvinced:
https://medium.com/#forsakenharmony/you-should-maybe-mention-that-the-arrow-function-in-the-class-body-is-just-syntactic-sugar-c7bfb3383bef
https://blog.usejournal.com/arrow-functions-are-disrupting-react-components-63662d35f97b
https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36 - only discusses Render method but same principle applies to class properties
I want a custom element I'm defining to have the Polymer.IronScrollTargetBehavior in Polymer 2.
In Polymer 1, this can be done by adding it to the behaviors array:
Polymer({
is: 'my-element',
behaviors: [Polymer.IronScrollTargetBehavior]
});
In the Polymer 2 upgrade guide, it says that you should:
Implement "behaviors" as mixins that return class expressions.
In the linked article, it explains how you can use the following syntax for mixins:
let MyMixin = (superclass) => class extends superclass {
foo() {
console.log('foo from MyMixin');
}
};
class MyClass extends MyMixin(MyBaseClass) {
/* ... */
}
I mostly get what's going on here (although I find the mixin syntax difficult to wrap my mind around), and I can get sample code to work.
What I haven't been able to do is apply this concept to Polymer.IronScrollTargetBehavior, and create a mixin for it. Since that behavior is already defined as an object, I don't know where to fit it in.
So, how do I implement the proper mixin in this scenario, or if I'm on the wrong path, how to I apply one of the defined Polymer behaviors to my custom element in Polymer 2?
You can use the Polymer 2 hybrid behaviours as mixins by extending
Polymer.mixinBehaviors(behaviors, klass) where
- behaviors is the Behavior object or array of behaviors
- klass is the Element class.
i.e.
<dom-module id="element-name">
<template><!-- ... --></template>
<script>
class MyElement extends Polymer.mixinBehaviors([MyBehavior, MyBehavior2], Polymer.Element) {
static get is() { return 'element-name' }
/* ... */
}
customElements.define('element-name', MyElement);
</script>
</dom-module>
For more detailed information search the Polymer source code for mixinBehaviors method: polymer/lib/legacy/class.html
worth reading: https://www.polymer-project.org/2.0/docs/upgrade#mixins
Polymer 2.0 has a compatibility layer that still supports the old Polymer function syntax. Most of the 2.0 preview elements, if not all, still retain the old syntax. The breaking changes are mostly in the dom-module markup.
If you are composing new elements, it is recommended you switch over to the class based syntax. If however you are porting 1.0 elements to 2.0 and those elements rely on Polymer behaviors, I don't think you much choice at this juncture but to retain the old syntax.
In the class-based syntax you can fluently simulate Element multiple inheritance of class mixins with something like this
let Mixin = (superclass) => new MixinBuilder(superclass);
class MixinBuilder {
constructor(superclass) {
this.superclass = superclass;
}
with(...mixins) {
return mixins.reduce((c, mixin) => mixin(c), this.superclass);
}
}
const MyMixin = subclass => class extends subclass {
_test(){
}
}
const MyMixinTwo = subclass => class extends subclass {
_testTwo(){
}
}
class MyElement extends Mixin(Polymer.Element).with(MyMixin,MyMixin2) {
static get is() { return 'my-element' }
}
You can separate the MixinBuilder into its own file and then reference it as an Html Import dependency whenever composing elements that use mixins.
I'm running into an "issue" where I don't know which one is the best option.
Say I have the following class
export default class A {
constructor(){
this.testMethod = function testMethod(){
console.log('a')
}
}
static testMethod2 = function() {
console.log('B')
}
}
now I'm extending this class
class C extends A {
fetch() {
this.testMethod()
A.testMethod2()
}
}
Defining it as a static method feels weird to use when extending it, I would assume the fact that I'm extending a class would allow me to access all of its own methods (ES5 prototype style)
I know both ways are correct but what's the best way to do this in ES6/React ? What are some caveats of both ways or performance issues ?
I'm currently using the constructor because it feels like the right/intended way of doing it but I can't "justify" one over the other.
All this came from applying the airbnb eslint to my code base (http://eslint.org/docs/rules/class-methods-use-this)
I would assume the fact that I'm extending a class would allow me to access all of its own methods
You actually can do that. Just call C.testMethod2() instead of A.testMethod2() (or even use this.constructor.testMethod2()).
Defining functions that have nothing to do with a particular instance on the prototype or even inside the constructor is a bad practise, don't do that.
I created my own es6 mixin (and it works, yea!). However, it seems that I do not fully understand what I have created here (following example here):
export var EventEmitterMixin = (daSuperClass) => class extends daSuperClass {
}
How do I read this line of code? It seems that daSuperClass is just cruft (as I can evidently change it to anything I like)? Why is it in there two times?
When defining a function you need to give a name to your parameters so that you can reference them. It may be easier to see what's going on if it is rewritten without the fat-arrow syntax:
export var EventEmitterMixin = function(daSuperClass) {
return class extends daSuperClass {
[...]
}
}
So the argument your mixin takes is going to form the prototype for the new class you are creating. You mix in your extra functionality by 'extending' from the base class you provide.