Front-end Hyperpolyglot

Inspired by hyperpolyglot.org, a comparison of similar features in popular JavaScript frameworks.

Any contributors who are more familiar with these frameworks would be massively appreciated. The source is on GitHub.

React Angular 2 Angular 1 Ember Polymer Vue Riot
Version used
15.0.2
2.0.0-beta.17
1.5.5
2.5.1
1.4.0
1.0.24
2.4.1
Language used
ES6
TypeScript
ES5
ES6
ES6
ES6
ES6
Templating logic
React Angular 2 Angular 1 Ember Polymer Vue Riot
Text interpolation
{ message }
{{ message }}
{{ message }}
{{ message }}
{{ message }}
{{ message }}
{ message }
Transform interpolation
{ filter(message) }
{{ message | filter }}
{{ message | filter }}
{{filter message }}
{{ filter(message) }}
{{ message | filter }}
{ filter(message) }
Transform with arguments
{ filter(message, 'arg1', arg2) }
{{ message | filter:'arg1':arg2 }}
{{ message | filter:'arg1':arg2 }}
{{filter message 'arg1' arg2 }}
{{ filter(message, 'arg1', arg2) }}
{{ message | filter 'arg1' arg2 }}
{ filter(message, 'arg1', arg2) }
Bind text content
<div textContent={message}>
<div [textContent]="message">
<div ng-bind="message">
<div textContent="{{ message }}">
<div text-content="{{ message }}">
<div v-text="message">
<div textContent={message}>
Bind href
<a href={ url }></a>
<a [href]="url"></a>
<a ng-href="{{ url }}"></a>
<a href="{{url}}"></a>
<a href$="{{ url }}"></a>
<a v-bind:href="url"></a>
<a href={ url }></a>
Dangerous raw HTML output
<div 
  dangerouslySetInnerHTML={{
    __html: raw_html
  }} />
<div [innerHTML]="raw_html">
<div ng-bind-html="raw_html">
{{{ raw_html }}}
<div inner-h-t-m-l="{{ raw_html }}">
{{{ raw_html }}}
see notes
Bind attribute value
<div id={'item-' + id}>
<div id="item-{{ id }}">
<div id="item-{{ id }}">
<div id="item-{{ id }}">
<div id$="item-{{ id }}">
<div id="item-{{ id }}">
<div id={'item-' + id}>
DOM add/remove
{shouldShow && <div />}
<div *ngIf="shouldShow">
<div ng-if='shouldShow'>
{{#if shouldShow}}
  <div></div>
{{/if}}
<template
  is='dom-if'
  if='{{shouldShow}}'>
</template>
<div v-if='shouldShow'>
<div if={ shouldShow }>
Repeat
items.map(item =>
  <div key={item.id} />
)
<div *ngFor="let item of items">
<div ng-repeat="item in items">
{{#each items as |item|}}
  <div></div>
{{/each}}
<template
  is='dom-repeat'
  items='{{items}}'>
</template>
<div v-for="item in items">
<div each={ item in items }>
Bind event handler
<button onClick={clicked}>
<button (click)="clicked()">
<button ng-click="clicked()">
<button {{action 'clicked'}}>
<button on-click="clicked">
<button v-on:click="clicked">
<button onclick={clicked}>
Components
React Angular 2 Angular 1 Ember Polymer Vue Riot
Define component ES6
class Polyglot extends React.Component
@Component({})class Polyglot {}
module.component('polyglot', {})
Ember.Component.extend({})
class Polyglot extends HTMLElement { 
  beforeRegister() {
    this.is = 'poly-glot';
  }
}
class Polyglot extends Vue
<polyglot></polyglot>
Define component ES5
React.createClass({})
ng.core.Component({}).Class({})
module.component('polyglot', {})
Ember.Component.extend({})
Polymer({is: 'poly-glot'})
Vue.extend({})
<polyglot></polyglot>
Component communication
React Angular 2 Angular 1 Ember Polymer Vue Riot
One-way data binding
<Child foo={bar} />
<Child [foo]="bar" />
<Child foo="{{ bar }}" />
{{Child foo=(readonly bar) }}
<div foo="[[ bar ]]">
<child :foo='bar' />
<child foo={bar} />
String literal prop
<Child foo='bar' />
<Child foo='bar' />
<Child foo='bar' />
{{Child foo='bar' }}
<div foo="bar">
<child foo='bar' />
<child foo='bar' />
Two-way binding (native) not supported
<input [(ngModel)]="foo" />
<input ng-model="foo" />
<input 
  value={{foo}}
  onkeyup={{
    action (mut foo)
      value='target.value'
  }}
  />
<input value="{{foo::input}}">
<input v-model="foo" />
not supported
Two-way binding (components) not supported
<Child [(foo)]="bar" />
<Child foo="bar" />
<Child foo=bar>
<poly-glot foo='{{ bar }}'></poly-glot>
<!-- and set notify: true -->
<child :foo.sync="bar"></child>
not supported
One-time binding not supported not supported
<Child foo="::bar" />
not supported not supported
<child foo.once="bar" />
not supported
Component internal state
React Angular 2 Angular 1 Ember Polymer Vue Riot
Set initial state
getIntitialState = () => { foo: 1 }
constructor() {
  this.foo = 1
}
controller: function() {
  this.foo = 1
}
{
  foo: 1
}
properties: {
  foo: { value: 1 }
}
data: {
  foo: 1
}
this.foo = 1
Set state
this.setState({ foo: 2 })
this.foo = 2
this.foo = 2
this.set('foo', 2)
this.foo = 2
this.foo = 2
this.foo = 2
Property validation
React Angular 2 Angular 1 Ember Polymer Vue Riot
Prop validation key
{propTypes: {}}
as types on @Input properties (below) (no prop types)
// requires ember-prop-types
{propTypes: {}}
{properties: {}}
{props: {}}
(no prop types)
Prop validate Number
{myNum: React.PropTypes.number}
@Input() myNum: number;
(no prop types)
{myNum: PropTypes.number}
{myNum: Number}
{myNum: Number}
(no prop types)
Prop validate String
{myStr: React.PropTypes.string}
@Input() myStr: string;
(no prop types)
{myStr: PropTypes.string}
{myStr: String}
{myStr: String}
(no prop types)
Prop validate Array
{myArr: React.PropTypes.array}
@Input() myArr: Array;
(no prop types)
{myArr: PropTypes.array}
{myArr: Array}
{myArr: Array}
(no prop types)
Prop validate Boolean
{myBool: React.PropTypes.bool}
@Input() myBool: boolean;
(no prop types)
{myBool: PropTypes.bool}
{myBool: Boolean}
{myBool: Boolean}
(no prop types)
Prop validate Function
{myFunc: React.PropTypes.func}
@Input() myFunc: Function;
(no prop types)
{myFunc: PropTypes.func}
not supported not supported (no prop types)
Prop validate Object
{myObj: React.PropTypes.object}
@Input() myObj: Object;
(no prop types)
{myObj: PropTypes.object}
{myObj: Object}
{myObj: Object}
(no prop types)
Prop validate union
{myVar: React.PropTypes.oneOfType([
  React.PropTypes.string, 
  React.PropTypes.number
])}
@Input() myVar: string | number;
(no prop types)
{myVar: PropTypes.oneOfType([
  PropTypes.string, 
  PropTypes.number
])}
not supported
{myVar: [String, Number]}
(no prop types)
Component lifecycle methods
React Angular 2 Angular 1 Ember Polymer Vue Riot
Initialized
componentWillMount
ngOnInit
$onInit
init
created
created
before-mount
DOM Ready
componentDidMount
ngAfterContentInit
$postLink
didInsertElement
ready
ready
mount
On prop change
willReceiveProps
ngOnChanges
$onChanges
didReceiveAttrs
properties: {
  foo: {observer: '_fooChanged'}  
}
none
update
Component updated
componentDidUpdate
none none
didUpdateAttrs
none none
updated
Before destroy
componentWillUnmount
none none
willDestroyElement
detached
beforeDestroy
before-unmount
After destroy none
ngOnDestroy
$onDestroy
didDestroyElement
none none
unmount

Templating logic

Text interpolation

Transform interpolation

React, Riot and Polymer don’t have the concept of ‘filters’ or ‘pipes’, but you can use a simple function to acheive the same result.

Transform with arguments

Bind text content

A way of binding the text content of an element via an attribute.

Bind href

Dangerous raw HTML output

Please don’t use these in your programs. Filtering raw HTML on the server or in the browser will not protect you 100% against XSS. For a deeper look at the subject, please refer to the Google Browser Security Handbook (PDF download) and the book The Tangled Web: A Guide to Securing Modern Web Applications.

Bind attribute value

DOM add/remove

Repeat

Bind event handler

Components

Define component ES6

Define component ES5

Component communication

One-way data binding

  • Polymer: The child component must also be set up to treat the property as read-only. Learn more about data binding in Polymer.

Two-way binding (native)

Two-way binding (components)

One-time binding

When a property is passed down and never updated again.

Component internal state

Property validation

Prop validation key

The key in the component configuration object to define the expected type of a passed prop.

class Polyglot extends React.Component {
  propTypes = {
    myNumber: React.propTypes.number
  }
}

Prop validate union

Component lifecycle methods

Initialized

DOM Ready

On prop change

Component updated

Before destroy

After destroy