1. 程式人生 > >react元件開發

react元件開發

本文分享一個react動畫元件開發過程。以一個從底部彈出的彈框為例:
這裡寫圖片描述
類似於actionSheet一樣的從底部彈出的彈框。

思路

1、點選按鈕底部彈出彈框
2、同時遮罩背景顯示
3、點選遮罩背景時彈框向下彈出去,背景消失。
一、背景遮罩實現
考慮到遮罩在多個地方使用,故封裝成元件。結合redux開發,程式碼如下:

//app.js 在全域性app中引入mask元件,全域性可用
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Header from './components/Header'
import Footer from './containers/Footer' import Find from './components/Find' import Slidebar from './components/Slidebar' import PlayList from './containers/PlayList' import Mask from './containers/Mask' class App extends Component { render() { return ( <div> <div className='header-div'
> <Header pathName={this.props.location.pathname} /> </div> <Footer /> <Slidebar /> <PlayList /> <Mask/> </div> ); } } export default App;
//containers目錄下的mask元件容器。負責與redux建立連線
import { connect } from 'react-redux'
import Mask from '../components/Mask' //將state對映成元件的props const mapStateToProps = (state, ownProps) => ({ isShowPop:state.showPopReducer.isShowPop }) export default connect(mapStateToProps)(Mask)
components下的mask 負責ui顯示
import React, {Component} from 'react'
import {showPop} from '../actions/popAction'

export default class Mask extends Component {
    statusName = 'fade-enter'
    render() {
        return (
            <div
                ref='maskDiv'
                className = {this.props.isShowPop?'':''}
                onClick={e=> this.clickHandle(e)}></div>
        )
    }

    componentDidMount() {
        this.refs.maskDiv.className = 'mask fade-enter';
    }

    componentWillUpdate(nextProps, nextState) {
        if(nextProps.isShowPop){
            this.refs.maskDiv.className = 'mask fade-enter-active'
        }else{
            this.refs.maskDiv.className = 'mask fade-leave-active'
        }
        setTimeout(()=>{
            if(nextProps.isShowPop){
                //this.refs.maskDiv.className = 'mask fade-enter';
            }else{
                this.refs.maskDiv.className = 'mask fade-leave';
            }
        },600)
    }

    clickHandle(e) {

        const {dispatch} = this.props;
        //分發action ,表示離場
        dispatch(showPop(false))
    }

}
//遮罩樣式
.mask{
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  content: '';
  background: rgba(0,0,0,.5);
  z-index:10001;
}
//遮罩進場離場過度動畫
.fade-enter-active {
  z-index: 10001!important;
  opacity: 1;
  transition: opacity 600ms ease-in;
}
.fade-enter ,.fade-leave {
  z-index: -1!important;
  opacity: 0;
}

.fade-leave-active {
  z-index: 10001!important;
  opacity: 0;
  transition: opacity 600ms ease-in;
}
//popAction.js
import * as actionTypes from '../constants/constant'

export  function showPlayListAction(isShow){
  return{
    type:actionTypes.SHOW_PLAYLIST_POP,
    isShow
  }
}
function startAnimate(startAnimate){
  return{
    type:actionTypes.SHOW_POP,
    startAnimate
  }
}
export function showPop(showPop){
//使用這種分發方式參考非同步資料流action分發 ,需要引用中介軟體redux-thunk,可參考官網例子
  return (dispatch,getState) =>{
    if(showPop){
      dispatch(showPlayListAction(showPop))
      dispatch(startAnimate(showPop));
    }else{
      dispatch(startAnimate(showPop));
      dispatch(showPlayListAction(showPop));
      // setTimeout(() => {
      //   dispatch(showPlayListAction(showPop))
      // }, 600);
    }

  }
}

彈框元件開發

//animation.js  動畫包裹元件
import React, { Component } from 'react'

export default class Animation extends Component {
  render(slot,isShow,name) {
    return (
      <div className={isShow?'animation '+name+'-enter-active':'animation '+name+'-leave-active'}>
          {slot}
      </div>
    )
  }

  componentWillUpdate(nextProps, nextState) {
    console.log(nextProps, nextState)
  }

}
//要執行動畫的子元件。
import React, {Component} from 'react'
import {fetchMusicData} from '../actions/musicDataAction'
import {showPop} from '../actions/popAction'
import Animation from './Animation'
import {selectSong} from '../actions/playMusicAction'
export default class PlayList extends Animation {
  constructor(props) {
    super(props)
    this.state = {
      isShow: false
    }
  }
  render() {
    //return (
    return super.render(
      <div className='play-list-wraper' onClick={e => this.clickHandle(e)}>
      <div
        className={this.props.isShowPop
        ? 'play-list '
        : 'play-list '}>
        <div className='header-bar'>
          <div className='play-type'>
            <i className='icon icon-music-random'/>
            <span>{'列表迴圈'}({33})</span>
          </div>
          <div className='op-div'>
            <label>
              <i className='icon-add-project'/>
              <span>收藏</span>
            </label>
            <label>
              <i className='icon-delete'/>
              <span>清空</span>
            </label>
          </div>
        </div>
        <div className='play-content'>
          {this
            .props
            .tracks
            .map((item, index) => <div key={index} onClick={e=> this.playSong(e,item.hash)} className='music-item'>
              <div className='music-name'>
                <label>{item.filename}</label>
                <span></span>
              </div>
              <div className='music-name'></div>
            </div>)}

        </div>
      </div>
    </div>, this.props.isShowPop, 'slide')
  }
  clickHandle(e) {
    if (e.target.className.indexOf('play-list-wraper') !== -1) {
      const {dispatch} = this.props;
      dispatch(showPop(false))
    }

  }
  playSong(e,index){
    const {dispatch} = this.props;
    dispatch(selectSong(index));
  }
  componentWillMount() {
    const {dispatch} = this.props;
    dispatch(fetchMusicData());
  }
}
//動畫css
.animation{
  position: fixed;
  z-index: 10002;
  width: 100%;
  bottom: 0;
  transform: translate3d(0,100%,0)
}
.slide-enter-active{
  transition: transform 0.6s;
  transform:translate3d(0,0,0)!important;
}
.slide-leave-active{
  transition: transform 0.6s;
  transform:translate3d(0,100%,0)!important;
}

上述只是部分程式碼,還有結合redux的使用的程式碼沒貼出,完整程式碼請檢視react仿網易雲音樂