我可以通过数组映射并渲染一些图像(在generateWord函数的底部附近)。我希望能够点击图像,然后播放相关的音频文件。它播放阵列中的第二个(或最后一个)音频文件。我想我应该将某种键或索引附加到音频文件中,以便它知道要播放哪一个,但我不确定如何准确。下面的代码是组件。部分状态在它下面注释,因此您可以看到映射数组的来源。
const debug = require("debug")("components:Displayletter")
const React = require("react")
const { connect } = require("react-redux")
const request = require("superagent")
const { Link } = require("react-router")
class Displayletter extends React.Component {
constructor() {
super()
this.playSound = this.playSound.bind(this)
}
playSound() {
this.playWord.play()
}
handleClick(e) {
e.preventDefault()
this.props.router.push("/")
}
render() {
debug(this.props)
const { dispatch, letters, letter } = this.props
const wordsArr = letter.wordImage
return (
<div className="row letter-container">
<div className="col-sm-12">
{this.generateWord(wordsArr)}
</div>
</div>
)
}
generateWord(wordsArr) {
return wordsArr.map((word) => {
return (
<div>
<audio
key={word.sound}
ref={(x) => { this.playWord = x; }}>
<source src={word.sound} preload='auto'/>
</audio>
<img src={word.image} onClick={this.playSound} />
</div>
)
})
}
}
module.exports = connect(state => state)(Displayletter)
//STATE
// letters: [
// {
// id: 1,
// capital: "A",
// lowercase: "a",
// capitalSound: "/sounds/capitalSounds/A.mp3",
// lowerSound: "/sounds/lowerSounds/a.mp3",
// wordImage: [
// {id:1, image:"images/words/aniwaniwa.png", sound: "sounds/ua.mp3"},
// {id:2, image:"images/words/anuhe.png", sound: "sounds/anuhe.mp3"},
// ],
// multimedia: "/multimedia/aniwaniwa.webm",
// mediaName: "Aniwaniwa Song",
// },
第二次迭代 - 在构造函数中添加了一个空对象,并通过onClick和playSound传递了一个'word'参数。
generateWord(wordsArr) {
return wordsArr.map((word) => {
return (
<div>
<audio
key={word}
ref={(x) => { this.playWords[word] = x; }}>
<source src={word.sound} preload='auto'/>
</audio>
<img src={word.image} onClick={this.playSound.bind(this, word)} />
</div>
)
})
playSound(word) {
this.playWords[word].play()
}
constructor() {
super()
this.playCapital = this.playCapital.bind(this)
this.playLower = this.playLower.bind(this)
this.playSound = this.playSound.bind(this)
this.playWords = {}
}
***************第三轮*******************
const debug = require("debug")("components:Displayletter")
const React = require("react")
const { connect } = require("react-redux")
const request = require("superagent")
const { Link } = require("react-router")
class Displayletter extends React.Component {
constructor() {
super()
this.playCapital = this.playCapital.bind(this)
this.playLower = this.playLower.bind(this)
this.playWords = {}
}
playCapital() {
this.playCap.play()
}
playLower() {
this.playLow.play()
}
playSound(word) {
this.playWords[word].play()
}
handleClick(e) {
e.preventDefault()
this.props.router.push("/")
}
render() {
debug(this.props)
const { dispatch, letters, letter } = this.props
const wordsArr = letter.wordImage
return (
<div className="row letter-container">
<div className="col-sm-12">
<audio
key={letter.capitalSound}
ref={(cap) => { this.playCap = cap; }}>
<source
src={letter.capitalSound}
preload="auto" />
<track
kind="captions"
src=""
srcLang="en" />
</audio>
<audio
key={letter.lowerSound}
ref={(low) => { this.playLow = low; }}>
<source
src={letter.lowerSound}
preload="auto" />
<track
kind="captions"
src=""
srcLang="en" />
</audio>
<button
type="button"
className="btn btn-xl display"
onClick={this.playCapital}>
{letter.capital}
</button>
<button
type="button"
className="btn btn-xl display"
onClick={this.playLower}>
{letter.lowercase}
</button>
</div>
<div className="col-sm-12">
{this.generateWord(wordsArr)}
</div>
<div className="col-sm-12">
<Link key={letter.id} to={`/media/${letter.capital}`}>
<button
type="button"
className="btn"
onClick={() =>
dispatch({
type: "RENDER_LETTER",
payload: letter,
})
}>
Watch: {letter.mediaName}
</button>
</Link>
</div>
</div>
)
}
generateWord(wordsArr) {
return wordsArr.map((word) => {
return (
<div>
<audio
key={word}
ref={(x) => { this.playWords[word] = x; }}>
<source src={word.sound} preload='auto'/>
</audio>
<img src={word.image} onClick={this.playSound.bind(this, word)} />
</div>
)
})
}
}
module.exports = connect(state => state)(Displayletter)
// letters: [
// {
// id: 1,
// capital: "A",
// lowercase: "a",
// capitalSound: "/sounds/capitalSounds/A.mp3",
// lowerSound: "/sounds/lowerSounds/a.mp3",
// wordImage: [
// {id:1, image:"images/words/aniwaniwa.png", sound: "sounds/ua.mp3"},
// {id:2, image:"images/words/anuhe.png", sound: "sounds/anuhe.mp3"},
// ],
// multimedia: "/multimedia/aniwaniwa.webm",
// mediaName: "Aniwaniwa Song",
// },
答案 0 :(得分:2)
你真的很亲密!问题在于如何保存对音频元素的引用:ref={(x) => { this.playWord = x; }}
。请注意,因为它位于map
内,每个元素都会一个接一个地保存,this.playWord
,因此当您单击时只会播放最后一个文件
您要做的是将所有单词保存到对象或数组,然后在您的单击处理程序中引用您想要播放的单词。
首先,在构造函数中执行类似this.playWords = {}
的操作,然后在ref={(x) => { this.playWords[word] = x; }}
中执行render
。这将为您提供一个对象playWords
,用于存储对按字键控的所有音频元素的引用。
然后,给playSound
一个单词参数,并确保onClick通过绑定它来传递该参数,如onClick={this.playSound.bind(this, word)}
。
我汇总了一个简单的例子来证明基本结构;您应该能够轻松地将这些原则应用于您的组件。
class Example extends React.Component {
constructor() {
super();
this.words = {};
}
logClick(i) {
console.log("user clicked on", this.words[i]);
}
render() {
const wordsArr = "this is an example sentence".split(" ");
return (
<div className="row letter-container">
<div className="col-sm-12">
{this.generateWord(wordsArr)}
</div>
</div>
)
}
generateWord(wordsArr) {
return wordsArr.map((word) => {
return (
<div>
<span
key={word}
ref={x => { this.words[word] = x; }}
onClick={this.logClick.bind(this, word)}
>
{word}
</span>
</div>
);
})
}
}
ReactDOM.render(<Example />, document.getElementById("container"));
<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="container"/>