Li Yafei
A senior Ruby on Rails developer
For 深JS
2018.08.28 by WinDy
连续创业者, 全栈开发工程师, 专注于 web app & native app.
作品: cywin(创业赢), 8020(八十二十), 角落等
Github: @windy
A very simple & powerful native app development architecture
Inspired by spreadsheets
An example from spreadsheet
See actual code for mobx
// a very simple mobx example
import { observable, computed, autorun } from 'mobx'
class A {
@observable a = "a";
@observable b = "b";
@observable c = "c";
@computed get sum() {
return this.a+this.b;
}
}
let classA = new A();
// output "ab"
autorun( ()=> {
console.log(classA.sum);
})
// output "aab"
classA.a = "aa";
// nothing output
classA.c = "cc";
Apply `spreadsheet` into Front-end development
High Performance
// counter_store.js
import {observable} from 'mobx'
import api from './api'
class CounterStore {
@observable counter = 0;
@observable remoteCounter = 0;
constructor() {
}
increment() {
this.counter++;
}
decrement() {
this.counter--;
}
incrementAsync() {
setTimeout(() => {
this.counter++;
}, 500);
}
getFromRemote() {
api.get('/hello')
.then( (r)=> {
if(r.ok)
this.remoteCounter = r.data;
else
this.remoteCounter = 'error';
});
}
}
const counterStore = new CounterStore;
export default counterStore;
// counter_screen.js
import React, { Component, PropTypes } from 'react'
import { Text, View, StyleSheet } from 'react-native'
import Button from 'react-native-button'
import { observer } from 'mobx-react/native'
import ApplicationStyles from '../styles'
import Icon from 'react-native-vector-icons/FontAwesome'
@observer
export default class CounterScreen extends Component {
render() {
return (
<View>
<Text>Clicked: <Text>{this.props.counterStore.counter}</Text> times</Text>
<Button style={ApplicationStyles.button} onPress={() => this.props.counterStore.increment()}>
| +1 |
</Button>
<Button style={ApplicationStyles.button} onPress={() => this.props.counterStore.incrementAsync()}>
| +1 async |
</Button>
</View>
)
}
}
An actual Todolist APP with react-native-mobx
UI program = state + View
`state` determine `View`
`View` trigger `action` to update `state` to update `View`
// a todolist app code snippet by jQuery only
// from: https://github.com/tastejs/todomvc/blob/gh-pages/examples/jquery/js/app.js
var App = {
init: function () {
this.todos = util.store('todos-jquery');
this.todoTemplate = Handlebars.compile($('#todo-template').html());
this.footerTemplate = Handlebars.compile($('#footer-template').html());
this.bindEvents();
},
bindEvents: function () {
$('#new-todo').on('keyup', this.create.bind(this));
$('#toggle-all').on('change', this.toggleAll.bind(this));
$('#footer').on('click', '#clear-completed', this.destroyCompleted.bind(this));
$('#todo-list')
.on('change', '.toggle', this.toggle.bind(this))
.on('dblclick', 'label', this.edit.bind(this))
.on('keyup', '.edit', this.editKeyup.bind(this))
.on('focusout', '.edit', this.update.bind(this))
.on('click', '.destroy', this.destroy.bind(this));
},
render: function () {
var todos = this.getFilteredTodos();
$('#todo-list').html(this.todoTemplate(todos));
$('#main').toggle(todos.length > 0);
$('#toggle-all').prop('checked', this.getActiveTodos().length === 0);
this.renderFooter();
$('#new-todo').focus();
util.store('todos-jquery', this.todos);
}
}
export default class TodoStore {
@observable todos = [];
@computed get activeTodoCount() {
return this.todos.reduce(
(sum, todo) => sum + (todo.completed ? 0 : 1),
0
)
}
@computed get completedCount() {
return this.todos.length - this.activeTodoCount;
}
addTodo (title) {
this.todos.push(new TodoModel(this, Utils.uuid(), title, false));
}
toggleAll (checked) {
this.todos.forEach(
todo => todo.completed = checked
);
}
}
X
High Performance
3 ~ 15 times faster usually
vs
mobx
redux
mobx VS Vue
mobx VS WEEX
Star and fork it!!!
八十二十
AD
github: @windy
By Li Yafei