有时,人们可能想要使用prop来设置一个只能通过JS设置的元素属性(因此,通过React无法控制)。
一个示例(和我的用例)使用paused
属性来定义视频是否应该播放(我的目标是分离控件和视频的可视化)。
以下是我目前的(简化)实施:
class Video extends Component {
constructor() {
super();
this.videoElRef = this.videoElRef.bind(this);
}
// Called when the video element is mounted.
videoElRef(ref) {
this.videoEl = ref;
if (this.videoEl) {
this.updateVideoProp();
}
}
// Update JS only property from the Component props.
updateVideoProp() {
const { paused } = this.props;
const videoEl = this.videoEl;
// Pause or play the video depending on the `paused` property.
if (paused && !videoEl.paused) {
videoEl.pause();
} else if (!paused && videoEl.paused) {
videoEl.play();
}
}
render() {
if (this.videoEl) {
this.updateVideoProp();
}
return (
<video ref={this.videoElRef}>
{ this.props.children }
</video>
);
}
}
const Component = React.Component;
class Video extends Component {
constructor() {
super();
this.videoElRef = this.videoElRef.bind(this);
}
// Called when the video element is mounted.
videoElRef(ref) {
this.videoEl = ref;
if (this.videoEl) {
this.updateVideoProp();
}
}
// Update JS only property from the Component props.
updateVideoProp() {
const { paused } = this.props;
const videoEl = this.videoEl;
// Pause or play the video depending on the `paused` property.
if (paused && !videoEl.paused) {
videoEl.pause();
} else if (!paused && videoEl.paused) {
videoEl.play();
}
}
render() {
if (this.videoEl) {
this.updateVideoProp();
}
return (
<video ref={this.videoElRef}>
{ this.props.children }
</video>
);
}
}
class App extends Component {
constructor() {
super();
this.state = { paused: true };
this.onClick = this.onClick.bind(this);
}
onClick(){
this.setState(state => ({ ...state, paused: !this.state.paused }));
}
render() {
return (
<div id="app">
<Video paused={this.state.paused}>
<source
src="http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_480p_h264.mov"
type="video/mp4"
/>
</Video>
<p><button onClick={this.onClick}>{this.state.paused?'play':'pause'}</button></p>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
video {
max-height: 80%;
max-width: 80%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
工作正常。但是,我发现它非常hacky。例如。修改paused
属性实际上并不需要重新呈现组件,并且updateVideoProp
方法被称为render
触发器的副作用。
我找不到合适的模式来实现这一目标。还有更好的办法吗?
答案 0 :(得分:1)
我认为updateVideoProp
方法的内容实际上属于componentDidUpdate
方法,或者如果要在调用render之前更改属性,请使用componentWillRecieveProps
方法。