单击新的div时禁用其他div的样式

时间:2019-05-24 13:31:34

标签: javascript reactjs

我正在构建“音乐机器”,但是我遇到了无法解决的问题。音乐机的所有其他部分都能正常工作。只有我想要,如果您单击(或按相应的键)新的音乐垫,最后一个“取消激活”其样式。等等,只有当前正在播放的声音具有活动板。

我已经尝试过这个和其他几个例子。

document.addEventListener("pause", function(){
      var audioDiv = document.getElementsByClassName("clip");
      for (var i = 0, len = audioDiv.length; i < len; i++) {
        audioDiv[i].style.backgroundColor = "Grey";
        audioDiv[i].style.margin = "50px"
        }
    }, true)

这是代码的SoundPad部分

class SoundPad extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      padStyle: inactiveStyle,
      toPlay: true,
    };
    this.playSound = this.playSound.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
    this.padControl = this.padControl.bind(this);
    this.stopOther = this.stopOther.bind(this)
  }
  componentDidMount() {
    document.addEventListener("keydown", this.handleKeyPress);
    document.addEventListener("play", this.stopOther, true);
    document.addEventListener("pause", function(){
      var audioDiv = document.getElementsByClassName("clip");
      for (var i = 0, len = audioDiv.length; i < len; i++) {
        audioDiv[i].style.backgroundColor = "Grey";
        audioDiv[i].style.margin = "50px"
        }
    }, true)
  }
  componentWillUnmount() {
    document.removeEventListener("keydown", this.handleKeyPress);
    document.removeEventListener("play", this.stopOther, true);
    document.removeEventListener("pause", function(){
      var audioDiv = document.getElementsByClassName("clip");
      for (var i = 0, len = audioDiv.length; i < len; i++) {
        audioDiv[i].style.backgroundColor = "Grey";
        audioDiv[i].style.margin = "50px"
        }
    }, true)
  }

  handleKeyPress(e) {
    if (e.keyCode === this.props.keyCode) {
      this.playSound();
    }
  }

  playSound(e) {
    if (this.state.toPlay) {
      const sound = document.getElementById(this.props.keyTrigger);
      sound.currentTime = 0;
      sound.play();
      this.padControl();
      this.props.changeDisplay(this.props.clipName);
    } else {
      const sound = document.getElementById(this.props.keyTrigger);
      sound.currentTime = 0;
      sound.pause();
      this.padControl();
      this.props.changeDisplay(String.fromCharCode(160));
    }
  }

  padControl() {
    this.state.toPlay
      ? this.setState({
          padStyle: activeStyle,
          toPlay: !this.state.toPlay
        })
      : this.setState({
          padStyle: inactiveStyle,
          toPlay: !this.state.toPlay
        });
  }

  stopOther(e) {
        var audios = document.getElementsByClassName("clip");
        for (var i = 0, len = audios.length; i < len; i++) {
          if (audios[i] != e.target) {
            audios[i].pause();
          } 
        }
      }

  render() {
    return (
      <div
        className="drum-pad"
        id={this.props.clipId}
        onClick={this.playSound}
        style={this.state.padStyle}
      >
        <audio
          className="clip"
          id={this.props.keyTrigger}
          src={this.props.clip}
        />
        {this.props.keyTrigger}
      </div>
    );
  }
}
const inactiveStyle = {
  backgroundColor: "Grey",
  margin: "50px"
};

const activeStyle = {
  backgroundColor: "Blue",
  margin: "40px"
};

完整代码:https://codepen.io/mathiascoding/pen/GaZxgr?editors=1010

如果解决方案使用JS而不是JQuery,将不胜感激

3 个答案:

答案 0 :(得分:1)

我用您要查找的逻辑编写了一个简单的代码段:

for (var el of document.getElementsByClassName('box')) {
  el.addEventListener('click', (e) => {
    var activeEl = document.getElementsByClassName('active')[0]
    if (activeEl) activeEl.classList.remove('active')
    e.target.classList.add('active')
  })
}
.box {
  background-color: grey;
  border: 1px solid black;
  height: 20px;
  width: 20px;
}

.active {
  background-color: blue
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>

在每次单击按钮时,您要查找具有active类的所有元素并将其删除,然后将active类应用于刚刚单击的元素。从技术上讲,您可以使用样式来实现此目的,但是类的使用要容易得多。

编辑:浏览完代码笔后,此代码应该可以正常工作:

const inactiveStyle = {
  backgroundColor: "Grey",
  margin: "50px"
};

const activeStyle = {
  backgroundColor: "Blue",
  margin: "40px"
};

document.addEventListener('click', (e) => {
  // If the element clicked has the class drum-pad
  if (e.target.classList.contains('drum-pad')) {
    // then get all the elements with the class drum-pad
    var drumPads = document.getElementsByClassName('drum-pad')
    // For each drum-pad
    for (var drumPad of drumPads) {
      // Loop over the keys in inactiveStyle
      Object.keys(inactiveStyle).map(key => {
        // and apply it to the element
        drumPad.style[key] = inactiveStyle[key]
      })
    }
    // Then loop over the keys in active style
    Object.keys(activeStyle).map(key => {
      // and apply it to the click element
      e.target.style[key] = activeStyle[key]
    })
  }

})
<div id="Music-Bank">
  <!-- react-text: 11 -->
  <!-- /react-text -->
  <div class="drum-pad" id="Pair-Of-Dice" style="background-color: blue; margin: 40px;"><audio class="clip" id="Q" src="https://dl.dropbox.com/s/u32apb7wl4z0abr/Ti%C3%ABsto%20%20Allure%20-%20Pair%20Of%20Dice%20%28Radio%20Edit%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 14 -->Q
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Speechless" style="background-color: blue; margin: 40px;"><audio class="clip" id="W" src="https://dl.dropbox.com/s/rirdacgv842n19z/Robin%20Schulz%20feat.%20Erika%20Sirola%20-%20Speechless%20%28Lyrics%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 17 -->W
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Sunset-Love" style="background-color: blue; margin: 40px;"><audio class="clip" id="E" src="https://dl.dropbox.com/s/ncv727qclyg0e5l/PETIT%20BISCUIT%20-%20Sunset%20Lover.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 20 -->E
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Lets-Go-Home" style="background-color: blue; margin: 40px;"><audio class="clip" id="A" src="https://dl.dropbox.com/s/nixax61siercuzm/Eklo%20-%20Lets%20Go%20Home%20%28Sinco%20Remix%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 23 -->A
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Are-You-With-Me" style="background-color: blue; margin: 40px;"><audio class="clip" id="S" src="https://dl.dropbox.com/s/9hruu7ag6nk5e49/Lost%20Frequencies%20-%20Are%20You%20With%20Me%20%28Kungs%20Remix%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 26 -->S
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Fallen" style="background-color: blue; margin: 40px;"><audio class="clip" id="D" src="https://dl.dropbox.com/s/8np1rhnfutwyimw/KLYMVX%20feat.%20COZY%20-%20Fallen%20%28Kygo%20Rework%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 29 -->D
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Swing" style="background-color: blue; margin: 40px;"><audio class="clip" id="Z" src="https://dl.dropbox.com/s/4c2ypp31ofdjbjl/Danny%20Ocean%20-%20Swing%20%28Letra%20%20Lyrics%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 32 -->Z
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Otro Trago" style="background-color: blue; margin: 40px;"><audio class="clip" id="X" src="https://dl.dropbox.com/s/vu8u5qntv9qhfzf/Sech%20%20Darell%20-%20%20Otro%20Trago%28LETRA%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 35 -->X
    <!-- /react-text -->
  </div>
  <div class="drum-pad" id="Mi Error" style="background-color: blue; margin: 40px;"><audio class="clip" id="C" src="https://dl.dropbox.com/s/xeoceqaj9vyizxm/Eladio%20Carrion%20Ft%20Zion%20-%20Mi%20Error%20%28Letra%29.mp3?dl=0" style="background-color: grey; margin: 50px;"></audio>
    <!-- react-text: 38 -->C
    <!-- /react-text -->
  </div>
  <!-- react-text: 39 -->
  <!-- /react-text -->
</div>

答案 1 :(得分:1)

科比的答案是正确的,但是React具有您自己的操作DOM的方式,不建议使用document,而可以使用React.createRef()或{{1}用钩子。您可以找到文档here

  

引用提供了一种方法,可以访问在render方法中创建的DOM节点或React元素。

     

在典型的React数据流中,道具是父组件与其子组件交互的唯一方式。要修改孩子,您可以使用新道具重新渲染它。但是,在某些情况下,您需要在典型数据流之外强制修改子级。要修改的子级可以是React组件的实例,也可以是DOM元素。对于这两种情况,React都提供了一个逃生舱口。

答案 2 :(得分:-1)

可以通过从您的SoundPadSide父组件向您的孩子SoundPad组件提供其他道具来实现欲望行为。

我的想法是从其父组件SoundPad控制SoundPadSide的活动状态。

基本上,您需要在state组件中定义SoundPadSide,以控制当前处于活动状态的内容。

然后,您需要定义一个回调函数,该函数将更改活动的Pad:

class SoundPadSide extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      activeSoundPadId: "Speechless"
    };
    this.handleActiveChanged = this.handleActiveChanged.bind(this);
  }

  handleActiveChanged(id) {
    this.setState({ activeSoundPadId: id });
  }
}

在构造函数中,您可以定义activeSoundPadId的初始状态。例如,我从您的音乐列表中拿了第二个。

接下来,您需要通过SoundPad方法将这些属性传递给render()组件:

MusicBank = this.props.musicData.map((Obj, i, MusicArr) => {
    return (
      <SoundPad
        clipId={MusicArr[i].id}
        clip={MusicArr[i].url}
        keyCode={MusicArr[i].keyCode}
        keyTrigger={MusicArr[i].keyTrigger}
        clipName={MusicArr[i].clipName}
        changeDisplay={this.props.changeDisplay}
        power={this.props.power}

        isActive={this.state.activeSoundPadId === MusicArr[i].id}
        activate={this.handleActiveChanged}
      />
    );
  }

SoundPad组件中有几处更改。由于现在收到的其他道具比我们应该应用的要多。 如果当前的activate y没有激活,我会在您的palySound方法中调用SoundPad回调:

playSound(e) {
   this.props.activate(this.props.clipId);

   if (this.state.toPlay) {
      const sound = document.getElementById(this.props.keyTrigger);
      sound.currentTime = 0;
      sound.play();
      this.padControl();
      this.props.changeDisplay(this.props.clipName);
    } else {      
      const sound = document.getElementById(this.props.keyTrigger);
      sound.currentTime = 0;
      sound.pause();
      this.padControl();
      this.props.changeDisplay(String.fromCharCode(160));
}

SoundPad render()方法中的另一项更改:

    return (
      <div
        class="Inactive"
        className="drum-pad"
        id={this.props.clipId}
        onClick={this.playSound}

        style={this.props.isActive ? activeStyle : inactiveStyle}
      >
      ...

我已经稍微更新了您的代码。 Here您可以找到演示