react元件開發
阿新 • • 發佈:2019-01-31
本文分享一個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仿網易雲音樂