IM即时通信_文本框

269 阅读1分钟

备注:最近再开发一款前端的即时通信产品,记录一些比较有价值的使用方法;

css消息显示
.text_msg{
    white-space: pre-line;
    word-break: break-all;
    word-break: break-word;
}
js找到['微笑替换表情']
export function ImHandleTextMessageEmoteShow(text: string, searchText?: string) {
    text = text.replace(/(?=\[)(.*?)(\])/g, function(tmp) {
        // 获取图片url
        return handleEmojiTextToUrl(tmp);
    });
    // 搜索高亮
    if (searchText && searchText.length > 0) { // 如果有搜索的时候
        return text.replace(searchText,'<span style=\'color: #58AEFF;\'>'+searchText+'</span>');
    };
    return text;
};
// vue 使用v-html react使用 <span dangerouslySetInnerHTML={{__html: str}}></span>
div变输入框
<div contenteditable="true"></div>
把光标移动到最后
andleKeepLastIndex() {
  // vue3 ref绑定;可以通过document.getById(targetName)获取
  const speakRefVal: any = speakRef.value;
  if (window.getSelection) {
    speakRefVal.focus();
    var range = window.getSelection();
    range.selectAllChildren(speakRefVal);
    range.collapseToEnd();
    /* 第二种方法
    var sel = window.getSelection();
 		var range = document.createRange();
    range.selectNodeContents(speakRefVal);
    range.collapse(false);
    sel.removeAllRanges();
    sel.addRange(range);*/
  };
},
监听回车和ctr回车
// vue3 @keydown="handleSpeakKey($event)"
// 监听按键_步骤1 监听Ctrl+Enter
handleSpeakKey(event: any) {
   if(event.ctrlKey && event.keyCode === 13){
     return false;
   }else if (event.keyCode === 13) {
     event.preventDefault() // 阻止浏览器默认换行操作
     return false
   }
},
处理复制
/* 个人建议图片单独上传,不要图文混排,虽然能实现,但是遇到bug能难解决 */
// vue3 ref绑定语法
speakRefVal.onpaste = function(e: any) {
  e.stopPropagation();
  e.preventDefault();
  const selection = getSelection();
  if (!selection) return;
  lastEditRange = selection.getRangeAt(0);
  if (!(e.clipboardData && e.clipboardData.items) ) {
    return ;
  };
  const items = e.clipboardData.items;
  if (items.length) {
    let item = items[0];
    if (item.kind === "string") {
      item.getAsString(function (str: string) {
        if (!str) return;
        let tmpStr = HTMLEncode(str);
        let Span = `<div>${tmpStr}</div>`;
        methods.handleInsertContent(Span);
      })
    }
    if (item.kind === "file") {
      var pasteFile = item.getAsFile();
      if (pasteFile.type === "image/png") {
        Dialog.confirm({
          title: '图片上传',
          message: '确定上传该图片吗?',
        }).then(() => {
          methods.handlePasteImgUpload(pasteFile);
        }).catch(() => {
        });
        //     var reader = new FileReader()
        //     reader.onload = function(event: any) {
        //         let Img = `<div><img src="${event.target.result}"/></div>`;
        //         methods.handleInsertContent(Img);
        //     };
        //     reader.readAsDataURL(pasteFile);
      };
    }
  }
}
记录最后一次光标位置
// vue3 ref绑定语法
speakRefVal.onblur = function() {
		const selection = getSelection();
   	if (!selection) return;
   	lastEditRange = selection?.getRangeAt(0);
 };
将标签插入到光标位置
handleInsertContent(Element: string) {
    // 获取光标对象
    const selection: any = getSelection();
    if (!selection) return;
    selection.addRange(lastEditRange);
    // 获取当前光标位置
    const range = selection.getRangeAt(0);
    // 创建Dom
    const node = range.createContextualFragment(Element);
    // 获取当前元素最后一个子元素
    const c = node.lastChild;
    // 插入创建Dom
    range.insertNode(node);
    // 插入成功后光标移动到插入Dom后面
    if (c) {
      range.setEndAfter(c);
      range.setStartAfter(c);
    };
},
文本框移动到最后
var tObj = document.getElementById('searchInput');
var sPos = tObj.value.length;
setCaretPosition(tObj, sPos);
function setCaretPosition(tObj, sPos) {
  if (tObj.setSelectionRange) {
    tObj.setSelectionRange(sPos, sPos);
    tObj.focus();
  } else if (tObj.createTextRange) {
    var rng = tObj.createTextRange();
    rng.move('charcter', sPos);
    rng.select();
  }
}
聊天框需要的正则
// 去除所有标签
str.replace(/<[^>]+>/g, "");
// 去除html所有标签,img除外
str.replace(/<(?!img).*?>/g, '');