React,Antd实现文本输入框话题添加及删除的完整功能解决方案

发布于:2024-12-18 ⋅ 阅读:(110) ⋅ 点赞:(0)

最终效果就是实现该输入框:

  • 添加话题时,话题自动插入到输入框前面
  • 多文本输入框左侧间距为话题的宽度
  • 多行文本时,第二行紧接开头渲染
  • 删除文本时,如果删除到话题,再次删除,话题被删除
  1. 首先构造div结构
  const [hashtag, setHashtag] = useState(""); // 话题内容
  const [textIndent, setTextIndent] = useState("0px"); // 动态缩进
  const hashtagRef = useRef(null);
  const [value, setValue] = useState("");
  const [focus, setFocus] = useState(false);


<div className="topInput">
            <div className="topiceShow" ref={hashtagRef}>
              {hashtag}
            </div>
            <TextArea
              value={value}
              onChange={(e) => setValue(e.target.value)}
              onInput={TextAreaInput}
              onFocus={() => setFocus(true)}
              onBlur={() => setFocus(false)}
              onKeyDown={handleKeyDown}
              autoSize={{ minRows: 3, maxRows: 5 }}
              maxLength={1000}
              style={{
                flex: 1,
                border: "none",
                textIndent,
                backgroundColor: focus ? "#ffffff" : "#f2f3f5",
                transition: "none",
              }}
            />
          </div>

2.重点是在添加话题时,获取话题的宽度和你本身需要添加的间距

 const selectTopice = (item: any) => {
    setHashtag(`#${item.ActivityTitle}#`);
    setValue(` ${value}`);
  };

3.实时监听话题变化,给其宽度赋值

 // 动态计算话题宽度
  useEffect(() => {
    if (hashtagRef.current) {
      const hashtagWidth = hashtagRef.current.offsetWidth;
      const extraPadding = 5; // 话题后的额外空隙
      setTextIndent(`${hashtagWidth + extraPadding}px`);
    }
  }, [hashtag]);

4.现在宽度有了,如何使其两个div并行,且第二行紧接开始呢?

这就要用到css 的样式  text-index

text-index是 CSS 中的一个属性,用于控制文本的首行缩进。它通常用于段落、列表、文本框等元素中,指定文本的第一行相对于其容器的缩进距离。这个属性的值可以是像素(px)、百分比(%)等单位。

5.所以我们来编写样式结构

.topInput {
        position: relative;
        .topiceShow {
          font-size: 14px;
          position: absolute;
          left: 10px;
          top: 5px;
          z-index: 8888;
          display: inline-block; /* 让内容宽度适应话题文本 */
        }
      }

6.话题设置为 position: absolute;然后设置TextArea的 textIndent为计算值,即可实现这样样式格式

7.但是如何实现删除呢,这就要用到onKeyDown事件了

 const handleKeyDown = (e: any) => {
    // 检测按键是否是 Backspace 并文本为空
    const cursorPosition = e.target.selectionStart;
    if (
      (e.code === "Backspace" || e.code === "Delete") &&
      cursorPosition === 0
    ) {
      setHashtag(""); // 清空话题
    }
  };

8.至此,功能全部实现 


网站公告

今日签到

点亮在社区的每一天
去签到