自己紹介
じゅんじゅんというニックネームで、関西を拠点に活動しているフロントエンドエンジニアです。
HAL大阪の2回生です👍 (2016.9.9現在)
よくstart up系イベントに行くので、大阪らへんの方は会いましょう!
作ったもの
今回は
- ElectronとReactで作ること
しか決まってないので、リアルタイムプレビューの機能だけしかつけていません。
できたもの。
今回作った経緯
今回は、いつもREADMEとかを書くときにsublime textのOmniMarkupPreviewerを使っていたんですが、全然動かない。。
なぜか分からないので、勉強を兼ねて作ることにしました。
今回使う技術は
- Electron
- React
ぐらいです。
Editor部分はAceを使いました。
Markdownのpreviewには、markedを使いました。
Electronに関しては、ほぼサンプルコードのままです。
環境
Node v5.1.1
Electron v1.3.5
開発
今回の構成は
- app.js(electron)
- index.html
- stylesheets
- markd.css
- style.css
- javascripts
- app.js
- bundle.js
- components
- App.jsx
- Editor.jsx
- Preview.jsx
という感じになっています。
まずはnpm init
から始めましょう。
今回使ったモジュールは
- react
- react-dom
- marked
- react-ace
- brace
- electron-packager
開発に使うのは
- watchify
- babelify
- babel-preset-react
- babel-preset-es2015
react-ace
はreactでaceを使うためのコンポーネントです。
watchify
は使い差分ビルドするためで、babelify
はES6に対応したBrowserify用のパッケージです。
babel-preset-react
は、babelのreactのトランスパイルに使うものです。
babel-preset-es2015
というのがありますが、ES6用のものです。ES6で書かない場合は、省いて大丈夫です!
package.jsonにこれを追記してください。
"main": "app.js",
"scripts": {
"start": "watchify -v -t babelify javascripts/app.js -o javascripts/bundle.js"
},
では、まず.babelrc
を書きましょう。
{
"presets": ["react", "es2015"]
}
次に、htmlを編集します。
<body>
<div id="react"></div>
<script src="javascripts/bundle.js></script>
</body>
Reactのレンダリングするためのjavascripts/app.js
を編集しましょう。
import React from "react";
import { render } from "react-dom";
// componentのApp.jsxをインポート
import App from "./components/App.jsx";
render(
<App/>,
document.getElementById("react")
)
では、このインポートされたApp.jsxを書いていきます。
import React from "react";
// 後で作ります。
import Editor from "./Editor.jsx"
import Preview from "./Preview.jsx"
export default class App extends React.Component{
constructor(){
super();
this._edit = this._edit.bind(this); // ES6のthisバインドされない問題があるので.bind(this)
this.state = {
value: ""
}
}
render(){
return(
<div className="clearfix" id="app">
<Editor
edit={this._edit} // editorコンポーネントにeditしている間に呼ぶメソッドをpropsでわたします。
value={this.state.value}
/>
<Preview
data={this.state.value} // markedでhtmlにパースするときのデータ
/>
</div>
);
}
_edit(text){
this.setState({ value: text })
}
}
特に困ることもないと思います。
import React from "react";
import brace from 'brace';
import AceEditor from 'react-ace'; // aceのreact componentを使います。
import 'brace/mode/markdown'; // modeを選ぶ
import 'brace/theme/textmate'; // カラーテーマを選ぶ
export default class Editor extends React.Component{
constructor(props){
super(props)
this._onChange = this._onChange.bind(this);
}
render(){
return(
<AceEditor
mode="markdown" // mode
theme="textmate" // theme
width="45%"
height="100%"
name="editor" // id
tabSize={2}
showPrintMargin={false} // 真ん中らへんの線を消す
highlightActiveLine={false} // lineのハイライトを消す
editorProps={{$blockScrolling: true}}
onChange={this._onChange}
value={this.props.value}
/>
)
}
_onChange(text){
this.props.edit(text); // propsでわたってきたものを実行
}
}
上二つにでてくるthis._onChange = this._onChange.bind(this)
などのものですが、これはES6で書いたときに、自動でthisをバインドしてくれないので自分で書くしかない場合の書き方です。
stage-0を使ってより簡単に記述することができます。
//_onChange(){}
_onChange = () => {}
自作のメソッドをアロー関数をつかってかけばthisを追えるようになります。
react-ace
のオプションなどはreact-aceを参照ください。
import React from "react";
import marked from "marked";
export default class Preview extends React.Component{
constructor(props){
super(props);
}
render(){
return(
<div id="preview"
dangerouslySetInnerHTML={{__html: marked(this.props.data)}} // reactは標準では、HTMLがエスケープされてしまうので、エスケープされないようにしないといけない。
></div>
)
}
}
これで全てコンポーネントを書き終えました。
$ npm start
を実行してください。bundle.jsが出力されます。
そしたら
$ electron app.js
とすれば、アプリとしてこのエディタが立ちあがると思います。
おソースは全てgithubにあるので、興味あるひとはぜひみてください!
最後に
React自体もそんなに難しくなく、markedもaceも余裕でしたね。
今後はexport機能とかをつけようと思います。
9/15 グランフロントでReactハンズオンします!大阪の人ぜひ!
Twitter => @konojuya
HP => Hello, My World