13、React系列之--微博Demo 02 终结篇

版权声明:本文为博主原创文章,未经博主允许不得转载。

PS:转载请注明出处
作者:TigerChain
地址:http://www.jianshu.com/p/9fddf666b718
本文出自TigerChain简书

React 教程系列

教程简介

  • 1、阅读对象

本篇教程适合有React基础的朋友阅读(基础知道 state,props, 组件化思想,webpack+yarn 等),老鸟直接略过,如果有误,欢迎指出,谢谢。

正文

经过上一篇学习,我们把微博 Demo 的雏形搭建出来了,那把接下来我们把微博后面的内容带大家手把手全部做完。我们接着上一节的步骤继续学习

5、添加头像组件

  • 1、在项目的根目录新建 img 文件夹并且放入三张图片 (具体在demo中去查看)
imgs.png
  • 2、修改 WeiBoListItem.js

只添加一句代码,就是进入一张图片并且设置样式,这里就不贴代码了,看图即可。

import_avator.png

如图所示,其中黄色部分就是我们引入一张图片,并设置样式,大家应该想到了还要去设置样式,没错。

  • 3、修改 ListItemStyle.css ,添加以下样式即可
.imgStyle{
  width: 80px;
  height: 80px;
  border-radius: 40px;
  margin-right: 10px;
}
  • 4、yarn start 跑一下,如果没有什么问题,会报如下错
error_import_img.png

从图中我们可以清楚的看到报错的原因,就是我们加载不了图片,给我们的建议是下面这条红线中说的,我们需要 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

我们就会看到如下界面

avator_weibo_list.png

我们如期把头像加载进来了。

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 回车

weibo_dam.gif

我们基本上把开头微博的样子完成百分之九十了,接下来就是把评论组件抽取出来并且把评论列表样式修改一下(我们这里只是把姓名,内容,时间显示出来,这里完全可以抽取成一个组件)

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

modify_commentform.png

从图中可以看到,我们只是修改黄色部分即可。

看一下效果:

weibo_commentlist.png

我们可以看到评论列表样式我们修改完成了。

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

我们再运行一下,就会看到我们开头的效果图

weibo-demo.gif

到此为止,我们手把手教大家撸了一个微博的小 Demo,经过这个 demo 大家掌握 webpack+yarn+react的基础知识,以及组件化的思想,无状态化组件编写等。希望大家能从 0 开始动手写一遍。

Demo地址

https://github.com/tigerchain/react-lesson/tree/master/lesson02/10-weibodemo

如果觉得对你有用,就点个喜欢吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 PS:转载请注明出处作者:TigerChain地址:http...
    TigerChain阅读 2,558评论 9 14
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,655评论 7 110
  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,125评论 7 35
  • 最近在学习 Webpack,网上大多数入门教程都是基于 Webpack 1.x 版本的,我学习 Webpack 的...
    My_Oh_My阅读 8,150评论 40 247
  • 像虫子咬着指尖 心里隐隐作痛 指头来回揉搓 有点失落 鸟儿叫 天儿明 心儿堵的慌 雨过天晴 总是难逃心里的结
    田萍阅读 312评论 1 6