- 投稿日:2019-08-29T23:44:20+09:00
初めてのvue.js 簡易的なメモ・備忘録編
はじめに
まず、私の説明だけ簡単にさせていただきます。
とあるベンチャー企業でフロントエンドエンジニアとして働いています。
ライブラリーはReactを使い、1年にも満たないですが、redux,redux-saga,非同期通信などなど、様々なことに挑戦して、Reactを自信を持って書けるようになりました。
そんな私が、あるきっかけでvue.jsを使用することになってので、勉強録としてまとめてみました。今回は、まとめというより、メモという意味合いが強いです。
vue.jsやフロントエンドに強い方、謝りや誤認識等ありましたら、ぜひご指摘ください!こちらの書籍をベースに学習しております。
Reactに馴染んでいる私にとって、非常にわかりやすく、スラスラ読める一冊です!
初めてプログラミングに触れた時は、全く理解できなかったが………
Vue.js入門 基礎から実践アプリケーション開発までそれでは。
オプション(メソッドのようなもの)
data
UIの状態・データ
Reactでいうstateみたいなものかな?変数のような概念かな?
このdata
を通して、html側にデータを送るようです。
名前から役割が想像しやすいですね。el
vueインスタンスをマウントする要素。
マウントがよく分かっていません。
el
でマウントすることで、該当htmlにデータを送受信したり、計算したり、加工したりできるようになる。メソッドによるマウントもでき、その場合は$mountを使うようです。
filters
データを文字列と整形する。
データを 計算 するのではなく、あくまでも整形する。
後述ののcomputed
と役割が被って見えます。methods
イベントが発生した時などの振る舞い。
onClick等の処理を書いているところですね。computed
データから派生して算出される値。
要は、受け取ったデータを 計算 しているものですね。
前述のfilters
と役割が被って見えます。テンプレート構文
{{}}
Mustache構文(二重中括弧)という名前らしいです。ディレクティブ
オプションと同じように、vue.jsで重要な概念の一つ。
ディレクティブにより、onClickで処理をメソッドに渡したり、繰り返しの構文を使えたり、formのデータを取得できるようです。v-bind
`v-bind: 属性名 = "データを展開した属性値"
buttonのdisableやstyleなどに、vueのデータやメソッドを挟み込めるようになりますね。省略記法として、
:
+ 属性名で記述できます。例<p v-bind:class="hoge"> ↓ <p :class="hoge">v-if/v-show
条件付きレンダリング。
名前だけやと分からないですね。
非表示・非表示を切り替える場合に使うものです。見た目上は同じような動きをしますが、v-ifはDOMの追加・削除を、v-showはdisplayプロパティの変更をするようです。
v-for
リストレンダリング。
jsのfor構文と同じく、html上でデータの繰り返し処理ができるようです。v-on
イベントハンドリング。
onClickやonChange属性にメソッドや処理を渡せるようです。省略記法として
@
があります。例<button v-on:click="hoge"> ↓ <button @click="hoge">v-model
フォーム入力バインディング。
双方向バインディングを実現できる。
Reactでは少し記述が冗長になるため、これは非常に便利!
- 投稿日:2019-08-29T17:54:52+09:00
vte.cxによるバックエンドを不要にする開発(その5)
前回=>vte.cxによるバックエンドを不要にする開発(その4)
今回はデータ登録における一貫性について、ホテル予約サンプルアプリケーションを元に説明します。
データ一貫性を考慮したホテル予約アプリケーションを作る
まず、ホテルを予約するシンプルなアプリケーションを作ってみましょう。
ここで大事になるのは、複数の顧客が、同じ部屋を予約しようとした場合の処理です。当然ですが各部屋は顧客一人しか予約できません。絶対に複数の顧客が同じ部屋を予約できないようにしなくてはいけません。
例えば 101 の部屋の空き状況を、二人の顧客(A と B)が同じタイミングで確認したとしましょう。そのときには 101 は空いていました。その後、A は B よりも早く 101 を予約します。その少し後に、B も 101 を予約しようとします。なぜなら B が見ている空き状況は、最初に確認したタイミングのものですから、A が予約したことが反映されていないからです。このような状況で予約ボタンを押した場合、「既に予約されているのでエラーにする」必要があります。
こういったシステムを作るために vte.cxには、idを元にした楽観的排他という仕組みがあります。
それぞれのentryには一意の識別子としてidがあり、idには更新回数であるrevisionが含まれています。(revisionは更新の都度+1されることになります) この revision を含む id を書き込み時に参照することで、既に他の顧客が更新した後なのかどうなのか、ということを判別しています。では早速、アプリケーションの以下の項目を管理画面の新規エントリ項目追加から登録しましょう。
登録方法はこれまで行っていますのでわかりますね。room name reservation(boolean)エントリ項目一覧で以下のように表示されればOKです。(※ 前回使用したuserなどの項目が残っていても問題ありません)
また、エンドポイント管理で
/hotel
というエンドポイントを追加しましょう。
(※ 前回使用した/fooが残っていても問題ありません)登録したら、設定ファイルをダウンロードして更新しておきましょう。
npm run download:template npm run download:typingsアプリケーションのソースコードは以下のようになります。
index.tsximport * as React from 'react' import * as ReactDOM from 'react-dom' import { useState } from 'react' import axios from 'axios' const App = () => { const [rooms, setRooms] = useState<VtecxApp.Entry[]>([]) const initdata: VtecxApp.Entry[] = [ { room: { name: '101', reserved: false }, link: [ { "___href": "/hotel/101", "___rel": "self" } ] }, { room: { name: '102', reserved: false }, link: [ { "___href": "/hotel/102", "___rel": "self" } ] } ] const putrooms = async (req:VtecxApp.Entry[]) => { try { axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest' await axios.put('/d/hotel',req) getrooms() } catch (e) { alert('error:'+e) } } const getrooms = async () => { try { axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest' const res = await axios.get('/d/hotel?f') setRooms(res.data) } catch (e) { alert('error') console.log(e) } } const showrooms = () => { return rooms.map((entry,index) => { if (entry.room&&!entry.room.reserved) { return ( <div key={index}> <p>{entry.room.name} <button onClick={() => { reserve(entry) }} > 予約 </button> </p> </div> ) } }) } const reserve = async (entry:VtecxApp.Entry) =>{ if (entry.room) { entry.room.reserved = true putrooms([entry]) } } return ( <div> <button onClick={() => { putrooms(initdata) }}> 初期化 </button> <button onClick={() => { getrooms() }}> 一覧 </button> <br/> {showrooms()} </div> ) } ReactDOM.render(<App/>, document.getElementById('container'))これを、
npm run serve:index
で起動してください(未ログインの場合は、先にnpm run serve:login
を実行してください)すると、以下のような画面が出ますので、初期化ボタンを押してください。
ホテルの部屋一覧が表示されると思います。このとき、サーバに登録されたデータは以下のようになっています。
部屋番号の右の予約ボタンを押すと予約が実行されてリストから消えます。
101号室と102号室をそれぞれ予約してみてください。元に戻すには初期化ボタンを押します。楽観的排他制御の確認
次に、ブラウザのタブをもう一つ開いてアプリケーションを表示させてください。
1つ目のアプリケーション画面では初期化ボタンを押し、別のアプリケーション画面では一覧ボタンを押し、101号室を予約してください。そして、1つ目のアプリケーションに戻り、まだ表示されている101号室の予約を実行してください。このとき、2つ目のアプリケーションが先に101号室を予約しているので、1つ目のアプリケーションはエラーになるはずです。実際に予約を実行すると以下のようなエラー画面が出てくると思います。
デベロッパーツールで詳しくエラーメッセージを見ると、
{"feed" : {"title" : "Optimistic locking failed. Key = /hotel/101"}
のように出ています。
これは楽観的排他エラーが発生したことを意味します。つまり、1つ目のアプリケーションで更新しようとしたentryのidが、既に2つ目のアプリケーションにより更新されて+1されており、一致しなかったというわけです。楽観的排他エラーになることで、ダブルブッキングをさせない空室予約が可能になるのです。
ちなみに、強制的に上書きする方法もあります。それは、PUT更新時にid項目を含めないでリクエストすることで、楽観的排他エラーを敢えて発生させずに更新することができます。
今回はここまでです。お疲れ様でした。
- 投稿日:2019-08-29T17:31:59+09:00
静的サイトジェネレータReact-Staticを使ってみる
はじめに
プログラミング歴2ヶ月の素人が書いています。(間違っていたらご指摘ください)
「React-Staticをはじめて使ってみる」ための学習メモです。
React-Staticプロジェクトの生成
Netlifyへのデプロイ
上記2点についてまとめます。
?React-Static公式?
https://github.com/react-static/react-static今回の目的
静的サイトジェネレータReact-Staticを初めて使います。
簡単に爆速表示のブログサイトを自動生成して、Netlifyにデプロイします。
Node.jsのインストール
ReactはNode.jsを必要としますので、インストールします。
https://nodejs.org/ja/yarnのインストール
パッケージマネジャーとしては、Node.jsに付いてくる標準のnpmもありますが、私の環境と実力ではうまくビルドができませんでした。
npmからyarnに変えたところうまくいったので、ここはyarnを使うのがいいと思います。
React-Staticのインストール
$ yarn global add react-staticグローバルにReact-Staticをインストールします。
React-Staticプロジェクトの作成
$ cd プロジェクトのディレクトリ $ react-static createプロジェクト名と、テンプレート名を聞かれます。
テーンプレートは、『Basic』を選択しました。ローカルホストで確認
localhost:3000
から作成したプロジェクトにアクセスできます。本番環境のビルド
$ yarn build本番用のファイルとして、distファイルが生成されます。
githubにプッシュ
まずはgithubにプッシュして、そのリポジトリをNetlifと連携することでデプロイします。
dist
だけでなく、プロジェクト全体をプッシュします。Netlifyにデプロイ
SignUpを済ませます。
今回はgithubと連携させてデプロイします。
連携の際、
『Build Command』 =>
yarn build
『Publish Directory』 =>
dist
を入力します。
これによって、今後githubに変更がプッシュされるたびに、Netlifyが自動で
yarn build
を実行し、生成されるdist
ファイルをデプロイしてくれます。私たちはgithubにプッシュするだけでいいので、手間が省けます。
まとめ
React-Staticプロジェクトの生成
Netlifyへのデプロイ
上記2点についてまとめました。
- 投稿日:2019-08-29T14:10:46+09:00
ReactでQiitaAPIを叩いてアプリを作る入門
はじめに
Reactの勉強を始めたので手始めにAPIを叩いて超簡単なアプリを一から作ってみる練習をしました。
今回使用したAPIはQiita API v2です。作成したアプリはGitHubのリポジトリにあげてあります。どのAPIを叩くか決めるとき参考にした記事
https://qiita.com/mikan3rd/items/ba4737023f08bb2ca161
アプリを作るときに参考にした記事
https://qiita.com/gcyagyu/items/4d186df2e90c53228951create-react-appでプロジェクトの作成
create-react-appを使うことでアプリの雛形を作ることができます。今回はreact-api-studyというアプリ名で作成しています。
参考
https://create-react-app.dev/$ create-react-app react-api-studyaxiosのインストール
アプリを作成したらディレクトリを移動して、axiosをインストールします。
$ cd react-api-study $ yarn add axiosアプリの実装
今回はQiitaAPIの
https://qiita.com/api/v2/items
のエンドポイントを叩いて記事一覧を取ってきて、タイトルとURLを表示させます。GET /api/v2/items
記事の一覧を作成日時の降順で返します。
- page
- ページ番号 (1から100まで)
- Example: 1
- Type: string
- Pattern: /^[0-9]+$/
- per_page
- 1ページあたりに含まれる要素数 (1から100まで)
- Example: 20
- Type: string
- Pattern: /^[0-9]+$/
- query
- 検索クエリ
- Example: "qiita user:yaotti"
- Type: string
src/index.js
の拡張子を変えてsrc/index.jsx
を記述しますsrc/index.jsximport React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; // 次に記述する src/components/App.jsx をインポートする import App from './components/App'; ReactDOM.render(<App />, document.getElementById('root'));
src
ディレクトリの下にconponents
ディレクトリを作成し、その中にApp.jsx
ファイルを作成し次のソースを記述します。src/conponents/App.jsximport React, { Component } from 'react'; // axiosをインポート import axios from 'axios'; class App extends Component { constructor(props) { super(props); this.getQiitaPosts = this.getQiitaPosts.bind(this); this.state = { // ここを`React`など検索したいワードに変えられる query: 'React' } } // QiitaAPIを叩く getQiitaPosts() { //axios.get(APIのエンドポイント,パラメータの引数) axios.get('https://qiita.com/api/v2/items', { params: { "page": "1", "per_page": "20", "query": this.state.query, } }) // response にAPIからのレスポンスが格納される .then((response) => { // data にレスポンスから帰ってきた1つ目の記事の情報を格納 const data = response.data[0]; this.setState({ title: data.title, url: data.url, }); // コンソールから response と title と url を確認 console.debug(response, "ressponse"); console.debug(this.state.title, "title") console.debug(this.state.url, "url") }) .catch((error) => { console.debug(error); }); } // 表示されるHTMLを記述 render() { return ( <div className="App"> <h1 className="app-title">Hello Qiita API</h1> <p>タイトル: {this.state.title}</p> <p>URL: <a target="__blank" href={this.state.url}>{this.state.url}</a></p> <input type="button" value="検索" onClick={() => this.getQiitaPosts()} /> </div> ) } } export default App;
{this.state.title}
などでAPIから取ってきた値を埋め込んで表示させています。
<a target="__brank" href={this.state.url}>
aタグのhref属性にurlを指定してリンクを埋め込んでいます。
onClick={() => this.getQiitaPosts()}
で検索ボタンをクリックしたときにQiitaAPIを叩く関数を呼び出しています。完成
ターミナルで
npm start
で起動してlocalhost:3000
を開きますおわりに
間違っていることや改善したほうが良いことがあればコメントで優しく教えて下さいmm
- 投稿日:2019-08-29T13:06:52+09:00
Reactでよく使われるライブラリをオールインワンにしたボイラーテンプレートを作った
React+Typescriptを使ったシステム構築を検討する上で、「これは使うよなー」と思ったライブラリをまとめて、サンプル付きのボイラーテンプレートを作りました。
動機
Reactで実際に動くシステムを作ろうすると、色々なライブラリを使いたくなる。
でも、一つのライブラリを動かすために、ディレクトリ構成を考え直したり設定をコードに書いていくのは本当に大変。。。
なので、共通して使えそうなエッセンスだけを抽出してボイラーテンプレートを作りました!Demo
リポジトリの場所
https://github.com/joolen/react-project-template
使い方
下記のコマンドを実行するだけ。
# clone this repository git clone https://github.com/joolen/react-project-template.git my-app # change direcory you made cd my-app # install dependencies npm install # run project. you can access http://localhost:3000 npm start使用ライブラリ
Name Note ドキュメントURL React これがなければ始まらない。 https://reactjs.org/ Typescript 所謂、AltJS。解説は巷に溢れているが、静的な型付をすることが特徴。 https://www.typescriptlang.org/ material-ui 簡単にそれなりの画面を作る為のコンポーネント群を提供してくれる。 https://material-ui.com/ react-redux 非常にわかりやすい記事があるので添付
たぶんこれが一番分かりやすいと思います React + Redux のフロー図解https://redux.js.org/
https://react-redux.js.org/typescript-fsa(-reducers) TypescriptでReduxを使うときのボイラーテンプレートです。これにより、記述を簡略化出来ます。 https://github.com/aikoven/typescript-fsa
https://github.com/dphilipson/typescript-fsa-reducersredux-saga React Redux構成でAPI通信を行う為のMiddlewareです。 https://redux-saga.js.org/ react-router SPAで画面遷移をさせる為のデファクトスタンダードライブラリ。これを使うことで、ブラウザの「戻る」ボタンなども使える様になる。 https://reacttraining.com/react-router/ Storybook 作成したコンポーネントを単体で見られる様にしてくれるツール。
(このツール自体はReactには限らない。vue.jsなどでも利用可能。)https://storybook.js.org/ ディレクトリ構成
こんな感じ
my-app ├── README.md ├── node_modules ├── package.json ├── .gitignore ├── .tsconfig.json ├── .storybook # StoryBookの設定関連ファイル │ ├── addons.js │ ├── config.js │ └── webpack.config.js ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json └── src │ ├── API # 外部APIとの通信はここにまとめる │ ├── components # Atomic Designを使ってコンポーネントを管理している │ │ ├── atoms │ │ ├── molecules │ │ ├── organisms │ │ ├── templates │ │ ├── pages │ │ └── stories # StoryBookの定義 │ └── containers # Redux connectはここにまとめている │ └── routes # SPAなので、各ページへのルーティングはここに記述 │ │ └── index.tsx │ ├── sagas # Redux-sagaの関連処理 │ │ └── index.ts # root saga │ ├── modules # Reduxのmodules。変則的かもしれないど、Ducks │ ├── tests # JestとStoryShotsをここで利用 │ │ └── __snapshots__ # snapshot │ │ │ └── storyshots.test.ts.snap # snapshotファイル │ │ └── reducers # reducersのテストコード │ │ │ └── sample.test.ts │ │ └── storyshots.test.ts # storyshots │ ├── App.css │ ├── configureStore.ts # Reduxで使うStoreのconfigurationがまとまっている │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ └── serviceWorker.ts └─────この構成にした理由
別途、まとめ中です。下記のような構成で書いていこうと思います。
Reactのアーキテクトを考える道のり - その1 (最小の構成)
Reactのアーキテクトを考える道のり - その2(Fluxとの出会い)
Reactのアーキテクトを考える道のり - その3(非同期処理でハマる)→Redux-saga
Reactのアーキテクトを考える道のり - その4(コンポーネントのディレクトリ構成に悩む)→Atomic Designとの出会い
Reactのアーキテクトを考える道のり - その5(テストについて)→JestやStoryshotsについて
- 投稿日:2019-08-29T11:11:20+09:00
Reduxを使い始めたらthisに悩まされなくなった
javascriptのthisは非常に癖が強く使う場合は注意が必要です。
最近はアロー関数のおかげである程度マシになりましたが、
逆に旧来のjsに慣れ親しんでいる人からするとthisが切り替わらないことが気持ち悪かったりもするようで、厄介なことに変わりありません。javascriptは後方互換性を大切にする言語なので、thisレベルの大きな言語仕様が変更されることはおそらくないでしょうし、
typescriptを使ってもjavascriptのスーパーセットである以上、thisはthisのままです。
これはいつまで経ってもフロントではthisに悩まされ続けるのかなぁとうんざりしていたのですが、
ふと気づくと最近thisに悩まされないどころか、書いてすらいないことに気づきました。何がきっかけなんだっけ?と振り返ってみたところ、どうやらReduxのおかげのようでした。
Reduxを使うと処理と状態が分離する
thisが必要になるのは、いわゆるオブジェクト指向的な、
状態を持ったオブジェクトに紐づく関数を使う場合です。しかし、Reduxを使うとStateはStoreに全て集約されます。
Reducerは純粋な関数ですし、ActionCreatorも引数に応じてActionをDispatchするだけ、
ContainerはStateからPropsを生成してPresentationalComponentに渡すだけ、
PresentationalComponentは当然FunctionalComponentなのでStateは持ちません。つまり、thisを使う必要のあるシーンがありません。
まとめ
- thisはStateとロジックが結合している場合に必要になる
- reduxはStateを一か所に集約するためthisが必要なくなる