若是歷來不瞭解React先看前篇React入門 (1)—使用指南(包括ES5和ES6對比)。
本文爲了能將前篇學到的react知識學以至用,作了一個相似微博展現列表的demo。使用的是ES6+React+JSX+Webpack+Babel+NPMcss
圖爲截取的微博展現列表,我這麼來劃分組件:
html
花括號括起來的是我要寫的幾個組件:react
最外層節點放在最上面,每一個控件的數量經過後臺給的數據控制,組件之間的關係用樹狀圖表示:
webpack
本文章只實現純文字,帶圖片的微博。帶視屏,轉發的能夠用相似的方法實現,就不贅述了。後端數據的結構設計爲:es6
var dataList=[ { headUrl:'http://img1.gtimg.com/tech/pics/hv1/238/85/1736/112905313.jpg', nickName:'Robin', content:'拿快遞拿快遞3號小郵局爆倉啦', NoCollect:132, NoForward:202, NoComment:142, NoPointGreat:423, contentImgUrls:[ "http://img1.gtimg.com/tech/pics/hv1/238/85/1736/112905313.jpg", "http://img1.gtimg.com/tech/pics/hv1/238/85/1736/112905313.jpg" ] }, { //內容同上 } ];
圖中組件的數量是根據後端給的數據來決定的,dataList的元素個數表明OneWB的個數,contentImgUrls的元素個數決定了微博帶不帶圖片,以及展現幾個。web
使用webpack+npm。
個人工程目錄結構如圖:
webpack以commonjs的形式來書寫腳本,是如今很火的模塊加載器+打包工具。使用方法:npm
npm init
參數能夠不填,回車代替。
執行完會生成package.json文件json
npm install 插件名 --save-dev.
('--save-dev' 通常在開發者開發項目的時候用,這個指令會把安裝的包依賴寫入package.json的devDependencies字段中。若是命令去掉'-dev',則會記錄到dependencies字段中)。
須要安裝這麼些個:
npm install -save-dev webpack
npm install -save-dev react
npm install -save-dev react-dom
npm install --save-dev babel-core
npm install --save-dev babel-loader
npm install --save-dev babel-preset-es2015
,babel6才須要裝
npm install -save-dev babel-preset-react
,babel6才須要裝
若是用的別人的工程,已存在package.json文件且內容完整,那麼直接npm install不須要手動安裝了。後端
根據webpack.config.js文件來決定webpack要作哪些動做。數組
//webpack.config.js 文件內容 var path = require('path'); module.exports = { entry: { 'index': './index.js' //key只是個名字,能夠自由改 }, output: { path: './build', filename: 'entry.js',//也能夠動態生成文件名 filename:'[name].js',將根據entry中的key生成名字 }, module: { loaders: [{ test: /\.jsx?$/, loader: 'babel', /* babel6 才須要配置這個,presets裏面兩個預編譯插件,前一個用於編譯es6,後一個用於編譯react。按需配置。這個工程都須要。 query:{ presets: ['es2015','react'] }*/ }] } };
這段代碼主要告訴了webpack:
總得來講,webpack從entry拿到目標文件,經過loaders進行編譯,從output輸出,其餘功能由plugins引入。
注:index.js:負責渲染組件到頁面上。至關於一個總的出口。由於會自動加載依賴關係,因此webpack.config.js文件只須要配置這一文件便可。
另外,這個工程比較簡單,只需配置一個js文件。
entry: { 'file1': './index.js', //key只是個名字,能夠自由改 'file2': './index2.js' }
webpack
會在build文件夾下生成編譯後(未壓縮)的js文件,entry.js。若是編譯錯誤會在命令行提示錯誤緣由,entry.js爲上一版本的內容。
你也可使用其餘命令,方便開發:
webpack -w
監聽你的代碼修改,實施打包生成entry.js, 通常都直接使用這個命令。
webpack -p
打包js文件,並壓縮。
完成以上四步,你就能夠一邊編寫代碼,用require(es6用import)來加載依賴的模塊,一邊在瀏覽器查看效果啦。而且若是之後有新的項目,直接拷貝package.json和webpack.config.js ,秒搭建環境。
須要用的react特性有:事件,state,props。依然能夠參見上一篇的詳細介紹。
import React from 'react';
,以及依賴的其餘組件。import ReactDOM from 'react-dom';
,由於渲染頁面的方法render()是reactdom的。module.exports = ListWB;
開放組件給其餘文件引用。只需引入一個文件,編譯後的文件entry.js。div#place爲react組件的父容器。是否是看起來好像什麼都沒有呢?react中,經過js來插入組件,咱們看index.js文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>weibo-react</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <div id="place"> <!-- 此處插入react插件 --> </div> <!-- dom定義 --> <script src="build/entry.js"></script> </body> </html>
使用自定義的react組件,渲染頁面。
import React from 'react'; import ReactDOM from 'react-dom'; import ListWB from './components/list-wb.jsx';//微博列表組件 var dataList=[{},{}];//這裏存儲的是後端傳來的數據。包括頭像,內容,點贊數等等 ReactDOM.render(<ListWB data={dataList} />, document.getElementById('place') );
ListWB是微博列表組件,經過自定義屬性data傳遞後端數據,並set到子組件中,展現到頁面上。
注意import ListWB from './components/list-wb.jsx';
必定要記得引入自定義組件模塊。
import React from 'react'; import OneWB from './one-wb.jsx';//標籤的名字根據這個變量名來決定 class ListWB extends React.Component{ render() { // 遍歷後端給的數據,而且插入 var oneWBNodes = this.props.data.map(function(aWB,index){ return <OneWB oneData={aWB} key={index}></OneWB>; }); return <div> {oneWBNodes} </div>; } } module.exports = ListWB;
筆記:
該組件表明單條微博。要處理的有:
<div id={if (condition) { 'msg' }}>Hello World!</div>
React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
然而咱們仍是有不少場景須要根據條件判斷某些組件要不要展現。
咱們用這幾種方式來實現:
React.render(<div id={condition ? 'msg' : ''}>Hello World!</div>, mountNode);
var vid=''; if(condition){ vid='msg'; } React.render(<div id={vid}>Hello World!</div>, mountNode);
<div id={(()=>{ if(this.state.isComment){ return 4; } })()}> </div>
匿名函數這種方式也一樣能夠用在標籤中間 <div>{(()=>{//函數內容})()}</div>
我使用的是第二種方式,代碼仍是更易維護一些。
這個文件的代碼:
import React from 'react'; import CommentForm from './comment-form.jsx'; import ContentImg from './content-img.jsx'; class OneWB extends React.Component{ constructor(props){ super(props); this.state={ isComment:false, }; } render() { var oneData=this.props.oneData; var commentForm; var contentImgs; if(this.state.isComment) { //控制評論框是否展示,由於是動態的,因此放在state而不是props commentForm =<CommentForm data-my-head-img={oneData.headUrl}/>; } if(oneData.contentImgUrls){ //若後端給的數據中有圖片url,則展現 contentImgs = <ContentImg content-img-urls={oneData.contentImgUrls} /> } return <div className="big-center" > <div className="one-wb "> <div className="clearfix"> <div className="ow-left"> <img className="nick-img" src={oneData.headUrl}/> </div> <div className="ow-right"> <div className="ow-nick row"> <span>{oneData.nickName}</span> </div> <div className="ow-content row">{oneData.content}</div> {contentImgs} </div> </div> <div className="ow-footer row "> <ul className="clearfix" onClick={this.handlerForwardClick.bind(this)}> <li className="li-side-border"><span>收藏</span> {oneData.NoCollect}</li> <li className="li-side-border"><span>轉發</span> {oneData.NoForward}</li> <li className="li-side-border"><span>評論</span> {oneData.NoComment}</li> <li><span>贊</span> {oneData.NoPointGreat}</li> </ul> </div> </div> {commentForm} </div>; } handlerForwardClick(event) { if(event.target.innerText == '評論'){ this.setState({isComment:true}); }else{ this.setState({isComment:false}); } } } module.exports = OneWB;
由於子組件放在一個數組裏,一樣須要注意配置key
import React from 'react'; class ContentImg extends React.Component{ render() { var imgNodes=this.props['content-img-urls'].map(function(oneImg,index){ return <li key={index} ><img src={oneImg} alt="微博配圖" /></li>; }); return <div className="row extra-content clearfix"> <ul> {imgNodes} </ul> </div> } } module.exports = ContentImg;
import React from 'react'; class CommentForm extends React.Component{ render() { var imgUrl=this.props['data-my-head-img']; return <div className="row comment-form clearfix" > <div className="ow-left"> <img src={imgUrl} alt="頭像" className="little-head" /> </div> <div className="ow-right" > <textarea name="name" rows="8" cols="40" className="comment-box"></textarea> <input className="comment-btn" type="submit" value="評論"/> </div> </div>; } } module.exports = CommentForm;
看完這篇文章,相信可以快速在工做當中實踐了吧 ~(≧▽≦)/~ 。但願之後能出一些深入的文章。