1.插入span标签

将span标签的 contenteditable 设置为 false 达到backspace一键删除标签的效果

这个方案很坑,虽然可以基本满足业务组件的需求,但是浏览器的规则中 contenteditable 为 false 的元素光标是不显示的 这就导致我们在插入标签后光标明明已经点到span标签后但却看不到光标,用户体验不理想

2.插入img标签

这个方案是在此 大佬的博客 中得到的启发 将span标签换为img标签

我们动态生成svg 再把svg序列化为字符串 通过 Blob 转为ObjectUrl 加载到img标签中

效果相较于插入span表现优异

重要实现步骤

// 一个插入标签点击事件
onLabelClick() {
     let str = "一个标签";
     let svg = this.createSvg(str);
     let img = this.creatImg(str,svg);
     this.insertHtmlAtCaretNew(img.outerHTML);
// 动态创建svg (可以根据str传入的字符串长度计算 svg 、svg_rect 的宽度以及 svg_tspan 的偏移量 )
createSvg(str) {
      let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      svg.setAttribute("style", "width:64px;height:20px;");
      svg.setAttribute("viewBox", "0 0 64 20");
      let svg_title = document.createElementNS(
        "http://www.w3.org/2000/svg",
        "title"
      svg_title.innerHTML = str;
      let svg_g = document.createElementNS("http://www.w3.org/2000/svg", "g");
      svg_g.setAttribute("fill", "none");
      svg_g.setAttribute("fill-rule", "evenodd");
      let svg_rect = document.createElementNS(
        "http://www.w3.org/2000/svg",
        "rect"
      svg_rect.setAttribute("style", "width:60px;height:20px;rx:10px;");
      svg_rect.setAttribute("fill", "#E8EBED");
      let svg_text = document.createElementNS(
        "http://www.w3.org/2000/svg",
        "text"
      svg_text.setAttribute("font-family", "PingFangSC-Regular, PingFang SC");
      svg_text.setAttribute("font-size", "12px");
      svg_text.setAttribute("fill", "#494B4D");
      let svg_tspan = document.createElementNS(
        "http://www.w3.org/2000/svg",
        "tspan"
      svg_tspan.setAttribute("x", "8");
      svg_tspan.setAttribute("y", "15.5");
      svg_tspan.innerHTML = str;
      svg_text.appendChild(svg_tspan);
      svg_g.appendChild(svg_rect);
      svg_g.appendChild(svg_text);
      svg.appendChild(svg_title);
      svg.appendChild(svg_g);
      return svg;
    // 创建img标签 同样的宽高需要计算
    creatImg(str,svg) {
      let img = document.createElement("img");
      img.alt = str;
      let xml_svg = new XMLSerializer().serializeToString(svg);
      var svg_blob = new Blob([xml_svg], {
        type: "image/svg+xml;charset=utf-8",
      var url = URL.createObjectURL(svg_blob);
      img.src = url;
      img.setAttribute("style", "max-width:60px;max-height:20px;");
      return img;

然后再通过Window.getSelection获取光标的位置插入标签即可

效果如下:

image.png

分类:
前端
  •