Vue实现字符串中自定义标识符的解析渲染🎩

4,572 阅读3分钟

遇到难题,保持平常心,勇于面对,总会找出突破口。

前言

有这样一个场景: 实现了文字和图片的混输,此时div中有img标签文字,那么我们要将这些内容发送给服务端,然后服务端将我们发送的内容推送给每个用户,服务端需要什么格式的数据?我们客户端拿到服务端返回的数据,要怎么渲染到页面?接下来就给大家分享下我的解决方案,先给大家看一下最终实现的效果

实现思路

  • 监听回车事件
  • 获取输入框的所有子元素
  • 遍历所有子元素
  • 找出img标签和text节点
  • 获取img标签的alt标识,将alt标识解析成特定字符串
  • 调用接口发送最终解析好的字符串
  • 获取接口返回的数据,解析自定义标识符
  • 获取自定义标识符在字符串中出现的位置,将其解析成img标签
  • 渲染解析好的字符串

实现过程

  • 监听回车事件
<div class="input-panel" ref="msgInputContainer"@keydown.enter.exact="sendMessage($event)" contenteditable="true" spellcheck="false"></div>
  • 实现回车事件函数
sendMessage: function (event) {
        if (event.keyCode === 13) {
            // 阻止编辑框默认生成div事件
            event.preventDefault();
            let msgText = "";
            // 获取输入框下的所有子元素
            let allNodes = event.target.childNodes;
            for(let item of allNodes){
                // 判断当前元素是否为img元素
                if(item.nodeName==="IMG"){
                    msgText += `/${item.alt}/`;
                }
                else{
                    // 获取text节点的值
                    if(item.nodeValue!==null){
                        msgText += item.nodeValue;
                    }
                }
            }
            console.log("消息捕获成功:");
            console.info(msgText);
            // 接口调用,发送消息至服务端

                // 此处省略...

            //
            // 解析接口返回的数据进行渲染
            /**
             * 使用正则表达式解析特定字符串
             *     找到特定字符串出现的位置
             *     遍历配置文件中的json数据,
             *     判断当前关键字是否在配置文件中
             *     获取配置文件中的属性,生成img标签
             *     替换特定字符串为所生成的img标签
             * */
            let separateReg = /(\/[^/]+\/)/g;
            let finalMsgText = "";
            // 将符合条件的字符串放到数组里
            const resultArray = msgText.match(separateReg);
            if(resultArray!==null){
                for (let item of resultArray){
                    // 删除字符串中的/符号
                    item = item.replace(/\//g,"");
                    for (let emojiItem of this.emojiList){
                        // 判断捕获到的字符串与配置文件中的字符串是否相同
                        if(emojiItem.info === item){
                            const imgSrc = require(`../assets/img/emoji/${emojiItem.hover}`);
                            const imgTag = `<img src="${imgSrc}" width="28" height="28" alt="${item}">`;
                            // 替换匹配的字符串为img标签:全局替换
                            msgText = msgText.replace(new RegExp(`/${item}/`,'g'),imgTag);
                        }
                    }
                }
                finalMsgText = msgText;
            }else{
                finalMsgText = msgText;
            }
            console.log("消息解析成功:");
            console.log(finalMsgText);
            const thisSenderMessageObj = {
                "msgText": finalMsgText,
                "msgId": Date.parse(new Date()),
                "avatarSrc": require("../assets/img/avatar.jpg")
            };
            // 渲染页面
            this.senderMessageList.push(thisSenderMessageObj);
            // 清空输入框中的内容
            event.target.innerHTML = "";
        }
    },

踩坑记录

  • 使用removeChild()innerHTML删除可编辑div的子元素

    获取他的所有子元素,进行遍历删除,但是就是删不掉回车所产生的div,也不知道是不是自己写错了,有发现错误的朋友,欢迎评论区留言指正。

    let allNodes = event.target.childNodes;
     // 清空输入框中的内容
    for (let nodesItem of allNodes){
        event.target.removeChild(nodesItem);
    }
    
    // event.target.innerHTML = "";
    

  • 错误的正则表达式

    在渲染解析好的文字和图片的混输内容时,要将/图片描述/转成img标签,看了好久的正则表达式文档研究出的写法,看似没问题实则用不了。最后在群里求助,遇到了一个正则大佬,帮我改进了下,最终实现了我的需求

    // 我的正则
    let separateReg = /^\/.*\/$/g;
    // 大佬帮我改进的正则
    let separateReg = /(\/[^/]+\/)/g;    
    
  • 正确的删除可编辑div中的子元素

    先禁用掉可编辑div的回车生成div事件,然后清空输入框的内容

    event.preventDefault();
    event.target.innerHTML = "";
    
  • 正确解析字符串dom

    v-html的妙用

    <p v-html="item.msgText"/>
    

写在最后

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
  • 本文首发于掘金,如需转载请评论区留言💌