NW.js + React.js + Material UI 簡單整合範例
前言
NW.js 提供了一用 Html 5 / Javascript 開發軟體的選擇, 雖然目前採用相關方法開發的程式 (例如: PhoneGap) 速度上以及程式大小上還無法跟原生軟體相比, 但是這個距離正在拉近中. 採用 Html 5 / Javascript 技術開發應用程式速度上的確比傳統應用程式快移植也快, 但是大大小小的問題讓這個開發方式有一條很長的路要走.
ReactJS 是 Facebook 發表的一套 Web UI 架構 Framework, 它的作用不是用來取代現有的 Framework, 而是提供一個架構讓 Web UI 元件化並提高元件的可再用性. ReactJS 內建的 JSX 語法讓 Javascript 與 Html 語法更緊密的結合在一起, 在某種程度上看起來有點像 Server-side Script (PHP/JSP/ASP) 跟 Html 碼交互呈現的感覺. 畢竟現在 Javascript 要產生 Html DOM 內容並不像 Server-side Script 這麼直覺. 所以採用 ReactJS 在某種程度上有助於簡化以及讓程式碼更易於維護.
Material-UI 是一套以 ReactJS 為底層實作的一系列仿 Google Material UI 風格的 Web UI 元件, 對於這套 UI 我還不是很了解.
本篇的目的是如何把這 ReactJS 以及 Material-UI 成功的運行在 NW.js 上面. 有關 Material-UI 以及 ReactJS 的用法就不在本篇的探討範圍中.
準備工作
請先下載 NW.js
與 Node.js 一樣, NW.js 需要 package.json 告訴它要從哪裡開始載入, 並採用那些函式庫. 以下是一個可以運行的範例:
{
"name": "Tester",
"main": "index.html",
"scripts": {
"less": "lessc css/main.less > css/main.css"
},
"dependencies": {
"material-ui": "^0.7.3",
"node-jsx": "^0.12.4",
"react": "^0.13.1",
"react-tap-event-plugin": "^0.1.6"
}
}
範例一: package.js
接下來是 index.html 的內容:
<!DOCTYPE html>
<html>
<head>
<title>Tester</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<script>
global.document= window.document
global.navigator= window.navigator
window.onload = function() {
require('node-jsx').install({extension: '.js'});
require('./app/main.js');
}
</script>
</body>
</html>
範例二: index.html
接下來是 Material-UI 的 css 定義:
@import "node_modules/material-ui/src/less/scaffolding.less";
@import "node_modules/material-ui/src/less/components.less";
範例三: main.less
Material-UI 是使用 less, 所以必須要安裝 less 做 css 編譯工作 npm install less
. 安裝完成之後可以執行 npm run-script less
編譯 css.
目前 ReactJS 主要還是運行在瀏覽器上, 跟 Node.js 還是並沒有 100% 相容, 所以這兩行程式碼主要是解決相容性問題以免 ReactJS 找不到 document 以及 navigator 物件
global.document= window.document
global.navigator= window.navigator
在 index.html 之中我採用了內嵌式的 Javascript <script>...</script>
, 並在內部用 CommonJS 載入主程式. 而不是 <script type="text/jsx">...</script>
或是 <script src="app/main.js">...</script>
, 是因為 NW.js 無法解析 <script type="text/jsx">
, 採用 <script src="app/main.js">
的話 main.js 必須是採用正規 Javascript 的語法而不能用 JSX 語法.
ReactJS 原本是 Web 的 Framework, 所以直接在 NW.js 上使用 ReactJS 會有些問題. 所以我們改用 node-jsx 套件並提前載入 jsx 解譯器. {extension: '.js'}
則是告訴解譯器 JSX 副檔名為 .js
接下來是 main.js:
(function () {
var React = require('react'),
injectTapEventPlugin = require("react-tap-event-plugin"),
Main = require('./main_ui.js');
//Needed for React Developer Tools
window.React = React;
//Needed for onTouchTap
//Can go away when react 1.0 release
//Check this repo:
//https://github.com/zilverline/react-tap-event-plugin
injectTapEventPlugin();
// Render the main app react component into the document body.
// For more details see: https://facebook.github.io/react/docs/top-level-api.html#react.render
React.render(<Main />, document.body);
})();
範例四: app/main.js
大部分的程式碼在註解都有解釋了, 我還是稍微提一下. react-tap-event-plugin
是目前用來啟動 ReactJS 的Touch 事件支援, 也許以後就不需要了.
這樣基本的 ReactJS 架構就已經成形, 接下來就是程式碼的部分.
主程式
這個程式只用了一個標準扁平按鈕做測試, 以下是程式碼.
var React = require('react'),
mui = require('material-ui'),
FlatButton = mui.FlatButton;
var MainUi = React.createClass({
render: function() {
return (
<FlatButton label="Primary" primary={true} />
);
}
});
module.exports = MainUi;
範例五: app/main_ui.js
2015/7/6 更新:
React.js 在 0.13.2 版之後似乎對於內部架構有所變動, 目前還沒有找到解決方案. 如果目前不想改的話只能暫時使用 0.13.1 之前的版本.
修改 package.json
{
...
"node-jsx": "^0.12.4",
"react": "0.13.1", // 把版本固定在 0.13.1
"react-tap-event-plugin": "^0.1.6"
...
}
執行 npm update
更新 react.js.
我也發現這篇教學忘了把 css 部份加入所以畫面顯示會不正常, 順便補上.
留言
張貼留言