從零開(kāi)始學(xué)習(xí) React 時(shí)按灶,歷經(jīng)一個(gè)月,終于算是有了一些理解筐咧。其中不乏有許多困惑的地方鸯旁,借本文在此梳理,項(xiàng)目地址量蕊。
引用 菜鳥(niǎo)教程的話:
React 是一個(gè)用于構(gòu)建用戶界面的 JAVASCRIPT 庫(kù)铺罢。
React主要用于構(gòu)建UI,很多人認(rèn)為 React 是 MVC 中的 V(視圖)危融。
React 起源于 Facebook 的內(nèi)部項(xiàng)目畏铆,用來(lái)架設(shè) Instagram 的網(wǎng)站,并于 2013 年 5 月開(kāi)源吉殃。
React 擁有較高的性能辞居,代碼邏輯非常簡(jiǎn)單楷怒,越來(lái)越多的人已開(kāi)始關(guān)注和使用它。
正由于react主要用于構(gòu)建UI瓦灶,所以要完成一個(gè)完整的項(xiàng)目我們不得不配合使用其他的工具鸠删,如webpack(打包工具)、gulp(自動(dòng)化構(gòu)建工具)贼陶、express(應(yīng)用程序框架)等刃泡。
express
express可以在本地啟動(dòng)一個(gè)服務(wù),當(dāng)你訪問(wèn)對(duì)應(yīng)端口時(shí)碉怔,你可以在服務(wù)里面進(jìn)行處理烘贴,返回文字,圖片撮胧,頁(yè)面等桨踪,是一個(gè)web應(yīng)用的基礎(chǔ)。新建一個(gè)server.js芹啥,里面如下:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
然后執(zhí)行
npm init //初始化packag.json
npm install express --save //安裝express
node server.js //把服務(wù)器跑起來(lái)
打開(kāi)瀏覽器輸入http://localhost:3000/
現(xiàn)在你能看到
Hello World!
我們也可以返回一個(gè)標(biāo)簽:
res.send('<h1>Hello World!</h1>')
看到就是這樣了
Hello World!
我們項(xiàng)目需要做的就是把一些寫好的組件锻离、頁(yè)面呈現(xiàn)給訪問(wèn)者,然后處理一些邏輯和展示數(shù)據(jù)墓怀。
我們?cè)傩陆ㄒ粋€(gè)index.html汽纠,內(nèi)容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello world!
</body>
</html>
我們?cè)俑囊幌聅erver.js文件,把html傳出去:
res.sendfile('./index.html');
webpack
我們一般用webpack來(lái)打包文件和資源傀履,并通過(guò)它來(lái)實(shí)時(shí)更新和打包虱朵。詳細(xì)可以看文檔。包括webpack的安裝钓账,配置文件的解釋和使用卧秘,打包,實(shí)時(shí)更新等內(nèi)容官扣。
由于react需要用到react.js、react-dom.js等庫(kù)羞福,項(xiàng)目中也會(huì)用到其他許許多多的庫(kù)我們先學(xué)習(xí)用webpack打包成一個(gè)很小的bundle.js文件惕蹄,然后在html文件中引用。
安裝webpack命令:
npm install webpack --save
一個(gè)最簡(jiǎn)單的Webpack配置文件webpack.config.js如下所示:
module.exports = {
entry:[
'./src/app.js'
],
output: {
path: __dirname + '/assets/',
publicPath: "/assets/",
filename: 'bundle.js'
}
};
我們創(chuàng)建兩個(gè)文件夾src治专、assets卖陵,并在src下新建app.js文件。執(zhí)行如下命令安裝react和react-dom:
npm install react --save
npm install react-dom --save
app.js文件內(nèi)容如下:
import { render } from 'react-dom'
render((
<div>hello world!</div>
), document.getElementById('root'));
為了讓webpack識(shí)別ES6和jsx語(yǔ)法我們需要安裝加載器loader了:
npm install --save-dev babel-core babel-preset-es2015
npm install --save-dev babel-loader
npm install babel-preset-react --save
在webpack.config.js中添加:
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015']
}
}]
}
在命令行執(zhí)行:
webpack
完成后就能在assets目錄下看到一個(gè)bundle.js文件了张峰。
為了讓我們的app.js允許訪問(wèn)本地資源泪蔫,我們加入以下代碼:
app.use(express.static('assets'));
我們?yōu)橹暗膇ndex.html添加一個(gè)script引用bundle.js:
//Express 相對(duì)于靜態(tài)目錄查找文件,因此靜態(tài)目錄的名稱不是此 URL 的一部分
<script src="/bundle.js"></script>
再次執(zhí)行:
node server.js
我們便可以看到兩個(gè)hello world!了喘批,這樣我們就把react這個(gè)“V”和服務(wù)器聯(lián)系了起來(lái)撩荣,接下來(lái)可以專心寫界面了铣揉。
react
react的官方文檔對(duì)我們的理解和使用有很大的幫助。文檔介紹了react的基本使用(組件的創(chuàng)建和渲染)餐曹,組件的生命周期(componentDidMount)逛拱,屬性的更新和值的傳遞(state、setState台猴、props)朽合。
jsx語(yǔ)法
HTML 語(yǔ)言直接寫在 JavaScript 語(yǔ)言之中,不加任何引號(hào)饱狂,這就是 JSX 的語(yǔ)法曹步,它允許 HTML 與 JavaScript 的混寫。
var names = ['a', 'b', 'c'];
render((
<div>
{
names.map(function (name) {
return <div>Hello, {name}!</div>
})
}
</div>
), document.getElementById('root'));
重新打包休讳,執(zhí)行
webpack
node server.js
可以看到
Hello, a!
Hello, b!
Hello, c!
hello world!
組件(component)
新建一個(gè)Home.js文件讲婚,如下:
import React from 'react';
class Home extends React.Component {
render() {
return <div>
home
</div>
}
}
export default Home
在app.js中引用
import { render } from 'react-dom';
import React from 'react';
import Home from './Home';
var names = ['a', 'b', 'c'];
render((
<div>
{
names.map(function (name) {
return <div>Hello, {name}!</div>
})
}
<Home />
</div>
), document.getElementById('root'));
重新打包,執(zhí)行
webpack
node server.js
可以看到
Hello, a!
Hello, b!
Hello, c!
home
hello world!
gulp
gulp就是一個(gè)自動(dòng)化工具衍腥,可以開(kāi)啟多個(gè)任務(wù)磺樱,然后將它們按序執(zhí)行,也可以結(jié)合其他插件使用婆咸。
每次都要打包竹捉,運(yùn)行是不是很麻煩,我們就需要用工具來(lái)幫我們完成這些工作尚骄。在根目錄新建一個(gè)gulpfile.babel.js文件块差。
gulp原生并不支持es6語(yǔ)法,但是我們可以告訴gulp使用babel將gulpfile轉(zhuǎn)換為es5倔丈,方法就是將gulpfile命名為gulpfile.babel.js憨闰。如果你的babel是6.0以上的版本,你需要添加一個(gè).babelrc文件:
{
"presets": ["es2015"]
}
安裝gulp相關(guān)工具:
npm install --save gulp-cli
npm install --save-dev gulp gulp-babel
npm install --save gulp-util
npm install --save-dev del
npm install --save exec
gulpfile.babel.js文件如下:
import gulp from 'gulp';
import gulpUtil from 'gulp-util';
import webpack from 'webpack';
import webpackConfig from './webpack.config.js';
import del from 'del';
import exec from 'exec';
gulp.task('clean-all', function () {
return del([webpackConfig.output])
});
gulp.task('watch', () => {
return gulp.watch('src/**/*.*', ['webpack:build'])
});
gulp.task('webpack:build', (callback) => {
// run webpack
webpack(webpackConfig, (err) => {
if (err)
throw new gulpUtil.PluginError('webpack:build', err);
callback();
});
});
gulp.task('server', (callback) => {
exec('node server.js', (err) => {
if (err)
throw new gulpUtil.PluginError('webpack:build', err);
callback()
})
});
gulp.task('default', ['watch', 'webpack:build', 'server']);
執(zhí)行
gulp
路由
路由可以對(duì)不同頁(yè)面進(jìn)行跳轉(zhuǎn)需五,也可以劃分項(xiàng)目的層次結(jié)構(gòu)○亩現(xiàn)在我們安裝路由
npm install react-router --save
然后在app.js中做如下改動(dòng)
import { render } from 'react-dom';
import React from 'react';
import Home from './Home';
import {browserHistory, Router, Route} from 'react-router'
render((
<Router history={browserHistory}>
<Route path="/" component={Home} />
</Router>
), document.getElementById('root'));
我們?nèi)稳豢梢钥吹絟ello home!
子路由也可以不寫在Router組件里面宏邮,單獨(dú)傳入Router組件的routes屬性泽示,我們也可以將routes抽取出一個(gè)單獨(dú)的文件。
import React from 'react';
import {browserHistory, Router} from 'react-router'
import routes from './routes'
React.render((
<Router history={browserHistory} routes={routes} />
), document.getElementById('root'));
新建routes文件夾蜜氨,新建index.js文件
import Home from '../Home';
export default {
path: '/',
component: Home,
}
安裝自動(dòng)刷新瀏覽器的插件
npm install webpack-dev-middleware --save-dev
npm install webpack-hot-middleware --save-dev
npm install html-webpack-plugin --save-dev
在webpack.config.js中修改entry械筛,添加plugins
entry:[
'webpack-hot-middleware/client?reload=true',
'./src/app.js'
],
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
template: './index.html',
filename: './index.html'
}),
]
在server.js中引用這些中間件,修改后如下
import express from 'express';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackDevConfig from './webpack.config';
export default function (callback) {
const compiler = webpack(webpackDevConfig);
const app = express();
app.use(express.static( webpackDevConfig.output.path));
app.use(webpackDevMiddleware(compiler,{
publicPath: webpackDevConfig.output.publicPath,
noInfo: true,
stats: {
colors: true
}
}));
app.use(webpackHotMiddleware(compiler));
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
callback();
};
代理
除了靜態(tài)資源外飒炎,我們也會(huì)訪問(wèn)到其他資源埋哟。這時(shí)候我們就需要用到代理。
npm install http-proxy-middleware --save
在sever.js中導(dǎo)入中間件郎汪,把需要代理的請(qǐng)求都攔截下來(lái)赤赊,去目標(biāo)服務(wù)器訪問(wèn)闯狱。
import proxy from 'http-proxy-middleware';
app.use('/a', proxy({
target: 'http://xxx.xxx.xxx.xxx:80/',
ws: true,
}));