motivation
-
aurelia
のチュートリアルを実装してみる - 同じものを他のフレームワークで実装してみる
- なんとなくそれぞれの雰囲気を感じ取り、比較した気分に浸る
* 雰囲気を掴むだけなので深くはみない。実装も割と雑。
frameworks
* 他のフレームワークも試してみたら適宜追加していく。
todo app
なんでこの手のチュートリアルはTODOアプリなんだろうと思いつつ。
(フォーム・リスト・アイテムとコンポーネントの分割、各種アクションと基本的なものが学べるイイ教材?)
todo class
todo.js
export default class Todo {
constructor(description) {
this.description = description;
this.done = false;
}
}
タスクの概要と、進捗を要素として持つ。
case aurelia
app.html
<template>
<h1>${heading}</h1>
<form submit.trigger="addTodo()">
<input type="text" value.bind="todoDescription">
<button type="submit">Add Todo</button>
</form>
<ul>
<li repeat.for="todo of todos">
<input type="checkbox" checked.bind="todo.done">
<span css="text-decoration: ${todo.done ? 'line-through' : 'none'}">
${todo.description}
</span>
<button click.trigger="removeTodo(todo)">Remove</button>
</li>
</ul>
</template>
app.js
import Todo from './Todo';
export class App {
constructor() {
this.heading = 'Todos';
this.todos = [];
this.todoDescription = '';
}
addTodo() {
if (this.todoDescription) {
this.todos.push(new Todo(this.todoDescription));
this.todoDescription = '';
}
}
removeTodo(todo) {
let index = this.todos.indexOf(todo);
if (index !== -1) {
this.todos.splice(index, 1);
}
}
}
少ないコードでスッキリ書ける。
case vue
App.vue
<template>
<div>
<h1>{{heading}}</h1>
<form v-on:submit.prevent="addTodo()">
<input type="text" v-model="todoDescription">
<button type="submit">Add Todo</button>
</form>
<ul>
<li v-for="todo of todos">
<input type="checkbox" v-model="todo.done">
<span v-bind:class="[todo.done ? 'done' : '']">
{{todo.description}}
</span>
<button v-on:click="removeTodo(todo)">Remove</button>
</li>
</ul>
</div>
</template>
<script>
import Todo from './todo';
export default {
name: 'App',
data() {
return {
heading: 'Todos',
todoDescription: '',
todos: [],
};
},
methods: {
addTodo() {
if (this.todoDescription) {
this.todos.push(new Todo(this.todoDescription));
this.todoDescription = '';
}
},
removeTodo(todo) {
const index = this.todos.indexOf(todo);
if (index !== -1) {
this.todos.splice(index, 1);
}
},
},
};
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
Vue.js のシンタックスはちょっと苦手。
case react
App.js
import React, { Component } from 'react';
import update from 'immutability-helper';
import Todo from './todo';
class App extends Component {
constructor() {
super();
this.state = {
heading: 'Todos',
todos: [],
todoDescription: ''
}
}
onInput(e) {
this.setState({ todoDescription: e.currentTarget.value });
}
addTodo(e) {
e.preventDefault();
if (this.state.todoDescription) {
this.setState({
todos: update(this.state.todos, {$push: [new Todo(this.state.todoDescription)]}),
todoDescription: ''
});
}
}
removeTodo(todo) {
const index = this.state.todos.indexOf(todo);
if (index !== -1) {
const prevTodos = this.state.todos;
const nextTodos = update(prevTodos, {$splice: [[index, 1]]});
this.setState({
todos: nextTodos
});
}
}
render() {
const todos = this.state.todos.map((todo, i) => (
<li>
<input type="checkbox" checked={todo.done}
onChange={
() => {
this.setState({
todos: update(this.state.todos, {[i]: {done: {$set: !todo.done}}})
});
}
}/>
<span style={todo.done ? { textDecoration: 'line-through' } : {} }>
{todo.description}
</span>
<button onClick={() => this.removeTodo(todo)}>Remove</button>
</li>
));
return (
<div>
<h1>{this.state.heading}</h1>
<form onSubmit={e => this.addTodo(e)}>
<input type="text" onChange={e => this.onInput(e)} value={this.state.todoDescription}/>
<button type="submit">Add Todo</button>
</form>
<ul>
{todos}
</ul>
</div>
);
}
}
export default App;
コード量は多いけど、スクリプトだけで書けるのは良い。
summary
見出しに英語を使うと、ちょっと出来てる感が醸し出せる。