请添加图片描述

使用以下两个api

MDN Selection API
MDN Range API

需要 API

const Range = useCallback(() => {
    const selObj = window.getSelection();
    if (!selObj) return;
    return selObj.getRangeAt(0);
  }, []);

删除代码

const range = Range();
if (!range) return;
range.deleteContents();// 删除节点
加粗功能代码(修改 加入markdown 语法 ** ** 加粗)
onClick={() => {
 const range = Range();
 if (!range) return;
 const t = document.createElement("span");
 range.surroundContents(t);//标签先加入 然后在改值
 t.innerHTML = `**${range.toString()}**`;
}}

如果选中的文字不是同一行(不是同一个元素)需要先删除原来的 再添加新的

	const range = Range();
   if (!range) return;
   const prev = range.toString();
   range.deleteContents();
   const t = document.createElement("span");
   range.surroundContents(t);
   t.innerHTML = `**${prev}**`;

完整代码 仅供参考

import { Button } from "antd";
import { useState, useCallback, useRef, useMemo } from "react";
import { FC, ReactElement } from "react";
import styled from "styled-components";
import MarkDown from "../components/MD/MarkDown";

interface IProps {}

const MD: FC<IProps> = (): ReactElement => {
  const [content, setContent] = useState("");
  const input = useRef<HTMLInputElement | null>(null);
  const inputEvent = useMemo(() => {
    const event = document.createEvent("HTMLEvents");
    event.initEvent("input", true, true);
    return event;
  }, []);
  const Range = useCallback(() => {
    const selObj = window.getSelection();
    if (!selObj) return;
    return selObj.getRangeAt(0);
  }, []);

  const onInput = useCallback(e => {
    setContent(e.target.innerText);
  }, []);

  const forceInput = useCallback(() => {
    input.current?.dispatchEvent(inputEvent);
  }, [inputEvent]);

  return (
    <Container>
      <Nav>
        <Button
          onClick={() => {
            const range = Range();
            if (!range) return;
            range.deleteContents();
            forceInput();
          }}
        >
          删除
        </Button>
        <Button
          onClick={() => {
            const range = Range();
            if (!range) return;
            const t = document.createElement("span");
            range.surroundContents(t);
            t.innerHTML = `**${range.toString()}**`;
            forceInput();
            range.collapse(false);
          }}
        >
          加粗
        </Button>
      </Nav>
      <EditWrapper>
        <div ref={input} onInput={onInput} contentEditable='true'></div>
        <MarkDown content={content} />
      </EditWrapper>
    </Container>
  );
};

export default MD;

const Container = styled.div`
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
`;

const Nav = styled.nav`
  width: 100%;
  height: 50px;
  background-color: #000;
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 1;
`;

const EditWrapper = styled.div`
  height: calc(100% - 50px);
  width: 100%;
  display: flex;

  & > div {
    width: 50%;
    max-width: 50%;
    padding: 0 5px;
  }

  & > div:first-child {
    border-right: 1px dashed #ccc;
    outline: none;
  }
`;

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐