首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何发送<TextInput对象的contextmenu事件并通过在Typescript React中单击按钮来选择菜单项

如何发送<TextInput对象的contextmenu事件并通过在Typescript React中单击按钮来选择菜单项
EN

Stack Overflow用户
提问于 2021-09-17 21:54:51
回答 1查看 102关注 0票数 0

在我们的聊天组件中,许多人不知道他们可以通过右键单击文本区域并从菜单中选择表情来找到表情菜单。我想在UI中放一个按钮,可以直接打开表情菜单。这样,那些不知道右键单击和上下文菜单的人只需单击表情符号按钮,就可以获得内置的表情符号。

我尝试在文本输入旁边添加一个按钮(因此不是TextInput的子项),并发送上下文菜单,如下所示:

代码语言:javascript
复制
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对象如下所示:

代码语言:javascript
复制
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,因为我不知道如何找到它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-18 02:11:25

我在React中设置了一个代码示例,说明如何通过单击按钮来调用contextmenu事件。您需要对TextInput和具有上下文菜单的上下文菜单容器的DOM引用。

工作示例:https://stackblitz.com/edit/react-727dpd?file=src/App.js

在我的示例中,右键单击文本区域或按钮时,会出现上下文菜单。你需要关注的一点是我是如何将ref添加到textarea的。

代码语言:javascript
复制
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>
    </>
  );
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69229866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档