若是历来不了解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;
看完这篇文章,相信可以快速在工做当中实践了吧 ~(≧▽≦)/~ 。但愿之后能出一些深入的文章。