Textarea-remind textarea to remind

Through this sharing, we know that
1. The idea of developing AT functions based on Textarea can help people to avoid some detours when developing similar scenario components in the futureCopy the code

Components based on vuE-AT customized development of completed business components, the wheel inside is divided into two cases

  1. At function developed based on div contentEnable attribute
  2. At function developed based on Textarea

Why did you choose textarea?

For example, if you want to leave div contentEnable behind, you might have more problems with it.

Some problems to be expected: copy and paste, as well as custom tags, cursor movement, etc

Ideas and problems encountered

Textarea is based on yes highlighting

It is not highlighted in the Textarea layer, but in the rendering layer underneath the Textarea

Referring to the react-mentions demo, the basic principle is that textarea is positioned to overlap exactly with the bottom rendering layer, exactly the same font size, exactly the same font style, and then the background layer with the background color

The text layer is positioned by modification, above the rendering layer

Rendering layerBy CSS propertieswhite-space: pre-wrapPositioning to complete

I made a sketch

Problems encountered:

1. Division of paragraph names

The basic idea is to partition literal names according to the specified usage rules

Initially, wrap the span note with the name of the partitioned person and output it to the render layer once through V-HTML, but the background layer of the render layer will flash frequently as the text continues to be typed

Solution:

Conversion to v-for output array rendering, so that when vUE output virtual DOM, compared to the previous input text text virtual DOM content is changed, it will not be re-rendered.

Determine if the person name in the front-end pool is present once during a single rendering, and then highlight it.

Computed: {matchingUserNameText: {get () {// renderLayerText: renderLayerText // at: current at symbol let {renderLayerText: Text, at} = this let tempContent = "let tempArray = [] for (let index = 0, len = text.length; index < len; index++) { const char = text[index] if (char === at && tempContent) { tempArray.push(tempContent) tempContent = '' } if (char === SPACE && tempContent) { tempArray.push(tempContent) tempContent = '' } tempContent += char } if (tempContent) { tempArray.push(tempContent) tempContent = '' } return tempArray }, set (val) { this.matchingUserNameText = val } } }Copy the code

2. The textarea layer directly keeps pressing enter, and the cursor is stuck only when the cursor occupies a single line of text at the bottom, which will cause dislocation with the rendering layer

As long as no single cursor occupies the bottom row, the render layer is triggered to render successfully

Solution:

A

tag is placed directly at the end of the render layer output, so that each render layer will be rendered according to the position of the < BR > tag

3. During Chinese input, there are candidate words that fail to fall into textarea, which will also cause dislocation of rendering

Solution:

Prepare two layers of text objects, one layer for user input in text objects, and one layer for rendering text objects

The home input synchronizes the rendering layer text object every time the text changes. The key is to listen for the CompositionUpdate event on the Textarea object

/ / processing input method input text not defeated candidate for input box of time synchronization of background rendering layer onCompositionupdate (textarea) {textarea. AddEventListener (' compositionupdate ', (event) => {// text layer text object const {text} = this // get the current cursor position const index = textarea.selectionStart // Split the first half of the text const startStr = String(text).substr(0, Const endStr = String(text). Substr (index) // Output to computed matchingUserNameText this.renderLayerText  = `${startStr}${event.data}${endStr}` }) }Copy the code