Açılır menü bileşeninin dışında bir tıklama oluştuğunda bir açılır menüyü kapatmak istiyorum.
Bunu nasıl yaparım?
Açılır menü bileşeninin dışında bir tıklama oluştuğunda bir açılır menüyü kapatmak istiyorum.
Bunu nasıl yaparım?
Yanıtlar:
Eleman ben eklemiş mousedown
ve mouseup
bunun gibi:
onMouseDown={this.props.onMouseDown} onMouseUp={this.props.onMouseUp}
Sonra ebeveynde bunu yapıyorum:
componentDidMount: function () {
window.addEventListener('mousedown', this.pageClick, false);
},
pageClick: function (e) {
if (this.mouseIsDownOnCalendar) {
return;
}
this.setState({
showCal: false
});
},
mouseDownHandler: function () {
this.mouseIsDownOnCalendar = true;
},
mouseUpHandler: function () {
this.mouseIsDownOnCalendar = false;
}
showCal
Bir boolean olduğunu zaman true
benim durumumda gösterileri takvim ve false
gizler onu.
preventDefault()
olayları hemen aramanız gerekiyor ya da React'in ön işlemesi müdahale eden yerel Android davranışı devreye giriyor. O zamandan beri npmjs.com/package/react-onclickoutside yazdım .
Yaşam döngüsü yöntemlerini kullanarak, belgeye olay dinleyicileri ekleyin ve kaldırın.
React.createClass({
handleClick: function (e) {
if (this.getDOMNode().contains(e.target)) {
return;
}
},
componentWillMount: function () {
document.addEventListener('click', this.handleClick, false);
},
componentWillUnmount: function () {
document.removeEventListener('click', this.handleClick, false);
}
});
Bu bileşenin 48-54. Satırlarına bakın: https://github.com/i-like-robots/react-tube-tracker/blob/91dc0129a1f6077bef57ea4ad9a860be0c600e9d/app/component/tube-tracker.jsx#L48-54
Olayın hedefine bakın, eğer olay doğrudan bileşenin üzerindeyse veya bu bileşenin alt öğesindeyse tıklama içerideydi. Aksi takdirde dışarıdaydı.
React.createClass({
clickDocument: function(e) {
var component = React.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
// Inside of the component.
} else {
// Outside of the component.
}
},
componentDidMount: function() {
$(document).bind('click', this.clickDocument);
},
componentWillUnmount: function() {
$(document).unbind('click', this.clickDocument);
},
render: function() {
return (
<div ref='component'>
...
</div>
)
}
});
Bu birçok bileşende kullanılacaksa, bir karışımla daha güzeldir:
var ClickMixin = {
_clickDocument: function (e) {
var component = React.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
this.clickInside(e);
} else {
this.clickOutside(e);
}
},
componentDidMount: function () {
$(document).bind('click', this._clickDocument);
},
componentWillUnmount: function () {
$(document).unbind('click', this._clickDocument);
},
}
Buradaki örneğe bakın: https://jsfiddle.net/0Lshs7mg/1/
this.refs.component
0.14 facebook.github.io/react/blog/2015/07/03/…
Özel kullanım durumunuz için, şu anda kabul edilen cevap biraz fazla tasarlanmış. Bir kullanıcı açılır listeden tıkladığında dinlemek istiyorsanız <select>
, ana öğe olarak bir bileşen kullanın ve onBlur
ona bir işleyici ekleyin .
Bu yaklaşımın tek dezavantajı, kullanıcının öğeye zaten odaklanmayı sürdürdüğünü varsayması ve bir form kontrolüne dayanmasıdır ( tab
anahtarın da öğelere odaklandığını ve bulanıklaştırdığını hesaba katarsanız istediğiniz şey olabilir veya olmayabilir. ) - ancak bu dezavantajlar, yalnızca daha karmaşık kullanım durumları için bir sınırdır, bu durumda daha karmaşık bir çözüm gerekli olabilir.
var Dropdown = React.createClass({
handleBlur: function(e) {
// do something when user clicks outside of this element
},
render: function() {
return (
<select onBlur={this.handleBlur}>
...
</select>
);
}
});
onBlur
div tabIndex
özelliği varsa div ile de çalışır
Bileşenin dışından kaynaklanan olaylar için olay dışında tepki veren genel bir olay işleyicisi yazdım .
Uygulamanın kendisi basittir:
window
nesneye bir olay işleyicisi eklenir .onOutsideEvent
, hedef bileşende tetiklenir .import React from 'react';
import ReactDOM from 'react-dom';
/**
* @param {ReactClass} Target The component that defines `onOutsideEvent` handler.
* @param {String[]} supportedEvents A list of valid DOM event names. Default: ['mousedown'].
* @return {ReactClass}
*/
export default (Target, supportedEvents = ['mousedown']) => {
return class ReactOutsideEvent extends React.Component {
componentDidMount = () => {
if (!this.refs.target.onOutsideEvent) {
throw new Error('Component does not defined "onOutsideEvent" method.');
}
supportedEvents.forEach((eventName) => {
window.addEventListener(eventName, this.handleEvent, false);
});
};
componentWillUnmount = () => {
supportedEvents.forEach((eventName) => {
window.removeEventListener(eventName, this.handleEvent, false);
});
};
handleEvent = (event) => {
let target,
targetElement,
isInside,
isOutside;
target = this.refs.target;
targetElement = ReactDOM.findDOMNode(target);
isInside = targetElement.contains(event.target) || targetElement === event.target;
isOutside = !isInside;
if (isOutside) {
target.onOutsideEvent(event);
}
};
render() {
return <Target ref='target' {... this.props} />;
}
}
};
Bileşeni kullanmak için, hedef bileşen sınıf bildirimini yüksek dereceli bileşeni kullanarak sarmalamanız ve işlemek istediğiniz olayları tanımlamanız gerekir:
import React from 'react';
import ReactDOM from 'react-dom';
import ReactOutsideEvent from 'react-outside-event';
class Player extends React.Component {
onOutsideEvent = (event) => {
if (event.type === 'mousedown') {
} else if (event.type === 'mouseup') {
}
}
render () {
return <div>Hello, World!</div>;
}
}
export default ReactOutsideEvent(Player, ['mousedown', 'mouseup']);
Benim için işe yaramasa da cevaplardan birini oyladım. Beni bu çözüme götürdü. İşlemlerin sırasını biraz değiştirdim. Hedefte mouseDown ve hedefte mouseUp'ı dinliyorum. Bunlardan herhangi biri DOĞRU döndürürse, modu kapatmayız. Bir tıklama, herhangi bir yerde kaydedilir kaydedilmez, bu iki boole {mouseDownOnModal, mouseUpOnModal} false olarak geri döner.
componentDidMount() {
document.addEventListener('click', this._handlePageClick);
},
componentWillUnmount() {
document.removeEventListener('click', this._handlePageClick);
},
_handlePageClick(e) {
var wasDown = this.mouseDownOnModal;
var wasUp = this.mouseUpOnModal;
this.mouseDownOnModal = false;
this.mouseUpOnModal = false;
if (!wasDown && !wasUp)
this.close();
},
_handleMouseDown() {
this.mouseDownOnModal = true;
},
_handleMouseUp() {
this.mouseUpOnModal = true;
},
render() {
return (
<Modal onMouseDown={this._handleMouseDown} >
onMouseUp={this._handleMouseUp}
{/* other_content_here */}
</Modal>
);
}
Bunun avantajı, tüm kodun üst bileşen değil, alt bileşene ait olmasıdır. Bu, bu bileşeni yeniden kullanırken kopyalanacak standart kod olmadığı anlamına gelir.
.backdrop
)..target
) öğenin dışında .backdrop
ve daha büyük bir yığın dizini ( z-index
) ile bulundurun.Öğeye yapılan herhangi bir tıklama .backdrop
" .target
öğenin dışında" olarak kabul edilecektir .
.click-overlay {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1;
}
.target {
position: relative;
z-index: 2;
}
Kullanabilirsin ref
başarmak s , aşağıdaki gibi bir şey çalışmalıdır.
Öğenize ekleyin ref
:
<div ref={(element) => { this.myElement = element; }}></div>
Daha sonra, aşağıdaki gibi öğenin dışındaki tıklamayı işlemek için bir işlev ekleyebilirsiniz:
handleClickOutside(e) {
if (!this.myElement.contains(e)) {
this.setState({ myElementVisibility: false });
}
}
Son olarak, olay dinleyicilerini ekleyin ve kaldırın, eklenecek ve bağlantısı kesilecektir.
componentWillMount() {
document.addEventListener('click', this.handleClickOutside, false); // assuming that you already did .bind(this) in constructor
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, false); // assuming that you already did .bind(this) in constructor
}
handleClickOutside
içinde document.addEventListener()
ekleyerek this
başvuru. Aksi takdirde verir Yakalanmayan ReferenceError: handleClickOutside tanımlı değil decomponentWillMount()
Partiye çok geç kaldı, ancak açılır listenin üst öğesinde, açılır listeyi kapatmak için ilişkili kodla bir bulanıklaştırma etkinliği ayarlayarak ve ayrıca açılır menünün açık olup olmadığını kontrol eden ana öğeye bir fare indirme dinleyicisi ekleyerek başarılı oldum ya da değil ve açıksa olay yayılmasını durduracak, böylece bulanıklık olayı tetiklenmeyecektir.
Fare düşürme olayı baloncuk oluşturduğundan, bu, çocuklar üzerinde herhangi bir fare düşürmenin ebeveyn üzerinde bulanıklığa neden olmasını önleyecektir.
/* Some react component */
...
showFoo = () => this.setState({ showFoo: true });
hideFoo = () => this.setState({ showFoo: false });
clicked = e => {
if (!this.state.showFoo) {
this.showFoo();
return;
}
e.preventDefault()
e.stopPropagation()
}
render() {
return (
<div
onFocus={this.showFoo}
onBlur={this.hideFoo}
onMouseDown={this.clicked}
>
{this.state.showFoo ? <FooComponent /> : null}
</div>
)
}
...
e.preventDefault (), akıl yürütebildiğim kadarıyla çağrılmamalı, ancak firefox herhangi bir nedenle onsuz iyi oynamıyor. Chrome, Firefox ve Safari'de çalışır.
Bunun hakkında daha basit bir yol buldum.
Sadece onHide(this.closeFunction)
modal eklemeniz gerekiyor
<Modal onHide={this.closeFunction}>
...
</Modal>
Modeli kapatmak için bir fonksiyonunuz olduğunu varsayarsak.
Mükemmel tepki-onclickoutside karışımını kullanın :
npm install --save react-onclickoutside
Ve sonra
var Component = React.createClass({
mixins: [
require('react-onclickoutside')
],
handleClickOutside: function(evt) {
// ...handling code goes here...
}
});