Vue реализует синтаксический анализ и рендеринг пользовательских идентификаторов в строках 🎩

Vue.js
Vue реализует синтаксический анализ и рендеринг пользовательских идентификаторов в строках 🎩

Сталкиваясь с трудностями, сохраняйте спокойствие и смело встречайте их, и вы всегда найдете прорыв.

предисловие

Есть такой сценарий: реализованоСмешанный текст и изображения, в это время есть div вimg-тега такжеСлово, то мы хотим отправить их наСервер, а затем сервер отправляет контент, который мы отправляем каждому пользователю. Какой формат данных нужен серверу? Наш клиент получает данные, возвращенные сервером, как их отобразитьстраница? Далее я поделюсь с вами своим решением, сначала позвольте вам увидеть окончательный эффект

Реализовать идеи

  • Прослушивание событий возврата каретки
  • Получить все дочерние элементы поля ввода
  • перебирать все дочерние элементы
  • Найти теги img и текстовые узлы
  • Получите идентификатор alt тега img и разберите идентификатор 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 = "";
    

  • неправильное регулярное выражение

    При рендеринге смешанного содержимого разобранного текста и изображений необходимо преобразовать /image description/ в тег img Метод записи, разработанный после прочтения документа с регулярным выражением в течение длительного времени, вроде бы не проблема, но он не используется. Наконец, я обратился за помощью в группу, и я встретил постоянного начальника, который помог мне стать лучше и, наконец, осознал мои потребности.

    // 我的正则
    let separateReg = /^\/.*\/$/g;
    // 大佬帮我改进的正则
    let separateReg = /(\/[^/]+\/)/g;    
    
  • Правильно удалить дочерние элементы в редактируемом div

    Сначала отключите возврат каретки редактируемого div, чтобы сгенерировать событие div, а затем очистите содержимое поля ввода.

    event.preventDefault();
    event.target.innerHTML = "";
    
  • Правильно разобрать строку dom

    Волшебное использование v-html

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

напиши в конце

  • Если в статье есть ошибки, исправьте их в комментариях, если статья вам поможет, ставьте лайк и подписывайтесь 😊
  • Эта статья была впервые опубликована в Nuggets, если вам нужно перепечатать, пожалуйста, оставьте сообщение в области комментариев 💌