JavaScriptフレームワーク、Meteorのチュートリアルを試してみる その1
Meteorを試して使ってみる
Meteorとは
2012年に登場したNode.jsをベースとしたフルスタックフレームワークです。 Webアプリケーションが爆速で開発できるとのことでチュートリアル的なことを今回やってみたいと思います。
今回は公式サイトのチュートリアル「simple-todos with React」をやってみたいと思います。
準備
今回の環境は以下の通りです。
- CentOS 6.7
- Node.js v6.9.4
Meteorのインストール
バージョンによってインストール方法が異なるようなので下手に記事を漁るより 公式サイト - Meteorに従って進めていきましょう。 といっても簡単で以下のコマンドをターミナル上で実行します
curl https://install.meteor.com/ | sh
プロジェクトの作成
インストールが終わったら、次はプロジェクトの作成を行います。
meteor create simple-todos
一度、動かしてみる
ここまできたらとりあえず動かしてみましょう
cd simple-todos // meteorコマンドでサーバーを起動 meteor
サーバが起動したら確認します。 http://localhost:3000/で確認できるかと思います。
こんな感じの画面が出れば成功です。 ボタンを押すとカウントしてくれるカウンターアプリが作られています。
React用の準備
React.jsを用いて書いていくのでそちらの準備を行っていきます。 reactとreact-domをインストールします
meteor npm install --save react react-dom
Todoアプリを作成していく
準備が整ったのでTodoアプリを書いていきましょう まずは、client/main.htmlを書き換えていきます。
<head> <title>Todo List</title> </head> <body> <div id="render-target"></div> </body>
これだけでOKです。
次にclient/main.jsを書き換えます。 一度、client/main.jsを削除し、再度client/main.jsを作成しましょう。 中身のコードは以下の通りです。
import React from 'react'; import { Meteor } from 'meteor/meteor'; import { render } from 'react-dom'; import App from '../imports/ui/App.jsx'; Meteor.startup(() => { render(<App />, document.getElementById('render-target')); });
コンポーネントを作成
Reactを学んでいない方は少しわからないかもしれないですが、コンポーネントというものを作成していきます。簡単にいうと部品ごとにコードを分割し、コンポーネントにすることで可読性や生産性の向上を図ります。
mkdir imports mkdir imports/ui
まずは大元であるAppコンポーネントを作成していきます。
imports/ui/App.jsxです。
import React, { Component } from 'react'; import Task from './Task.jsx'; // App component - represents the whole app export default class App extends Component { getTasks() { return [ { _id: 1, text: 'This is task 1' }, { _id: 2, text: 'This is task 2' }, { _id: 3, text: 'This is task 3' }, ]; } renderTasks() { return this.getTasks().map((task) => ( <Task key={task._id} task={task} /> )); } render() { return ( <div className="container"> <header> <h1>Todo List</h1> </header> <ul> {this.renderTasks()} </ul> </div> ); } }
次は、タスク1つ1つに関するコンポーネントが必要なので作っていきます imports/ui/Task.jsxです
import React, { Component, PropTypes } from 'react'; // Task component - represents a single todo item export default class Task extends Component { render() { return ( <li>{this.props.task.text}</li> ); } } Task.propTypes = { // This component gets the task to display through a React prop. // We can use propTypes to indicate it is required task: PropTypes.object.isRequired, };
CSSも追加する
ここまででも動きますがせっかくなのでCSSでスタイリングしていきたいと思います。 client/main.cssに記述していきます。
/* CSS declarations go here */ body { font-family: sans-serif; background-color: #315481; background-image: linear-gradient(to bottom, #315481, #918e82 100%); background-attachment: fixed; position: absolute; top: 0; bottom: 0; left: 0; right: 0; padding: 0; margin: 0; font-size: 14px; } .container { max-width: 600px; margin: 0 auto; min-height: 100%; background: white; } header { background: #d2edf4; background-image: linear-gradient(to bottom, #d0edf5, #e1e5f0 100%); padding: 20px 15px 15px 15px; position: relative; } #login-buttons { display: block; } h1 { font-size: 1.5em; margin: 0; margin-bottom: 10px; display: inline-block; margin-right: 1em; } form { margin-top: 10px; margin-bottom: -10px; position: relative; } .new-task input { box-sizing: border-box; padding: 10px 0; background: transparent; border: none; width: 100%; padding-right: 80px; font-size: 1em; } .new-task input:focus{ outline: 0; } ul { margin: 0; padding: 0; background: white; } .delete { float: right; font-weight: bold; background: none; font-size: 1em; border: none; position: relative; } li { position: relative; list-style: none; padding: 15px; border-bottom: #eee solid 1px; } li .text { margin-left: 10px; } li.checked { color: #888; } li.checked .text { text-decoration: line-through; } li.private { background: #eee; border-color: #ddd; } header .hide-completed { float: right; } .toggle-private { margin-left: 5px; } @media (max-width: 600px) { li { padding: 12px 15px; } .search { width: 150px; clear: both; } .new-task input { padding-bottom: 5px; } }
コレクションを使う
Todoリストを作成しても、保存できなければ意味がありません。なのでコレクションを使用し、保存できるようにしましょう。 ディレクトリをつくってやります
mkdir imports/api
imports/apiの中に、tasks.jsファイルを作成します。
import { Mongo } from 'meteor/mongo'; export const Tasks = new Mongo.Collection('tasks');
先程作ったファイルをサーバで使うように読み込みます。 server/main.jsに追記していきます。
import '../imports/api/tasks.js';
コレクションを使うにはモジュールのインストールが必要なので行います。
meteor npm install --save react-addons-pure-render-mixin meteor add react-meteor-data
コレクションを使うには、先程つくったApp.jsxを編集する必要があります。
import React, { Component } from 'react'; //追記 import { createContainer } from 'meteor/react-meteor-data'; //追記 import { Task } from '../api/tasks.js'; //追記 import Task from './Task.jsx'; class App extends Component { renderTasks() { return this.getTasks().map((task) => ( <Task key={task._id} task={task} /> )); } render() { return ( <div className="container"> <header> <h1>Todo List</h1> </header> <ul> {this.renderTasks()} </ul> </div> ); } } //追記 App.propTypes ={ tasks: PropTypes.array.isRequired, }; //追記 export default createContainer(() => { return { tasks:Tasks.find({}).fetch(), }; },App);
コレクションにデータを入れていきます。 ターミナル2つ使い、1つはmeteorコマンドでサーバを起動 もう1つはmeteor mongoでコンソールを立ち上げます
//1つ目のターミナル meteor //2つ目のターミナル meteor mongo
データをインサートする
// 2つ目のターミナル コレクションのコンソールが起動した状態で db.tasks.insert({ text: "Hello world!", createdAt: new Date() });
Todoを追加するフォームを記述していきます imports/ui/App.jsx
import React, { Component, PropTypes } from 'react'; // 追記 import ReactDOM from 'react-dom'; import { createContainer } from 'meteor/react-meteor-data'; import { Tasks } from '../api/tasks.js'; import Task from './Task.jsx'; class App extends Component { // 追記 フォーム入力確定後に実行される関数 handleSubmit(event){ event.preventDefault(); const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim(); Tasks.insert({ text, createdAt: new Date(), }); ReactDOM.findDOMNode(this.refs.textInput).value = ''; } renderTasks() { return this.props.tasks.map((task) => ( <Task key={task._id} task={task} /> )); } render() { return ( <div className="container"> <header> <h1>Todo List</h1> // フォームの追記 <form className="new-task" onSubmit={this.handleSubmit.bind(this)} > <input type="text" ref="textInput" placeholder="Type to add new tasks" /> </form> </header> <ul> {this.renderTasks()} </ul> </div> ); } } App.propTypes ={ tasks: PropTypes.array.isRequired, }; export default createContainer(() => { return { // 書き換え tasks:Tasks.find({}, {sort: { createdAt: -1} }).fetch(), }; },App);
実行してみる
まだすべて実装が終わっていませんが、実行してみましょう。 ちなみにmeteorコマンドでサーバを起動した状態でコードを修正すると自動でサーバをリスタートしてくれます。また、ブラウザも更新してくれます。
// サーバ起動 meteor
ページにアクセスする際は、http://localhost:3000でいけると思います。
こんな感じのTodoリストができていたらOKです。 リストの追加や終わったリストへのチェック、項目の削除ができるので動作を確認しておきましょう。
今回のまとめ
今回はここまでにします。
今回は
- Meteorのインストール
- Meteorで動かす
- ToDoアプリを作成する
- Reactで書くための準備
- とりあえずのTodoリストを書く
- コレクションの設定
- フォームの設置
今後も書いていきます。
思ったよりチュートリアル長い。。。