[Scenario realization] How does Vue+element make post comments with emoji? This requirement made me start stepping on the pit in Quill

[Scenario realization] How does Vue+element make post comments with emoji? This requirement made me start stepping on the pit in Quill

Skyfall Giant Pit 1: Quill rich text input content is displayed with text + label after submission

It's not clear what the situation is, let's look at the rendering:

emm.. It looks so weird.

I have also thought of many ways back and forth, but I have overlooked the most primitive one! simplest! Wouldn t it be over if you simply replace the <> tag symbol in the input with an empty string.

Aside from anything else, locate the core code location for this comment.

Let's take a look at this button first:

<div class = "reply-btn-box" style= "text-align:center" > < el-button class = "reply-btn" size = "medium" @ click = "sendQuillComment" type = "primary" > Publish </el-button > </div > copy code

The bound sendQuillComment click event:

sendQuillComment () { if (! this .$refs.postForm.form.content) { this .$message({ showClose : true , type : 'warning' , message : 'quill comment cannot be empty' }) } else { let a = {} let input = document .getElementById( 'quillInput' ) let timeNow = new Date () .getTime () let time = this .dateStr(timeNow) a.name = this .myName a.comment = this .$refs.postForm.form.content.replace( /<[^>]+>/g , '' ) a.headImg = this .myHeader a.time = time a.commentNum = 0 a.like = 0 this .comments.push(a) this .replyComment = '' input.innerHTML = '' } }, Copy code

Smart students can see the key points at a glance:

= a.comment the this . refs.postForm.form.content.replace $ ( /<[^>] +>/G , '' ) copy the code

Let's simplify again, which step is removing the <> tag:

Replace ( /<[^>] +>/G , '' ) copy the code

Isn't this good?

Skyfall Giant Pit 2: Vue+element+Emoji+Quill

The most core is to realize the function of selecting emoji when commenting.

Comments, including secondary comments, are not difficult. Is it a bit naughty to bring emoji?

When everything is over, I will summarize an article "How to realize the post comment function through Vue+element" for your reference, similar to Tieba forum building.

So back to the topic. At first, my idea was to extract the emoji function as a component. Let me talk about the implementation process first.

method one

The first step is to import the JSON file:

const appData = require ( "../static/utils/emoji.json" ); Copy code

The specific content of the JSON file is as follows:

<style lang= "scss" > /* el-popover is at the same level as app, so the local attribute of scoped is invalid */ /* Global style needs to be set */ .el-popover{ height :200px; width:400px; overflow: scroll; overflow-x:auto; } </style> < style scoped > .chatIcon { padding : 0 10px ; font-size : 25px ; } .emotionList { display : flex; flex-wrap : wrap; padding : 5px ; } .emotionItem { width : 10% ; font-size : 20px ; text-align :center; } /*Include the following four kinds of links*/ .emotionItem { text-decoration : none; } /*Normal links that have not been visited*/ .emotionItem :link { text-decoration : none; } /*Visited links*/ .emotionItem :visited { text-decoration : none; } /*Mouse over ( hover ) link*/.emotionItem :hover { text-decoration : none; } /* The link being clicked*/ .emotionItem :active { text-decoration : none; } </style > Copy code

Step 2: template

The emoticon box component is triggered by the slot button; the input box is a textarea, and we need to insert the selected emoticon after the click on the textarea cursor:

<div class = "chatIcon" > < el-popover placement = "top-start" width = "400" trigger = "click" class = "emoBox" > < div class = "emotionList" > < a href = "javascript: void(0);" @ click = "getEmo(index)" v-for = "(item,index) in faceList" :key = "index" class = "emotionItem" > {{item}} </a > </div > < el-button class = "emotionSelect" icon = "iconfont icon-biaoqing" slot = "reference" > </el-button > </el-popover > </div> < el-input v-model = "textarea" class = "chatText" resize = "none" type = "textarea" id = 'textarea' rows = "5" @ keyup.enter.native = "sendInfo" > </el -input > copy code

The third step: css

Because el-popover is special, you need to set the el-popover style globally to prevent global pollution:

<style lang= "scss" > /* el-popover is at the same level as app, so the local attribute of scoped is invalid */ /* Global style needs to be set */ .el-popover{ height :200px; width:400px; overflow: scroll; overflow-x:auto; } </style> < style scoped > .chatIcon { padding : 0 10px ; font-size : 25px ; } .emotionList { display : flex; flex-wrap : wrap; padding : 5px ; } .emotionItem { width : 10% ; font-size : 20px ; text-align :center; } /*Include the following four kinds of links*/ .emotionItem { text-decoration : none; } /*Normal links that have not been visited*/ .emotionItem :link { text-decoration : none; } /*Visited links*/ .emotionItem :visited { text-decoration : none; } /*Mouse over ( hover ) link*/.emotionItem :hover { text-decoration : none; } /* The link being clicked*/ .emotionItem :active { text-decoration : none; } </style > Copy code

Step 4: script

mounted () { for ( let i in appData){ this .faceList.push(appData[i].char); } }, data () { return { faceList : [], textarea : "" }; }, method () { getEmo ( index ) { var textArea = document .getElementById( 'textarea' ); function changeSelectedText ( obj, str ) { if ( window .getSelection) { //Non-IE browser textArea.setRangeText(str); //When the text is not selected, reset the cursor position textArea.selectionStart += str.length; textArea.focus() } else if ( document .selection) { //IE browser obj.focus(); var sel = document .selection.createRange(); sel.text = str; } } changeSelectedText(textArea, this .faceList[index]); this .textarea=textArea.value; //To synchronize the data in data //console.log(this.faceList[index]); return ; }, } Copy code

After writing Method 1, the question that followed was: What expression I want to use must be added to the JSON file first, which is very inconvenient, so method 2 appeared.

Method 2: Use quill-emoji

Step 1: Import and register

Import DeDent from 'DeDent' Import {Quill, quillEditor} from 'VUE-Quill-Editor' Import quillEmoji from 'Quill-Emoji' Import 'Quill-Emoji/dist/Quill-emoji.css' Quill.register( 'modules/quillEmoji' , quillEmoji) copy the code

Don't forget to install these libraries

The second step:

export default { components : { Drawer, quillEditor }, data () { return { content : dedent ` <p><span data-name="grinning"><span contenteditable="false"><span class="ap ap-grinning"></span></span></span></p> ` , editorOption : { theme : 'snow' , modules : { 'emoji-toolbar' : true , 'emoji-shortname' : true , toolbar : { container : [ 'emoji' ] } } } } } } Copy code

Step 3: Application

<quill-editor class = "editor" v-model= "content" :options= "editorOption" /> Copy code

How rich is the emoji in Quill?

It has everything, Quill smells so good!

It is recommended that you use method two, so that you can avoid the giant pit one, and there will be no more <> tag characters in the comments.