版权声明:本文为博主原创文章,未经博主允许不得转载。
PS:转载请注明出处
作者:TigerChain
地址:http://www.jianshu.com/p/9fddf666b718
本文出自TigerChain简书
教程简介
- 1、阅读对象
本篇教程适合有React基础的朋友阅读(基础知道 state,props, 组件化思想,webpack+yarn 等),老鸟直接略过,如果有误,欢迎指出,谢谢。
-
2、教程难度
中级
3、Demo 地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/10-weibodemo
正文
经过上一篇学习,我们把微博 Demo 的雏形搭建出来了,那把接下来我们把微博后面的内容带大家手把手全部做完。我们接着上一节的步骤继续学习
5、添加头像组件
- 1、在项目的根目录新建 img 文件夹并且放入三张图片 (具体在demo中去查看)
- 2、修改 WeiBoListItem.js
只添加一句代码,就是进入一张图片并且设置样式,这里就不贴代码了,看图即可。
如图所示,其中黄色部分就是我们引入一张图片,并设置样式,大家应该想到了还要去设置样式,没错。
- 3、修改 ListItemStyle.css ,添加以下样式即可
.imgStyle{
width: 80px;
height: 80px;
border-radius: 40px;
margin-right: 10px;
}
- 4、yarn start 跑一下,如果没有什么问题,会报如下错
从图中我们可以清楚的看到报错的原因,就是我们加载不了图片,给我们的建议是下面这条红线中说的,我们需要 loader 去处理文件类型。loader 我们不陌生,我们去安装即可。提前说一下,在这里我们要安装两个 loader 分别是 url-loader 和 file-loader (都是用于打包文件和图片)。关于 url-loader 和 file-loader 的区别 请查看:url-loader和file-loader加载器有什么区别?
- 5、安装 url-loader 和 file-loader。
yarn add url-loader file-loader --dev
安装了 loader 以后肯定要在 webpack.config.js 中去配置。
- 6、添加 url-loader file-loader 到 webpack.config.js 中去
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=8192'
}
将以上内容添加到 webpack.config.js loaders 标签中,这没什么好说的。
- 7、运行项目 yart-start
我们就会看到如下界面
我们如期把头像加载进来了。
6、添加评论列表组件
我们在项目 app 目录新建 评论组件 CommentForm.js
# CommentForm.js
import React, { Component, PropTypes } from 'react';
// 导入评论的样式
import styles from '../css/commentStyle.css';
/**
* 取得当前时间
* @return {[type]} [description]
*/
function getCurrentFormatDate() {
var date = new Date() ;
var seperator1 = "-" ;
var seperator2 = ":" ;
var month = date.getMonth() + 1 ;
var strDate = date.getDate() ;
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+ " " + date.getHours() + seperator2 + date.getMinutes()
+ seperator2 + date.getSeconds();
return currentdate;
}
/**
* 评论组件
*/
export default class CommentForm extends Component {
constructor(props) {
super(props);
this.state = {
//默认回复内容为空
replycontents:[],
}
}
render() {
//遍历评论内容
var replyContentDatas = this.state.replycontents.map(function(data,index) {
return(
// <CommentReplyList key={index} reply={data}/>
<div key={index}>
<div>
{/* 回复姓名 */}
<span>{data.name}</span>
{/* 回复内容 */}
<span>{data.content}</span>
</div>
{/* 回复时间 */}
<span>{data.time}</span>
</div>
);
});
return (
<div className={styles.rootView}>
<div className={styles.headView}>
{/* 回复的头像 */}
<img src={require('../img/qiche.jpg')} className={styles.img} />
{/* 回复的文本框 */}
<div className={styles.textareaViewStyle}>
<textarea cols='4' rows='4' ref="content"/>
<button className={styles.commentBtnStyle} onClick={this._reply.bind(this)}>评论</button>
</div>
</div>
{/* 回复内容 */}
{replyContentDatas}
</div>
);
}
/**
* 回复评论功能
*/
_reply(){
//取得当前时间
let currentTime = getCurrentFormatDate();
//取得回复的内容
let recontent = this.refs.content.value;
if(recontent.length==0){
alert('评论内容不能为空!')
return ;
}
let newContent = {
content:recontent,
name:'军军',
time:currentTime,
}
//取得老的回复内容
let oldRepContent = this.state.replycontents,
//新的回复内容和老的回复内容叠加起来
newRplContent = oldRepContent.concat(newContent);//数组的叠加
//
this.setState({
replycontents:newRplContent,
});
//轻空输入框内容
this.refs.content.value = "";
}
}
这个代码稍微有点多,但是注释写的非常清楚,此组件的作用就是把评论的组件写出来。
7、在 css 目录中新建 commentStyle.css (评论组件 css 样式)
/*根样式*/
.rootView{
display: flex;
flex-direction: column;
background: #fff;
padding: 10px;
margin-top: -15px;
}
/*评论头头像,文本框,按钮样式*/
.headView{
display: flex;
background: #fff;
}
/*昵称样式*/
.nickNameStyle{
display: flex;
flex-direction: column;
font-size: 12px;
}
/**
* 评论列表样式
*/
.commentListStyle{
padding-left: 55px;
margin-bottom: 10px;
display: flex;
align-items: flex-start;
}
/**
* 评论内容样式
*/
.commentContentStyle{
display: flex;
flex:1;
margin-left: 10px;
justify-content: space-between;
}
.img{
width: 35px;
height: 35px;
}
/**
* 评论内容样式
*/
.textareaViewStyle{
margin-left: 20px;
display: flex;
flex-direction: column;
flex:1;
margin-bottom: 10px;
}
/**
* 评论按钮样式
*/
.commentBtnStyle{
width: 100px;
background: #ff8146;
margin-top: 10px;
border: 1px solid #f77c3d;
color: #fff;
height: 25px;
font-size: 14px;
}
这没有什么好说的,经过前面一步步的创建 css 这里我们大体也能看懂,注释也非常清楚。
以上步骤我们就成功创建了个评论组件,但是我们要把这个组件嵌入到 WeiBoListItem.js 中并且添加事件交互,我们接着做
8、添加 CommentForm.js 到 WeiBoListItem.js 中
- 1、首先我们在 WeiBoListItem.js 中导入评论组件
# WeiBoListItem.js
import CommentForm from './CommentForm' ;
- 2、在 render 的 return 方法中隐藏或显示评论组件
# WeiBoListItem.js
//渲染界面
render() {
let data = this.props.itemData ;
return (
<div>
{this._renderHeadView(data)}
<hr className={styles.hrStyle}/>
{this._renderFooterView(data)}
{/* 点击评论按钮 则展开评论组件,否则隐藏 新添加的方法*/}
{this.state.isComment? <CommentForm />:null}
</div>
);
}
- 3、给点赞等按钮添加事件在 _renderFooterView() 方法中
# WeiBoListItem.js
_renderFooterView(data){
return(
<div className={styles.commentViewStyle}>
<ul className={styles.ulStyle}>
{/* 此处新增方法 */}
<li className={styles.liStyle} onClick={this._dianzan.bind(this)}>点赞:{this.state.zanNum}</li><div className={styles.shuxian}></div>
<li className={styles.liStyle} onClick={this._comment.bind(this)}>评论:{data.NoComment}</li><div className={styles.shuxian}></div>
<li className={styles.liStyle} onClick={this._zhuanFa.bind(this)}>转发:{data.NoPointGreat}</li>
</ul>
</div>
);
}
4、添加点赞等方法
# WeiBoListItem.js
/**
* 评论方法
*/
_comment(){
this.setState({
isComment:true
})
}
/**
* 点赞方法
*/
_dianzan(){
this.setState({
isComment:false,
zanNum:parseInt(this.state.zanNum)+1,
})
}
/**
* 转发方法
*/
_zhuanFa(){
this.setState({
isComment:false
})
}
到这里基本上我就能响应评论组件并且输入内容来交互了,试一下吧。在命令行中 使用 yarn start ,并在浏览器输入 localhost:8899 回车
我们基本上把开头微博的样子完成百分之九十了,接下来就是把评论组件抽取出来并且把评论列表样式修改一下(我们这里只是把姓名,内容,时间显示出来,这里完全可以抽取成一个组件)
9、抽取评论列表
在 app 中新建 CommentReplyList.js (评论列表组件)
# CommentReplyList.js
import React, { Component, PropTypes } from 'react';
import styles from '../css/commentStyle.css';
/**
* 评论列表组件
*/
export default class CommentReplyList extends Component {
constructor(props) {
super(props);
this.state = {
// 回复列表
data:this.props.reply
}
}
render() {
let replyContent = this.state.data ;
return (
<div className={styles.commentListStyle}>
<img src={require('../img/avtova.jpg')} className={styles.img} />
{/**评论布局**/}
<div className={styles.commentContentStyle}>
{/**昵称和内容布局**/}
<div className={styles.nickNameStyle}>
{/**评论昵称**/}
<span>{replyContent.name}</span>
{/**评论内容**/}
<span>{replyContent.content}</span>
</div>
{/**评论时间**/}
<span className={styles.timeSize}>{replyContent.time}</span>
</div>
</div>
);
}
}
10、修改 CommentForm.js
从图中可以看到,我们只是修改黄色部分即可。
看一下效果:
我们可以看到评论列表样式我们修改完成了。
11、添加微博列表中图片组件
- 1、在 app 中新建 CommentListImgs.js (微博列表图片组件)
import React, { Component, PropTypes } from 'react';
/**
* 导入图片样式
*/
import styles from '../css/commentImgsStyle.css' ;
/**
* 微博列表中的图片 无状态的组件
*/
export default class CommentListImgs extends Component {
constructor(props) {
super(props);
}
render() {
// 遍历图片并显示
var imgs = this.props.imgUrls.map(function(imgurl,index) {
return(<li key={index} className={styles.liStyle}><img src={require('../img/avtova.jpg')} className={styles.imgStyle}></img></li>);
});
return(
<ul className={styles.ulstyle}>
{imgs}
</ul>
) ;
}
}
- 2、添加图片组件样式
在 css 目录中新建 commentImgsStyle.css 并输入以下内容
.imgStyle{
width: 100px;
height: 100px;
}
.ulstyle{
margin-top: 0px;
display: flex;
flex-wrap: wrap;
padding-left: 0px;
}
.liStyle{
list-style:none;
float:left;
margin-right: 10px;
margin-top: 10px;
align-self: center;
}
- 3 、修改 WeiBoListItem.js 组件 以下核心修改的地方
import CommentListImgs from './CommentListImgs.js' ;
_renderHeadView(data){
return(
<div className={styles.item}>
<img src={require('../img/tiger.jpg')} className={styles.imgStyle}></img>
<div className={styles.topRightView}>
<div className={styles.nickNameAndSendTime}>
<span>{data.nickName}</span>
<span>{data.sendTime}</span>
</div>
<p>{data.content}</p>
{/**新添加的内容**/}
{data.contentImgUrls?<CommentListImgs imgUrls={data.contentImgUrls}/>:null}
</div>
</div>
)
}
代码太多,我们这里只贴出核心修改的地方,具体代码看demo
我们再运行一下,就会看到我们开头的效果图
到此为止,我们手把手教大家撸了一个微博的小 Demo,经过这个 demo 大家掌握 webpack+yarn+react的基础知识,以及组件化的思想,无状态化组件编写等。希望大家能从 0 开始动手写一遍。
Demo地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/10-weibodemo
如果觉得对你有用,就点个喜欢吧。