版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
PS:轉(zhuǎn)載請(qǐng)注明出處
作者:TigerChain
地址:http://www.itdecent.cn/p/9fddf666b718
本文出自TigerChain簡(jiǎn)書
教程簡(jiǎn)介
- 1、閱讀對(duì)象
本篇教程適合有React基礎(chǔ)的朋友閱讀(基礎(chǔ)知道 state,props, 組件化思想,webpack+yarn 等),老鳥直接略過,如果有誤,歡迎指出,謝謝。
-
2、教程難度
中級(jí)
3、Demo 地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/10-weibodemo
正文
經(jīng)過上一篇學(xué)習(xí),我們把微博 Demo 的雛形搭建出來了,那把接下來我們把微博后面的內(nèi)容帶大家手把手全部做完。我們接著上一節(jié)的步驟繼續(xù)學(xué)習(xí)
5、添加頭像組件
- 1、在項(xiàng)目的根目錄新建 img 文件夾并且放入三張圖片 (具體在demo中去查看)

- 2、修改 WeiBoListItem.js
只添加一句代碼,就是進(jìn)入一張圖片并且設(shè)置樣式,這里就不貼代碼了,看圖即可。

如圖所示,其中黃色部分就是我們引入一張圖片,并設(shè)置樣式,大家應(yīng)該想到了還要去設(shè)置樣式,沒錯(cuò)。
- 3、修改 ListItemStyle.css ,添加以下樣式即可
.imgStyle{
width: 80px;
height: 80px;
border-radius: 40px;
margin-right: 10px;
}
- 4、yarn start 跑一下,如果沒有什么問題,會(huì)報(bào)如下錯(cuò)

從圖中我們可以清楚的看到報(bào)錯(cuò)的原因,就是我們加載不了圖片,給我們的建議是下面這條紅線中說的,我們需要 loader 去處理文件類型。loader 我們不陌生,我們?nèi)グ惭b即可。提前說一下,在這里我們要安裝兩個(gè) loader 分別是 url-loader 和 file-loader (都是用于打包文件和圖片)。關(guān)于 url-loader 和 file-loader 的區(qū)別 請(qǐng)查看:url-loader和file-loader加載器有什么區(qū)別?
- 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'
}
將以上內(nèi)容添加到 webpack.config.js loaders 標(biāo)簽中,這沒什么好說的。
- 7、運(yùn)行項(xiàng)目 yart-start
我們就會(huì)看到如下界面

我們?nèi)缙诎杨^像加載進(jìn)來了。
6、添加評(píng)論列表組件
我們?cè)陧?xiàng)目 app 目錄新建 評(píng)論組件 CommentForm.js
# CommentForm.js
import React, { Component, PropTypes } from 'react';
// 導(dǎo)入評(píng)論的樣式
import styles from '../css/commentStyle.css';
/**
* 取得當(dāng)前時(shí)間
* @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;
}
/**
* 評(píng)論組件
*/
export default class CommentForm extends Component {
constructor(props) {
super(props);
this.state = {
//默認(rèn)回復(fù)內(nèi)容為空
replycontents:[],
}
}
render() {
//遍歷評(píng)論內(nèi)容
var replyContentDatas = this.state.replycontents.map(function(data,index) {
return(
// <CommentReplyList key={index} reply={data}/>
<div key={index}>
<div>
{/* 回復(fù)姓名 */}
<span>{data.name}</span>
{/* 回復(fù)內(nèi)容 */}
<span>{data.content}</span>
</div>
{/* 回復(fù)時(shí)間 */}
<span>{data.time}</span>
</div>
);
});
return (
<div className={styles.rootView}>
<div className={styles.headView}>
{/* 回復(fù)的頭像 */}
<img src={require('../img/qiche.jpg')} className={styles.img} />
{/* 回復(fù)的文本框 */}
<div className={styles.textareaViewStyle}>
<textarea cols='4' rows='4' ref="content"/>
<button className={styles.commentBtnStyle} onClick={this._reply.bind(this)}>評(píng)論</button>
</div>
</div>
{/* 回復(fù)內(nèi)容 */}
{replyContentDatas}
</div>
);
}
/**
* 回復(fù)評(píng)論功能
*/
_reply(){
//取得當(dāng)前時(shí)間
let currentTime = getCurrentFormatDate();
//取得回復(fù)的內(nèi)容
let recontent = this.refs.content.value;
if(recontent.length==0){
alert('評(píng)論內(nèi)容不能為空!')
return ;
}
let newContent = {
content:recontent,
name:'軍軍',
time:currentTime,
}
//取得老的回復(fù)內(nèi)容
let oldRepContent = this.state.replycontents,
//新的回復(fù)內(nèi)容和老的回復(fù)內(nèi)容疊加起來
newRplContent = oldRepContent.concat(newContent);//數(shù)組的疊加
//
this.setState({
replycontents:newRplContent,
});
//輕空輸入框內(nèi)容
this.refs.content.value = "";
}
}
這個(gè)代碼稍微有點(diǎn)多,但是注釋寫的非常清楚,此組件的作用就是把評(píng)論的組件寫出來。
7、在 css 目錄中新建 commentStyle.css (評(píng)論組件 css 樣式)
/*根樣式*/
.rootView{
display: flex;
flex-direction: column;
background: #fff;
padding: 10px;
margin-top: -15px;
}
/*評(píng)論頭頭像,文本框,按鈕樣式*/
.headView{
display: flex;
background: #fff;
}
/*昵稱樣式*/
.nickNameStyle{
display: flex;
flex-direction: column;
font-size: 12px;
}
/**
* 評(píng)論列表樣式
*/
.commentListStyle{
padding-left: 55px;
margin-bottom: 10px;
display: flex;
align-items: flex-start;
}
/**
* 評(píng)論內(nèi)容樣式
*/
.commentContentStyle{
display: flex;
flex:1;
margin-left: 10px;
justify-content: space-between;
}
.img{
width: 35px;
height: 35px;
}
/**
* 評(píng)論內(nèi)容樣式
*/
.textareaViewStyle{
margin-left: 20px;
display: flex;
flex-direction: column;
flex:1;
margin-bottom: 10px;
}
/**
* 評(píng)論按鈕樣式
*/
.commentBtnStyle{
width: 100px;
background: #ff8146;
margin-top: 10px;
border: 1px solid #f77c3d;
color: #fff;
height: 25px;
font-size: 14px;
}
這沒有什么好說的,經(jīng)過前面一步步的創(chuàng)建 css 這里我們大體也能看懂,注釋也非常清楚。
以上步驟我們就成功創(chuàng)建了個(gè)評(píng)論組件,但是我們要把這個(gè)組件嵌入到 WeiBoListItem.js 中并且添加事件交互,我們接著做
8、添加 CommentForm.js 到 WeiBoListItem.js 中
- 1、首先我們?cè)?WeiBoListItem.js 中導(dǎo)入評(píng)論組件
# WeiBoListItem.js
import CommentForm from './CommentForm' ;
- 2、在 render 的 return 方法中隱藏或顯示評(píng)論組件
# WeiBoListItem.js
//渲染界面
render() {
let data = this.props.itemData ;
return (
<div>
{this._renderHeadView(data)}
<hr className={styles.hrStyle}/>
{this._renderFooterView(data)}
{/* 點(diǎn)擊評(píng)論按鈕 則展開評(píng)論組件,否則隱藏 新添加的方法*/}
{this.state.isComment? <CommentForm />:null}
</div>
);
}
- 3、給點(diǎn)贊等按鈕添加事件在 _renderFooterView() 方法中
# WeiBoListItem.js
_renderFooterView(data){
return(
<div className={styles.commentViewStyle}>
<ul className={styles.ulStyle}>
{/* 此處新增方法 */}
<li className={styles.liStyle} onClick={this._dianzan.bind(this)}>點(diǎn)贊:{this.state.zanNum}</li><div className={styles.shuxian}></div>
<li className={styles.liStyle} onClick={this._comment.bind(this)}>評(píng)論:{data.NoComment}</li><div className={styles.shuxian}></div>
<li className={styles.liStyle} onClick={this._zhuanFa.bind(this)}>轉(zhuǎn)發(fā):{data.NoPointGreat}</li>
</ul>
</div>
);
}
4、添加點(diǎn)贊等方法
# WeiBoListItem.js
/**
* 評(píng)論方法
*/
_comment(){
this.setState({
isComment:true
})
}
/**
* 點(diǎn)贊方法
*/
_dianzan(){
this.setState({
isComment:false,
zanNum:parseInt(this.state.zanNum)+1,
})
}
/**
* 轉(zhuǎn)發(fā)方法
*/
_zhuanFa(){
this.setState({
isComment:false
})
}
到這里基本上我就能響應(yīng)評(píng)論組件并且輸入內(nèi)容來交互了,試一下吧。在命令行中 使用 yarn start ,并在瀏覽器輸入 localhost:8899 回車

我們基本上把開頭微博的樣子完成百分之九十了,接下來就是把評(píng)論組件抽取出來并且把評(píng)論列表樣式修改一下(我們這里只是把姓名,內(nèi)容,時(shí)間顯示出來,這里完全可以抽取成一個(gè)組件)
9、抽取評(píng)論列表
在 app 中新建 CommentReplyList.js (評(píng)論列表組件)
# CommentReplyList.js
import React, { Component, PropTypes } from 'react';
import styles from '../css/commentStyle.css';
/**
* 評(píng)論列表組件
*/
export default class CommentReplyList extends Component {
constructor(props) {
super(props);
this.state = {
// 回復(fù)列表
data:this.props.reply
}
}
render() {
let replyContent = this.state.data ;
return (
<div className={styles.commentListStyle}>
<img src={require('../img/avtova.jpg')} className={styles.img} />
{/**評(píng)論布局**/}
<div className={styles.commentContentStyle}>
{/**昵稱和內(nèi)容布局**/}
<div className={styles.nickNameStyle}>
{/**評(píng)論昵稱**/}
<span>{replyContent.name}</span>
{/**評(píng)論內(nèi)容**/}
<span>{replyContent.content}</span>
</div>
{/**評(píng)論時(shí)間**/}
<span className={styles.timeSize}>{replyContent.time}</span>
</div>
</div>
);
}
}
10、修改 CommentForm.js

從圖中可以看到,我們只是修改黃色部分即可。
看一下效果:

我們可以看到評(píng)論列表樣式我們修改完成了。
11、添加微博列表中圖片組件
- 1、在 app 中新建 CommentListImgs.js (微博列表圖片組件)
import React, { Component, PropTypes } from 'react';
/**
* 導(dǎo)入圖片樣式
*/
import styles from '../css/commentImgsStyle.css' ;
/**
* 微博列表中的圖片 無狀態(tài)的組件
*/
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 并輸入以下內(nèi)容
.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>
{/**新添加的內(nèi)容**/}
{data.contentImgUrls?<CommentListImgs imgUrls={data.contentImgUrls}/>:null}
</div>
</div>
)
}
代碼太多,我們這里只貼出核心修改的地方,具體代碼看demo
我們?cè)龠\(yùn)行一下,就會(huì)看到我們開頭的效果圖

到此為止,我們手把手教大家擼了一個(gè)微博的小 Demo,經(jīng)過這個(gè) demo 大家掌握 webpack+yarn+react的基礎(chǔ)知識(shí),以及組件化的思想,無狀態(tài)化組件編寫等。希望大家能從 0 開始動(dòng)手寫一遍。
Demo地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/10-weibodemo
如果覺得對(duì)你有用,就點(diǎn)個(gè)喜歡吧。