react的路很長(zhǎng),這將是一個(gè)開(kāi)始酬诀。
開(kāi)發(fā)之前磺芭,你需要首先了解一下幾點(diǎn):
webpack:
Webpack 是當(dāng)下最熱門(mén)的前端資源模塊化管理和打包工具。它可以將許多松散的模塊按照依賴(lài)和規(guī)則打包成符合生產(chǎn)環(huán)境部署的前端資源是尖。還可以將按需加載的模塊進(jìn)行代碼分隔意系,等到實(shí)際需要的時(shí)候再異步加載。通過(guò) loader 的轉(zhuǎn)換饺汹,任何形式的資源都可以視作模塊蛔添,比如 CommonJs 模塊、 AMD 模塊、 ES6 模塊迎瞧、CSS夸溶、圖片、 JSON凶硅、Coffeescript缝裁、 LESS 等。
webpack-dev-server:
在webpack中有一個(gè)在開(kāi)發(fā)時(shí)很好用的功能足绅,熱加載(Hot-replace)捷绑,在react開(kāi)發(fā)中,結(jié)合上react-hot-loader插件氢妈,開(kāi)發(fā)工作將會(huì)變得更棒:更改代碼之后粹污,你甚至都不需要去刷新你的瀏覽器,界面就會(huì)自動(dòng)刷新首量。但是壮吩,要使用這一功能的話,我們就需要使用webpack-dev-server加缘。webpack-dev-server是一個(gè)小型的node.js Express服務(wù)器,它使用webpack-dev-middleware中間件來(lái)為通過(guò)webpack打包生成的資源文件提供Web服務(wù)鸭叙。它還有一個(gè)通過(guò)Socket.IO連接著webpack-dev-server服務(wù)器的小型運(yùn)行時(shí)程序。webpack-dev-server發(fā)送關(guān)于編譯狀態(tài)的消息到客戶(hù)端拣宏,客戶(hù)端根據(jù)消息作出響應(yīng)递雀。
react-router:
在react開(kāi)發(fā)中,react-router是由官方維護(hù)的蚀浆,唯一可選的路由庫(kù)缀程。它通過(guò)管理 URL,實(shí)現(xiàn)組件的切換和狀態(tài)的變化市俊,開(kāi)發(fā)復(fù)雜的應(yīng)用幾乎肯定會(huì)用到杨凑。
babel:
Babel是一個(gè)JavaScript編譯器。默認(rèn)情況下摆昧,babel自帶了一組ES2015語(yǔ)法轉(zhuǎn)化器撩满。這些轉(zhuǎn)化器可以讓你現(xiàn)在就使用最新的JavaScript語(yǔ)法,而不需要等待瀏覽器提供支持绅你。本文要講的開(kāi)發(fā)例子中伺帘,就使用到了ES6以及部分ES7所提出的一些新規(guī)范,所以需要使用babel來(lái)進(jìn)行轉(zhuǎn)化忌锯。
一伪嫁、配置package.json文件
首先建立項(xiàng)目文件夾,在該項(xiàng)目文件夾目錄下執(zhí)行npm init命令偶垮,然后一直回車(chē)到底张咳,生成package.json文件帝洪,接下來(lái)再進(jìn)行詳細(xì)的配置。
package.json
{
"name": "webpack-react",
"version": "1.0.0",
"description": " webpack-react ",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --hot --progress --colors",
"build": "webpack --progress --colors"
},
"author": "CainZK",
"license": "ISC",
"devDependencies": {
"babel": "^6.5.2",
"babel-core": "^6.7.2",
"babel-loader": "^6.2.4",
"babel-plugin-react-transform": "^2.0.2",
"babel-plugin-transform-class-properties": "^6.16.0",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-2": "^6.17.0",
"classnames": "^2.2.5",
"css-loader": "^0.23.1",
"file-loader": "^0.8.5",
"html-webpack-plugin": "^2.10.0",
"react": "^0.14.8",
"react-dom": "^15.3.2",
"react-hot-loader": "^1.3.0",
"react-router": "^2.8.1",
"react-slick": "^0.14.5",
"react-transform-hmr": "^1.0.4",
"rmc-list-view": "^0.6.2",
"sass-loader": "^3.2.0",
"style-loader": "^0.13.0",
"url-loader": "^0.5.7",
"webpack": "^1.12.14",
"webpack-dev-server": "^1.14.1"
}
}
這里需要說(shuō)一下scripts字段以及devDependencies字段脚猾。在scripts字段下第一個(gè)命令"start": "webpack-dev-server --hot --progress --colors"表示執(zhí)行npm start命令時(shí)葱峡,會(huì)執(zhí)行后面的命令,即用webpack-dev-server啟動(dòng)服務(wù)龙助, --hot表示熱替換配置砰奕,--progress表示顯示進(jìn)度,--colors表示配置輸出的顏色提鸟。第二個(gè)命令build表示執(zhí)行npm run build的時(shí)候军援,會(huì)使用webpack進(jìn)行打包操作。
二沽一、配置webpack.config.js文件
上一步打包的時(shí)候,所有的配置工作都是在webpack.config.js文件中進(jìn)行的漓糙。所以接下來(lái)我們來(lái)完善webpack的相關(guān)配置铣缠。
webpack.config.js
var path = require('path');
var webpack = require('webpack');
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
// var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
a:[
'webpack/hot/only-dev-server',
"./app/index.js"
],
b:[
'webpack/hot/only-dev-server',
"./app/index2.js"
]
},
output: {
path: BUILD_PATH,
publicPath: "/build/",
filename: "[name].bundle.js"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
query:
{
presets:['react','es2015','stage-2'] // babel配置:添加這三個(gè)presets用來(lái)處理js和jsx
}
}, {
test: /\.css$/,
loaders: ['style', 'css', 'sass'], //.scss 文件使用 style-loader、css-loader 和 sass-loader 來(lái)編譯處理
include: APP_PATH
}, {
test: /\.(png|jpg)$/,
loader: 'url?limit=40000' //圖片文件使用 url-loader 來(lái)處理昆禽,小于40000字節(jié)的直接轉(zhuǎn)為base64
}
]
},
resolve:{
extensions:['','.js','.json'] //自動(dòng)擴(kuò)展文件后綴名蝗蛙,意味著我們r(jià)equire模塊可以省略不寫(xiě)后綴名
},
devServer: {
hot: true, //熱加載模式
inline: true //inline模式(將webpack-dev-sever的客戶(hù)端入口添加到包(bundle)中)
},
plugins: [
new webpack.NoErrorsPlugin(),//用來(lái)跳過(guò)編譯時(shí)出錯(cuò)的代碼并記錄,使編譯后運(yùn)行時(shí)的包不會(huì)發(fā)生錯(cuò)誤
new webpack.HotModuleReplacementPlugin()//全局開(kāi)啟代碼熱替換
]
};
entry:入口配置醉鳖,這里我進(jìn)行的是多頁(yè)面入口文件的配置捡硅,如果是單頁(yè)面的話可以這樣來(lái)進(jìn)行配置:
entry: {
'webpack/hot/only-dev-server',
"./app/index.js"
},
path是webpack輸出地址,取絕對(duì)路徑盗棵;
publicPath是webpack-dev-server啟動(dòng)服務(wù)時(shí)在內(nèi)存中文件生成的地址壮韭。
filename:這里多頁(yè)面入口文件配置需要加上[name]。
loaders:使用loader對(duì)一些文件進(jìn)行相應(yīng)的處理纹因。
test:使用正則匹配要處理的文件喷屋。
exclude:排除不處理的目錄。
loader:要使用的loader瞭恰。
...(其余相關(guān)配置已寫(xiě)在代碼注釋中)
三屯曹、完善入口頁(yè)面
在項(xiàng)目根目錄下簡(jiǎn)歷index.html以及index1.html表示兩個(gè)入口頁(yè)面。
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" type="text/css" href="./app/css/base.css">
<title>React App</title>
</head>
<body>
<div id="content"></div>
<script src="./build/b.bundle.js"></script>
</body>
</html>
index1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="content"></div>
<script src="./build/a.bundle.js"></script>
</body>
</html>
在根目錄下新建app目錄惊畏,新建index.js以及index1.js文件恶耽。
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import myBt from './example/myBt';
import Carousel from './example/myCarousel';
import ActionSheet from './example/myActionSheet';
import { Router, Route, IndexRoute, hashHistory} from 'react-router';
import rt from './example/route';
class App extends React.Component {
render () {
console.log(window.screen.height);
return (
<div>
{this.props.children}
</div>
);
}
}
ReactDOM.render((
<Router history={hashHistory}>
<Route path="/" component={App} >
<IndexRoute component={rt}/>
<Route path="/carousel" component={Carousel}/>
<Route path="/button" component={myBt}/>
<Route path="/actionSheet" component={ActionSheet}/>
</Route>
</Router>),
document.getElementById('content')
);
index1.js
import React from 'react';
import ReactDOM from 'react-dom';
import ListView from 'rmc-list-view';
var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';
class App extends React.Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds,
loaded:false,
};
}
componentDidMount() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
loaded: true,
});
})
}
renderLoadingView() {
return (
<div>
Loading ...
</div>
);
}
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
var rowStyle = {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
}
var imgStyle = {
height:120,
width:80
}
return(
<ListView
style={{ height: 667, backgroundColor:'#FAFAFA' }}
dataSource={this.state.dataSource}
renderRow={(rowData) => (
<div style={rowStyle}>
<img src={rowData.posters.thumbnail} style={imgStyle}/>
<a style={{flex: 1,marginTop:15,marginLeft:10,fontSize:18,height:36,position:'absolute'}}>
{rowData.title}
</a>
</div>
)}
/>
);
}
};
ReactDOM.render(<App/>, document.getElementById('content'));
這里我們?cè)趇ndex.js文件中使用了react-router,簡(jiǎn)單介紹一下它的一些配置及簡(jiǎn)單的用法颜启。
導(dǎo)入路由:
import { Router, Route, IndexRoute, hashHistory} from 'react-router';
配置路由信息:
<Router history={hashHistory}>
<Route path="/" component={App} >
<IndexRoute component={rt}/>
<Route path="/carousel" component={Carousel}/>
<Route path="/button" component={myBt}/>
<Route path="/actionSheet" component={ActionSheet}/>
</Route>
</Router>
路由跳轉(zhuǎn)頁(yè)面設(shè)置:
import React from 'react';
export default class Button extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div style={{padding:20}}>
<a href="#carousel" style={{marginLeft:20}}>
carousel
</a>
<a href="#button" style={{marginLeft:20}}>
button
</a>
<a href="#actionSheet" style={{marginLeft:20}}>
actionSheet
</a>
</div>
);
}
};
path是跳轉(zhuǎn)路徑偷俭,component中的是跳轉(zhuǎn)路徑過(guò)后要展示出來(lái)的react組件。具體的詳細(xì)用法可以參考npm官網(wǎng)的介紹缰盏,這里就不多說(shuō)了社搅。
到這里框架搭建基本完成驻债,缺的只有文中所引用的第三方組件了,如果您感興趣的話形葬,可以參考github合呐,將項(xiàng)目down下來(lái),再進(jìn)行研究笙以,我也會(huì)繼續(xù)完善這個(gè)簡(jiǎn)單的框架淌实,添加更多的組件進(jìn)去,方便開(kāi)發(fā)猖腕。
成功搭建后的演示: