美文网首页Web前端之路让前端飞技术干货
13、React系列之--微博Demo 02 终结篇

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

作者: TigerChain | 来源:发表于2017-03-30 12:52 被阅读432次

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

    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/githubchen001/react-lesson/tree/master/lesson02/10-weibodemo

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

    相关文章

      网友评论

        本文标题:13、React系列之--微博Demo 02 终结篇

        本文链接:https://www.haomeiwen.com/subject/lmiuottx.html