React组件Component

1.轮播图Banner组件

banner.js

// Carousel component
import React, { Component } from 'react';
import { Toast, Modal } from 'antd-mobile';
import './banner.less'
export default class Carousel extends Component {
  constructor(props) {
    super(props);
    this.state = { currentIndex: 0,};
    this.renderChildren = this.renderChildren.bind(this);
    this.setIndex = this.setIndex.bind(this);
  }
  renderChildren() {
    const { children,width, height } = this.props;
    const childStyle = {
      width: width,
      height: height
    };
    return React.Children.map(children, child => {
      const childClone = React.cloneElement(child, { style: childStyle });
      return (
        <div
          style={{
            display: 'inline-block'
          }}
        >
          {childClone}
        </div>
       
      );
    });
  }
  setIndex(index) {
    const len = this.props.children.length;
    console.log("length"+len);
    const nextIndex = (index + len) % len;
    this.setState({ currentIndex: nextIndex,});
  }
  

    handleTouchStart = (e) => {
        this.startX = e.touches[0].clientX;
    }
    handleTouchMove = (e) => {
        this.endX = e.touches[0].clientX;
    }
    handleTouchEnd = (e) => {
        let distance = Math.abs(this.startX - this.endX);
        let currentIndex = this.state.currentIndex;
        if (distance > 50) {
            if (this.startX > this.endX) {
                this.setIndex(currentIndex - 1)
            } else {
                this.setIndex(currentIndex + 1)
            }
        }
    }
  render() {
    const { width, height } = this.props;
    const { currentIndex } = this.state;

    const offset = -currentIndex * width;

    const frameStyle = {
      width: width,
      height: height,
      whiteSpace: 'nowrap',
      overflow: 'hidden',
         
    };

    const imageRowStyle = {
      marginLeft: offset,
      transition: '.2s',
      background: 'red',
    };
    return (
      <div className="carousel">
        <div className="frame" style={frameStyle}>
          <div
           onTouchStart={this.handleTouchStart}
           onTouchMove={this.handleTouchMove}
           onTouchEnd={this.handleTouchEnd}
        //    onClick={() => this.setIndex(currentIndex + 1)}
           style={imageRowStyle}>{this.renderChildren()}
           
           </div>
        </div>
        <div className="tag">
                <p>{this.state.currentIndex+1}/{this.props.children.length}</p>
        </div>
      </div>
    );
  }
}

banner.less

.carousel {
    position: relative;
}
.tag {
    position: absolute;
    width:4.44rem;
    height:2.5rem;
    background:rgba(0,0,0,1);
    border-radius:1.25rem;
    opacity:0.7;
    justify-content: center;
    right: 0.63rem;
    bottom: 0.63rem;
    p{
        margin-top: 0.56rem;
        font-size: 1.25rem;
        line-height: 1.25rem;
        text-align: center;
        color: #ffffff;
    }
}

用法

//轮播
import Carousel from '../../components/groupbuy/banner'
let imgs = [img1,img2,img3];
    this.setState({
        images: imgs,
    })
 <Carousel width={width} height={'18.75rem'} imageCount={images.length}>
     {images.map(image => <img src={image} alt="" key={image}/>)}
 </Carousel>
 //注意:width 参与计算必须是数字,不能是rem单位,否则无法滑动:Example :width = 400

效果图:

4637097-70ff0090c4a1ef71.gif
轮播图.gif

2.拼团倒计时组件

1.countdown.js

import React, { Component } from 'react';
import './countDown.less'

class NoTimeContent extends Component {
    constructor(props) {
        super(props)
        this.state = {
            timeStamp:'',
            day: 0,
            hour: 0,
            minute: 0,
            second: 0
        }
    }
    render() {
        return (
                <h2>
                    <span>
                        <span className="timeItem">
                          {this.state.day}
                        </span>
                        &nbsp;:
                        <span  className="timeItem">
                        {this.state.hour}
                        </span>
                        &nbsp;:
                        <span  className="timeItem">
                        {this.state.minute}
                        </span >
                        &nbsp;.&nbsp;
                        <span className="timeItem">
                         {this.state.second}
                        </span>
                        &nbsp;
                        <span className="final">后结束</span></span>
                </h2>
        )
    }

    componentDidMount() {
        //console.log("时间戳"+this.props.timeStamp);
        let time = this.props.timeStamp;
      const end = Date.parse(new Date(time))
      this.countFun(end);
    }
  
  //卸载组件取消倒计时
  componentWillUnmount(){
    clearInterval(this.timer);
  }
  
  countFun = (end) => {

    let now_time = Date.parse(new Date());
    var remaining = end - now_time;
 
    this.timer = setInterval(() => {
        //防止出现负数
      if (remaining > 1000) {
        remaining -= 1000;
        let day = Math.floor((remaining / 1000 / 3600) / 24);
        let hour = Math.floor((remaining / 1000 / 3600) % 24);
        let minute = Math.floor((remaining / 1000 / 60) % 60);
        let second = Math.floor(remaining / 1000 % 60);

        this.setState({
            day:"0" + day,
            hour:hour < 10 ? "0" + hour : hour,
            minute:minute < 10 ? "0" + minute : minute,
            second:second < 10 ? "0" + second : second
        })
      } else {
        clearInterval(this.timer);
        //倒计时结束时触发父组件的方法
        //this.props.timeEnd();
      }
    }, 1000);
  }
}
export default NoTimeContent;

2.countDown.less

h2 {
    font-size: 0.88rem;
    color: #FF1634;
    .timeItem {
        padding: 0.16rem;
        width: 1.5rem;
        height: 1rem;
        background-color: #FF1634;
        font-size: 0.88rem;
        color: #FFFFFF;
        border-radius: 0.25rem;
    }
    .final {
        font-size: 1rem;
        color: #515151;
    }
}

3.用法

定义一个时间戳字符串,前提大于当前时间

time: '2019-5-29 24:00'

<NoTimeContent timeStamp={time}></NoTimeContent>

效果图

4637097-d01481a04f0ed7bf.gif
倒计时.gif

3.自定义Modal弹出框

ServiceDescriptionModal.js

import React, {Component} from 'react';
import './ServiceDescriptionModal.less'
import ReactDOM from 'react-dom';
import closeImg from '../../images/groupbuy/groupbuy_productDetail_closeBtn.png'
 
const styles = {
    mask: {
        position: 'fixed',
        top: 0,
        right: 0,
        left: 0,
        bottom: 0,
        backgroundColor: 'rgba(0, 0, 0, 0.65)',
        height: '100%',
        zIndex: 1000,
    },
    modalWrap: {
        position: 'fixed',
        top: 0,
        right: 0,
        left: 0,
        bottom: 0,
        zIndex: 1000,
    },
    modal: {
        fontSize: 14,
        marginTop:'17.44rem',
        width: '23.44rem',
        height: '24.25rem',
        backgroundColor: '#fff',
        overflow: 'hidden',
        borderTopRightRadius:'1rem',
        borderTopLeftRadius:'1rem',
        textAlign: 'center',
        position: 'relative',
    },
   
};
 
export default class ServiceDescriptionMask extends Component {
    constructor (props) {
        super(props);
 
        this.modal = null;
    }
 
    componentDidMount () {
        this.modal = document.createElement('div');
        this.props.visible && document.body.appendChild(this.modal);
 
        this._renderLayer();
    }
 
    componentDidUpdate () {
        if (this.props.visible) {
            document.body.appendChild(this.modal);
            this._renderLayer();
        } else {
            this.modal.parentNode.removeChild(this.modal);
        }
    }
 
    onOk = () => {
        const { onOk } = this.props;
        (onOk instanceof Function) && onOk();
    }
 
    // 渲染模态框内容
    _renderLayer () {
        const {title, content} = this.props;
 
        let JSXdom = (
            <div>
                <div style={styles.mask} />
                <div style={styles.modalWrap} onClick={this.onOk}>
                    <div style={styles.modal}>
                        <h2>{"服务说明"}</h2>
                        <div className="closeImg" onClick={this.onOk}>
                          <img src={closeImg} alt='' />
                        </div>
                        <div className="serviceItems">
                            <div className="item">
                                  <div className="title">
                                      {"关于成团"}
                                  </div>
                                  <div className="desc">
                                      {"拼团时间内,未凑够人成团,已支付的费用将自动退回 "}
                                  </div>
                            </div>

                            <div className="item">
                                  <div className="title">
                                      {"关于退费"}
                                  </div>
                                  <div className="desc">
                                      {"拼团时间内,未凑够人成团,已支付的费用将自动退回 "}
                                  </div>
                            </div>

                            <div className="item">
                                  <div className="title">
                                      {"关于有效期"}
                                  </div>
                                  <div className="desc">
                                      {"购买商品或权益,一旦拼团成功,商品可永久收听,权益按购买时的说明使用 "}
                                  </div>
                            </div>

                            <div className="item">
                                  <div className="title">
                                      {"关于解释权"}
                                  </div>
                                  <div className="desc">
                                      {"呼呼收音机对本课程具有最终法律解释权 "}
                                  </div>
                            </div>

                        </div>
                    </div>
                </div>
            </div>
        );
 
        ReactDOM.render(JSXdom, this.modal);
    }
 
    render () {
        return null;
    }
}

2.ServiceDescriptionModal.less

h2 {
    margin-top: 1rem;
    color: #515151;
    font-size: 1.13rem;
}

.closeImg {
    position: absolute;
    top: 0.81rem;
    right: 0.63rem;
    img {
        width: 1.88rem;
        height: 1.88rem;
    }
}

.serviceItems {
    position: absolute;
    top: 2.36rem;
    width: 21.19rem;
    height: 19.25rem;
    margin: auto 1.13rem;
    //background-color: red;

    .item {
        margin-top: 1.4rem;
        line-height: 1.38rem;
        text-align: left;
        font-size: 1rem;
        .title {
            font-weight:bold;
        }
    }
}

3.使用

//服务说明Modal
import ServiceDescriptionMask from '../../components/groupbuy/ServiceDescriptionModal'

<div className="service"> 
  <ServiceDescriptionMask visible={visible} 
            onOk={this.onOk} />
</div>
onOk = () => {
      this.setState({
          visible: false
      })
  }
  onClick={this.showModal}
  showModal = () => {
      this.setState({
          visible: true
      })
  }

效果图

4637097-e7e2e1c0c29d7e84.gif
自定义Modal弹出框.gif

4.消息上下轮播(拼团)

MessageCarousel.js


import React, { Component } from 'react';
import { Carousel } from 'antd-mobile';
import './MessageCarousel.less'
//图片资源
import addBg from '../../images/groupbuy/3.jpg'

class MessageMarquee extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
    }
  }

  componentDidMount() {
    this.requestList();
  }

  requestList = () => {
    let temp = [{ id: "1", nickname: "Steven", robot: true }, { id: "2", nickname: "Lucy", robot: false }, { id: "3", nickname: "Benny", robot: true }];
    this.setState({
          data: temp
        })
  }

  render() {
    const { data } = this.state
    console.log("data" + data);
    return (
      data && data.length > 0 ?
      <div id="message-marquee">
          <img src={addBg} alt="" />
          <Carousel className="my-carousel"
            vertical
            dots={false}
            dragging={false}
            swiping={false}
            autoplay
            infinite
            autoplayInterval={1500}
          >
            {
              data.map((item, index) =>(
                <div className="v-item" key={index}
                style={{overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace:'nowrap'}}
                >{item.nickname  + ' '+ '1' + ' 小时前发起拼团'}</div>
              ))
            }
          </Carousel>
      </div>
       : ''
    )
  }
}
export default MessageMarquee;

MessageCarousel.css

#message-marquee {
  position: absolute;
  width:13.19rem;
  height:2.5rem;
  background:rgba(0,0,0,1);
  border-radius:0.38rem;
  opacity:0.7;
  left: 0.63rem;
  display: flex;
      img{
        float: left;
        margin-left: 0.44rem;
        margin-top: 0.44rem;
        background-color:lightgray;
        width: 1.63rem;
        height: 1.63rem;
        border-radius: 0.82rem;
      }
      .my-carousel{
        margin-left: -0.56em;
        padding:0 1rem;
        width: 11.25rem;
        //background: red;
        font-size: 0.8rem;
        text-align: left;
        color: #FFFFFF;
        line-height: 2.5rem;
        flex: 1;    
      }
      overflow: hidden;
}

使用

//消息轮播
import MessageMarquee from '../../components/groupbuy/MessageCarousel'
<div className="remindView">
    <MessageMarquee/>
</div>
//less
.remindView {
  position: absolute;
  width:12.19rem;
  height:2.5rem;
  top: 2.56rem;
}

效果图

4637097-10c59b00126b2e3b.gif
消息上下轮播-拼团.gif

5.消息上下轮播(常规)

1.marquee.js

import React, { Component } from 'react';
import { Carousel } from 'antd-mobile';
import { getMarquee } from '../../api/hcFission'

class Marquee extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
    }
  }

  componentDidMount() {
    this.requestList();
  }

  requestList = () => {
    getMarquee({}).then((res)=>{
      this.setState({
        data: res
      })
    })
  }

  render() {
    const { data } = this.state
    return (
      data && data.length > 0 ?
      <Carousel className="my-carousel"
        vertical
        dots={false}
        dragging={false}
        swiping={false}
        style= {{height: '2.19rem',background: '#5A19B5', fontSize:'1rem', color: '#FFFFFF', padding:'0 1rem', lineHeight: '2.19rem'}}
        autoplay
        infinite
        autoplayInterval={1500}
      >
        {
          data.map((item, index) =>(
            <div className="v-item" key={index}
            style={{overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace:'nowrap'}}
            >{'恭喜 ' + item.nickname + ':' + item.content}</div>
          ))
        }
      </Carousel> : ''
    )
  }
}
export default Marquee;

2.使用

//消息上下轮播常规
import Marquee from '../../components/HcFission/marquee'
//使用
<Marquee/>

效果图

4637097-9bb3ed8ea1e82e65.gif
消息上下轮播-常规.gif

转载于:https://www.jianshu.com/p/9eab07f72658

猜你喜欢

转载自blog.csdn.net/weixin_33781606/article/details/91058959