我有一个音量元素,当用户将鼠标悬停在音量栏上时会显示音量条。这一切都适用于桌面。但是,要在移动设备上获得相同的功能,用户可以点击音量元素,同时切换静音点击事件。
当用户在移动设备上点击(即点按)该元素时,我想停止该静音事件。
我不想修改Mute或VolumeBar类来修复它,因为这些是我的库中开发人员使用的泛型类。
https://jsfiddle.net/jwm6k66c/2145/
打开控制台 - >进入移动视图(在chrome上按CTRL + SHIFT + M) - >单击音量按钮并观察控制台日志。
我尝试了什么:
当音量条的高度为0(即不可见)时,使用volumeControlOnClick
来停止传播,但这并不会取消onClick。
我想要的是什么:
如果用户第一次在移动设备中点击了音量图标,则取消静音点击事件。相反,它应该只显示音量条。
const volumeControlOnClick = (e) => {
const volumeBarContainer =
e.currentTarget.nextElementSibling.querySelector('.jp-volume-bar-container');
/* Stop propogation is for mobiles to stop
triggering mute when showing volume bar */
if (volumeBarContainer.clientHeight === 0) {
e.stopPropagation();
console.log("stop propogation")
}
};
class Volume extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div className="jp-volume-container">
<Mute onTouchStart={volumeControlOnClick}><i className="fa fa-volume-up" /></Mute>
<div className="jp-volume-controls">
<div className="jp-volume-bar-container">
<VolumeBar />
</div>
</div>
</div>
);
}
};
class Mute extends React.Component {
render() {
return (
<button className="jp-mute" onClick={() => console.log("mute toggled")} onTouchStart={this.props.onTouchStart}>
{this.props.children}
</button>
);
}
};
class VolumeBar extends React.Component {
render() {
return (
<div className="jp-volume-bar" onClick={() => console.log("bar moved")}>
{this.props.children}
</div>
);
}
};
React.render(<Volume />, document.getElementById('container'));
答案 0 :(得分:1)
只要您使用气泡阶段,您可以使用标记表示您在处于鼠标事件之前处于触摸事件中。因此,将监听器附加到容器元素,如下所示:
let isTouch = false;
const handleContainerClick = () => isTouch = false;
const handleMuteClick = () => {
if (isTouch == false) {
console.log("mute toggled");
}
};
const volumeControlOnClick = () => {
isTouch = true;
};
class Volume extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div className="jp-volume-container" onClick={handleContainerClick}>
<Mute onTouchStart={volumeControlOnClick} onClick={handleMuteClick}><i className="fa fa-volume-up" /></Mute>
<div className="jp-volume-controls">
<div className="jp-volume-bar-container">
<VolumeBar />
</div>
</div>
</div>
);
}
};
class Mute extends React.Component {
render() {
return (
<button className="jp-mute" onTouchStart={this.props.onTouchStart} onClick={this.props.onClick}>
{this.props.children}
</button>
);
}
};
class VolumeBar extends React.Component {
render() {
return (
<div className="jp-volume-bar" onClick={() => console.log("bar moved")}>
{this.props.children}
</div>
);
}
};
render(<Volume />, document.getElementById('container'));
如果你没有使用气泡阶段,那么你可以用上面相同的逻辑注册100ms的超时,在100ms之后你再次使你的flag变量为false。只需添加到touchStart处理程序:
setTimeout(() => {isTouch = false}, 100);
编辑尽管默认情况下Chrome 56中的触摸事件应该是被动的,但您可以从touchEnd事件中调用preventDefault()以防止点击处理程序触发。因此,如果您无法以任何方式修改Mute类的单击处理程序,但您可以添加touchEnd事件,而不是:
const handleTouchEnd = (e) => e.preventDefault();
const volumeControlOnClick = () => console.log("volumeControlOnClick");
class Volume extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div className="jp-volume-container">
<Mute onTouchStart={volumeControlOnClick} onTouchEnd={handleTouchEnd}><i className="fa fa-volume-up" /></Mute>
<div className="jp-volume-controls">
<div className="jp-volume-bar-container">
<VolumeBar />
</div>
</div>
</div>
);
}
};
class Mute extends React.Component {
render() {
return (
<button className="jp-mute" onTouchStart={this.props.onTouchStart} onTouchEnd={this.props.onTouchEnd} onClick={() => console.log("mute toggled")}>
{this.props.children}
</button>
);
}
};
class VolumeBar extends React.Component {
render() {
return (
<div className="jp-volume-bar" onClick={() => console.log("bar moved")}>
{this.props.children}
</div>
);
}
};
render(<Volume />, document.getElementById('container'));
答案 1 :(得分:-1)
试试这个
render() {
return (
<div className="jp-volume-container" onClick={handleContainerClick}>
<Mute onTouchStart={volumeControlOnClick} onClick={handleMuteClick}><i className="fa fa-volume-up" /></Mute>
<div className="jp-volume-controls">
<div className="jp-volume-bar-container">
<VolumeBar />
</div>
</div>
</div>
);
}
};
class Mute extends React.Component {
render() {
return (
<button className="jp-mute" onTouchStart={this.props.onTouchStart} onClick={this.props.onClick}>
{this.props.children}
</button>
);
}
};
class VolumeBar extends React.Component {
render() {
return (
<div className="jp-volume-bar" onClick={() => console.log("bar moved")}>
{this.props.children}
</div>
);
}
};
render(<Volume />, document.getElementById('container'));