如何做到可扩展的组件。
来源:6-8 扩展作业 - 轮播图组件设计
慕斯6088333
2019-06-12
老师,您好,
我完成了轮播图的组件。本来是想要children来实现更加可扩展性的轮播图组件。但是我碰到了一些问题。比如说子组件要调用父组件的方法以及state(比如item.index是否与state中currentItemIndex相同。但是在React.children.map中,我去访问这些组件内容。我尝试了用了挺多种方法。 但是结果都是一些东西undefine啊什么的。。 比如这里的方法 https://codepen.io/Yuschick/post/react-passing-state-to-props-children-in-jsx。我看完了试了一下,并不是特别好用。
不知道老师是否能够提供一些 方式去解决它呢。
另外一点就是访问本地资源的问题。。 比如我现在的程序只是去访问src 底下的 img文件夹中的文件。倘若我们去访问其它路径的文件夹,该如何解析呢。。我尝试着把文件放到其它地方。 然后用require()去获取,得到Error:Cannot find module。。。。(比如以后可能增加用户模块上传自定义轮播图之类的。如果是用springboot搭建,可能存在target文件下)
还有就是像轮播图按钮这种的大小。最好能做成responsive design 。 不过在react.js中去改变css的样式。我感觉还挺麻烦的。
Carousels component (没写太多注释,还请见谅)
import React from 'react';
import {MOVE_PRE, MOVE_NEXT} from '../utilities/PriceUtility'
/**
* props: height, width,totalImages
* isAutoChange: true,intervalTime: 2000,
* onMouseEnter onMouseLeave
*/
export class Carousels extends React.Component{
constructor(props){
super(props)
this.state = {
currentImgIndex: 0,
intervalTime: 3000,
isAutoChange: true,
}
}
/**
* Will Call after construction if we allow auto-changable Carousels
* Set interval change state every 2 second.
*/
componentDidMount() {
if (this.props.isAutoChange){
this.timer = setInterval(this.changeAutoDisplayImgIndex, this.state.intervalTime)
}
}
/**
* Auto change items by the timer
*/
changeAutoDisplayImgIndex = ()=>{
let imgIdx = this.state.currentImgIndex
let totalItems = this.props.totalItems
this.setState({
currentImgIndex: imgIdx === totalItems - 1 ? 0 : imgIdx + 1
})
}
/**
* change items by clicking left/right button
*/
handleButtonChange = (event,moveType) =>{
event.preventDefault()
//stop timer
clearInterval(this.timer)
let imgIdx = this.state.currentImgIndex
let totalItems = this.props.totalItems
if (moveType === MOVE_PRE){
this.setState({
currentImgIndex: imgIdx === 0 ? totalItems - 1: imgIdx - 1,
})
} else if (moveType === MOVE_NEXT){
this.setState({
currentImgIndex: imgIdx === totalItems - 1 ? 0 : imgIdx + 1,
})
}
// restart timer
this.timer = setInterval(this.changeAutoDisplayImgIndex, this.state.intervalTime)
}
/**
* change items by clicking points underware
*/
handlePointsChange = (event,index) => {
event.preventDefault()
//stop timer
clearInterval(this.timer)
this.setState({
currentImgIndex: index,
})
// restart timer
this.timer = setInterval(this.changeAutoDisplayImgIndex, this.state.intervalTime)
}
/**
* Mouse Enter: stop timer
*/
handleMouseEnter = (event) =>{
event.preventDefault()
//stop timer
clearInterval(this.timer)
}
/**
* Mouse Enter: start timer
*/
handleMouseLeave = (event) => {
event.preventDefault()
// restart timer
this.timer = setInterval(this.changeAutoDisplayImgIndex, this.state.intervalTime)
}
componentWillUnmount(){
//stop timer
clearInterval(this.timer)
}
render(){
const { height, width, items} = this.props
const { currentImgIndex} = this.state
const displayItem = items[currentImgIndex]
console.log(displayItem)
/**
* CSS styles
*/
const frameStyle = {
width: width,
height: height,
whiteSpace: 'nowrap',
overflow: 'hidden',
position: 'relative',
margin: '100px auto'
};
const imageRowStyle = {
width: '100%',
height: '100%',
};
const buttonStyle = {
position: 'absolute',
top: '40%',
bottom: '40%',
width: '10%',
background: 'rgba(0,0,0,0.5)',
outline: 'none',
color: '#fff',
border: 'none',
fontSize: '50px'
};
const leftButtonStyle = {
...buttonStyle,
left: '0'
}
const rightButtonStyle = {
...buttonStyle,
right: '0'
}
const pointsStyle = {
position: 'absolute',
left: '50%',
bottom: '10%'
}
return(
<div className = "carousel-component" style={frameStyle}>
<button onClick={(event) => this.handleButtonChange(event, MOVE_PRE)} style={leftButtonStyle}>
<
</button>
<img className='carousel-component-child' style={imageRowStyle}
onMouseEnter={(event) => this.handleMouseEnter(event)}
onMouseLeave={(event) => this.handleMouseLeave(event)}
src={displayItem.address} alt="#">
</img>
<button onClick={(event) => this.handleButtonChange(event, MOVE_NEXT)} style={rightButtonStyle}>
>
</button>
<div className ="pointsTab" style = {pointsStyle}>
{this.props.items.map((item,index) => {
const pointStyle = {
display: "inline-block",
width: "15px",
height: "15px",
margin: "15px",
borderRadius: "50%",
}
const generatePointColor = (index)=>{
return index === this.state.currentImgIndex ?
{ ...pointStyle, background: '#3333FF'} : { ...pointStyle,background: '#fff'}
}
return(
<button key = {index} style={generatePointColor(index)}
onClick={(event) => { this.handlePointsChange(event, index)}}></button>
)
})}
</div>
</div>
)
}
}
/**
* 注释掉的失败方法
*
export const Carousel = ({ children }) => {
return <React.Fragment>{children}</React.Fragment>
}
*/
/**
失败的方法:
const childWithProp = React.Children.map(children, (child) => {
return React.cloneElement(child,
{
handleButtonChange: this.handleButtonChange,
handleMouseEnter: this.handleMouseEnter,
handleMouseLeave: this.handleMouseLeave,
currentImgIndex: currentImgIndex,
handlePointsChange: this.handlePointsChange,
});
});
* props that child component needed
*/
常量相关
export const images = [
{
'address': require('../img/user_03_carousel_01.jpg'),
},
{
'address': require('../img/user_03_carousel_02.jpg'),
},
{
'address': require('../img/user_03_carousel_03.jpg'),
}
]
export const MOVE_PRE = 'pre';
export const MOVE_NEXT = 'next';
调用
<Carousels height={720} width={'100%'} totalItems={images.length} items= {images}></Carousels>`
写回答
1回答
-
张轩
2019-06-12
谢谢你认真做作业的态度,问题较多,我会在周末比较空闲的时候写。?
112019-06-13
相似问题