Ours and Populars
Componentization
Data Binding
Assets Management
Complex Applications
New syntax
Applications for specific business scenario
We want to make UI elements:
UI Component = View + Logic
(HTML / CSS) (Javascript)
UI Component:
Outside: behaves just like an html tag, can dispatch events and may have public methods
Inside: has a renderer which define the real html content, and may have nested components
JUIC ✔️
UI5 ✔️
React ✔️
Angular ✔️
Vue ✔️
<section class="main" v-show="todos.length">
<input class="toggle-all" type="checkbox" v-model="allDone">
<ul class="todo-list">
<li class="todo" v-for="todo in filteredTodos"
:class="{completed: todo.completed, editing: todo == editedTodo}">
<div class="view">
<input class="toggle" type="checkbox" v-model="todo.completed">
<label @dblclick="editTodo(todo)">{{todo.title}}</label>
<button class="destroy" @click="removeTodo(todo)"></button>
</div>
<input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo"
@blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)">
</li>
</ul>
</section>
Vue's template (renderer)
app.TodoItem = React.createClass({
// other method...
render: function () {
return (
<li className={classNames({
completed: this.props.todo.completed,
editing: this.props.editing
})}>
<div className="view">
<input className="toggle" type="checkbox" checked={this.props.todo.completed}
onChange={this.props.onToggle} />
<label onDoubleClick={this.handleEdit}>
{this.props.todo.title}
</label>
<button className="destroy" onClick={this.props.onDestroy} />
</div>
<input ref="editField" className="edit" value={this.state.editText}
onBlur={this.handleSubmit} onChange={this.handleChange}
onKeyDown={this.handleKeyDown}/>
</li>
);
}
});
React's render method (using JSX):
juic.set(new juic.Component(), {
// other methods
renderHtml : function(h) {
h.push('<input type="checkbox" ',
'id="', this.id, '" ',
(this._checked ? "checked " : " "),
(!this._enabled ? 'disabled="disabled" ' : ''), ' ');
if (this._name)
h.push('name="', this._name, '" ');
if (this._value)
h.push('value="', this._value, '" ');
if (this._isRequired) h.push(' aria-required="true" ');
if (this._ariaLabelledBy)
h.push(' aria-labelledby="', this._ariaLabelledBy, '" ');
h.push('onkeydown="' + this.fireCode('_onKeydownHandler') + '" ');
h.push('onclick="' + this.fireCode('_click') + '"/>');
if (typeof this._label != "undefined") {
h.push(' <label');
if (!this._ariaLabelledBy) {
h.push(' for="' + this.id + '"');
}
h.push('>',
'<span id="lbl', this.id, '" class="', !this._enabled ? 'readonly' : '', '">',
juic.escapeHTMLIfNeeded(this._label, this._encodeLabels), '</span>',
'</label>');
}
}
});
JUIC's render
What's the consequent challenge?
Data - View inconsistence:
Variable's change won't trigger UI change
Automatically keep data and view synchronized
<div id="app">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">Reverse Message</button>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
</script>
How the change event is triggered?
What's the scope of updating?
UI5 & React:
Use setter method
// Example in React
// ...
handleKeyDown: function (event) {
if (event.which === ESCAPE_KEY) {
// set the variable by calling this.setState
this.setState({editText: this.props.todo.title});
this.props.onCancel(event);
} else if (event.which === ENTER_KEY) {
this.handleSubmit(event);
}
}
// ...
Angular & Vue:
Change observer
// Example in Vue
// ...
methods: {
onEnlargeText: function (enlargeAmount) {
// Update the variable directly
this.postFontSize += enlargeAmount
}
}
// ...
Change observer is more elegant & intuitive
But setter method is better on performance & compatibility
Rerendering is the bottleneck of performance.
How to restrict the range of rerendering?
Angular & Vue:
Partial update by analyzing the data-UI binding
<h1 v-if="title">{{ title }}</h1>
<!--
This div won't be updated if only this.title is changed.
Because Vue can analyze the binding relationship and this
div is not related to title.
-->
<div v-if="content">{{ content }}</div>
UI5:
Full update without checking the binding relationship
React:
Full update on Virtual-DOM
DOM Diff algorithm to find the part that really need to be changed
Partial update on real DOM
JUIC ❌
UI5 ⚠️
React ✔️
Angular ✔️
Vue ✔️
What an application should have:
Libraries - focus on component level functionalities
React, Vue, JUIC
Frameworks - provide application level functionalities
UI5, Angular
Enhance libraries:
React: react-router / redux(mobx) / immutable
Vue: vue-router / vuex
JUIC: N/A
Look and Feel:
SAPUI5: strictly following Fiori Design
React / Vue / Angular: Various design pattern available (not including Fiori)
JUIC ❌
UI5 ✔️
React ⚠️
Angular ✔️
Vue ⚠️
Consumes some particular API
Satisfies very detailed requirements
Can build large application with few code (ideally)
Config UI:
A form renderer developed by SF
Customize layout in WYSIWYG
Fiori Elements:
Form renderer and data visualizer developed by SAP
Annotate data with semantic terms
Alternatives in industry:
N/A
Why?
More complex
Less adaptable
Dependency management
Code minifying
Language Compiler
SMRF
Webpack
UI5?
Runtime dependency loading - may have severe performance problem.
Can be built by Maven, but build process is not very simple.
More simple code
More strict type system
Static syntax validation
JSX
ES7
TypeScript
Kotlin
SF status:
Still using ES5
JUIC + SMRF | UI5 | React + Redux + Webpack | Angular + TypeScript + Webpack |
|
Load Speed | 😳 | 😡 | 😄 | 😄 |
Render Speed | 😡 | 😡 | 😄 | 😄 |
Flexibility | 😳 | 😡 | 😄 | 😄 |
Business scenarios support | 😳 | 😄 | 😡 | 😡 |
Maintainable | 😡 | 😳 | 😄 | 😄 |
Community support | 😡 | 😳 | 😄 | 😄 |
Built-in components | 😳 | 😄 | 😡 | 😡 |
Componentization
Modulization
Strict data management (data type, immutable, ...)
Build the code
Convention over configuration
...
Separate frontend from backend
Performance (load & run)
Heavy coupling in legacy code
Security in JUIC
Lack of docs (API doc & PRD doc)
...
Be open to new technologies
Trust on open source community
Make flexible & improvable software