LoginSignup
2
2

More than 5 years have passed since last update.

Meteorのあんちょこ꒰。・ω・`;꒱ ReactJS

Last updated at Posted at 2016-08-28

概要

  • React - Meteor(Tutorial)...simple-todosを作成

  • Virtual DOMで高速にDOMを操作したい

    • DOM(Documment Object Model)...タグをオブジェクトとみなし、各オブジェクトに様々な命令を実行できるようにJavaScriptがHTML/XMLを認識しなおした構造体。
    • VirtualDOM...DOMをJSONに書出したもの。
    • DOMに操作する場合は、仮想DOMを操作した結果をDOMに反映する。
    • DOMを直接操作しなくなるため、最小限のDOM操作だけで済ませることが可能。
    • [VirtualDOMとは@のんびりコード]
  • コンポーネント指向

  • リアクティブプログラミング

  • 関数型言語(プログラミング)

サンプル(DB未接続)

  • simple-todos

1.プロジェクト作成

console
$ meteor cretate simple-todos
$ cd simple-todos/
  1. npmインストール
console
$ meteor npm install

3.起動確認

console
$ meteor

4.react追加

console
$ meteor npm install --save react react-dom

5.React View Component 定義

client/main.html
<head>
  <title>Todo List</title>
</head>

<body>
  <div id="render-target"></div><!-- App Component を展開-->
</body>
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-target'にApp Componentを展開する。
  render(<App />, document.getElementById('render-target'));
});

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() {
    // JSONとして返却する。
    return [
      { _id: 1, text: 'This is task 1' },
      { _id: 2, text: 'This is task 2' },
      { _id: 3, text: 'This is task 3' },
    ];
  }

  // Taskを取得し、map関数でTaskを表示する。
  renderTasks() {
    return this.getTasks().map((task) => (<Task key={task._id} task={task} />));
  }

  // App render <App/>
  render() {
    return (
      <div className="container">
        <header>
          <h1>Todo List</h1>
        </header>

        <ul>
          {this.renderTasks()} 
        </ul>
      </div>
    );
  }
}
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>
      //<li>{this.props.task.text}(id={this.props.task._id})</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,
};
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;
  }
}

6.動作確認

console
$ meteor

DB接続

imports/api/tasks.js
  :
import { Mongo } from 'meteor/mongo';
export const Tasks = new Mongo.Collection('tasks');
  :
server/main.js
  :
import '../imports/api/tasks.js';
  :

React Meteor 関連付け

  • React Componentに含まれるコレクションのデータを使用するためには、Atmosphere パッケージ react-meteor-dataを使用する
  • react-meteor-dataでは、MeteorのリアクティブデータをReactのコンポーネント階層に受け渡すデータコンテナを生成できる。
console
$ meteor npm install --save react-addons-pure-render-mixin
$ meteor add react-meteor-data
App.jsx
import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';

import { Tasks } from '../api/tasks.js';

import Task from './Task.jsx';

// アプリケーション全体に提示されるApp Component
// App component - represents the whole app
class App extends Component {
// export default class App extends Component {

  // getTasks() {
  //   // JSONとして返却する。
  //   return [
  //     { _id: 1, text: 'This is task 1' },
  //     { _id: 2, text: 'This is task 2' },
  //     { _id: 3, text: 'This is task 3' },
  //   ];
  // }

  // Taskを取得し、map関数でTaskを表示する。
  renderTasks() {
    // (3)App(this).propsに対して、Task Componentを表示する。
    return this.props.tasks.map((task) => (
    // 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 = {
  // (2) App(this).props.tasks
  tasks: PropTypes.array.isRequired,
};

export default createContainer(() => {
    return {
      // (1)tasksにDBのTasks(tasks)の全データを取得し、フェッチする
      tasks: Tasks.find({}).fetch(),
    }
  };
}, App);
  • 動作確認
  • DBにダミーデーターを登録し、DBからデータが取得できることを確認する。
console
$ meteor mongo
> db.tasks.insert({ text: "Hello world!", createdAt: new Date() });
> exit
$ meteor

データ追加

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2