在我们的聊天组件中,许多人不知道他们可以通过右键单击文本区域并从菜单中选择表情来找到表情菜单。我想在UI中放一个按钮,可以直接打开表情菜单。这样,那些不知道右键单击和上下文菜单的人只需单击表情符号按钮,就可以获得内置的表情符号。
我尝试在文本输入旁边添加一个按钮(因此不是TextInput的子项),并发送上下文菜单,如下所示:
const showCtxMenu = () => {
var element = document.getElementById("chatti");
var ev2 = new MouseEvent("contextmenu", {
bubbles: true,
cancelable: false,
view: window,
button: 2,
buttons: 0,
clientX: element.getBoundingClientRect().x,
clientY: element.getBoundingClientRect().y
});
element.dispatchEvent(ev2);
}在相同的功能组件中,TextInput对象如下所示:
return (
<View
style={[
style.inputView,
{borderColor: primaryColor, height: 40}
]}>
<div id="chatti">
<TextInput
value={message}
// onContentSizeChange={(event) => {
// causes infinite react state update on ctrl+A -> delete
// setHeight(event.nativeEvent.contentSize.height);
// }}
onChangeText={(text) => onChangeMessage(text)}
style={{当按钮单击时,我会将事件发送到父div,所以什么都不会发生。我不知道如何将事件直接发送到TextInput,因为我不知道如何找到它。
发布于 2021-09-18 02:11:25
我在React中设置了一个代码示例,说明如何通过单击按钮来调用contextmenu事件。您需要对TextInput和具有上下文菜单的上下文菜单容器的DOM引用。
工作示例:https://stackblitz.com/edit/react-727dpd?file=src/App.js
在我的示例中,右键单击文本区域或按钮时,会出现上下文菜单。你需要关注的一点是我是如何将ref添加到textarea的。
import React, { useRef, useEffect } from 'react';
import './style.css';
export default function App() {
const contextMenuRef = useRef();
const chatBoxRef = useRef();
useEffect(() => {
const contextMenu = contextMenuRef.current;
const scope = chatBoxRef.current;
const normalizePozition = (mouseX, mouseY) => {
// ? compute what is the mouse position relative to the container element (scope)
let { left: scopeOffsetX, top: scopeOffsetY } =
scope.getBoundingClientRect();
scopeOffsetX = scopeOffsetX < 0 ? 0 : scopeOffsetX;
scopeOffsetY = scopeOffsetY < 0 ? 0 : scopeOffsetY;
const scopeX = mouseX - scopeOffsetX;
const scopeY = mouseY - scopeOffsetY;
// ? check if the element will go out of bounds
const outOfBoundsOnX =
scopeX + contextMenu.clientWidth > scope.clientWidth;
const outOfBoundsOnY =
scopeY + contextMenu.clientHeight > scope.clientHeight;
let normalizedX = mouseX;
let normalizedY = mouseY;
// ? normalize on X
if (outOfBoundsOnX) {
normalizedX =
scopeOffsetX + scope.clientWidth - contextMenu.clientWidth;
}
// ? normalize on Y
if (outOfBoundsOnY) {
normalizedY =
scopeOffsetY + scope.clientHeight - contextMenu.clientHeight;
}
return { normalizedX, normalizedY };
};
scope.addEventListener('contextmenu', (event) => {
console.log(event);
event.preventDefault();
const { clientX: mouseX, clientY: mouseY } = event;
const { normalizedX, normalizedY } = normalizePozition(mouseX, mouseY);
contextMenu.classList.remove('visible');
contextMenu.style.top = `${normalizedY}px`;
contextMenu.style.left = `${normalizedX}px`;
setTimeout(() => {
contextMenu.classList.add('visible');
});
});
scope.addEventListener('click', (e) => {
// ? close the menu if the user clicks outside of it
if (e.target.offsetParent != contextMenu) {
contextMenu.classList.remove('visible');
}
});
}, []);
const showCtxMenu = (e) => {
//e.preventDefault();
var element = chatBoxRef.current;
var ev2 = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: false,
view: window,
button: 2,
buttons: 0,
clientX: element.getBoundingClientRect().x,
clientY: element.getBoundingClientRect().y,
});
element.dispatchEvent(ev2);
};
return (
<>
<div style={{ height: '300px' }}></div>
<textarea ref={chatBoxRef} col={10}></textarea>
<div ref={contextMenuRef} id="context-menu">
<div class="item">Option 1</div>
<div class="item">Option 2</div>
<div class="item">Option 3</div>
<div class="item">Option 4</div>
<div class="item">Option 5</div>
</div>
<button onClick={showCtxMenu}>Press Context</button>
</>
);
}https://stackoverflow.com/questions/69229866
复制相似问题