So implementieren Sie die @person-Funktion über Vue

So implementieren Sie die @person-Funktion über Vue

Dieser Artikel verwendet Vue und fügt Mausklickereignisse und einige kleine Seitenoptimierungen hinzu

Grundstruktur

Erstellen Sie eine sandBox.vue-Datei, um die Grundstruktur der Funktion zu schreiben

 <div Klasse="Inhalt">
    <!--Textfeld-->
    <div
      Klasse="Herausgeber"
      ref="divRef"
      Inhalt editierbar
      @keyup="handkeKeyUp"
      @keydown="Tastennachunten bedienen"
    ></div>
    <!--Optionen-->
    <AtDialog
      v-if="Dialog anzeigen"
      :sichtbar="Dialog anzeigen"
      :position="Position"
      :Abfragezeichenfolge="Abfragezeichenfolge"
      @onPickUser="Benutzer auswählen"
      @onHide="handleHide"
      @onShow="Anzeigengriff"
    ></AtDialog>
  </div>
<Skript>
importiere AtDialog aus '../components/AtDialog'
Standard exportieren {
  Name: 'sandBox',
  Komponenten: { AtDialog },
  Daten () {
    zurückkehren {
      node: '', // Den Knoten abrufen user: '', // Den Inhalt des ausgewählten Elements endIndex: '', // Die letzte Cursorposition queryString: '', // Suchwert showDialog: false, // Ob das Popup-Fenster angezeigt werden soll position: {
        x: 0,
        j: 0
      }//Anzeigeposition des Popup-Fensters}
  },
  Methoden: {
    // Cursorposition abrufen getCursorIndex () {
      const Auswahl = Fenster.getSelection()
      return selection.focusOffset //Wählen Sie den Offset von focusNode am Anfang},
    //Knoten abrufen getRangeNode () {
      const Auswahl = Fenster.getSelection()
      return selection.focusNode // ausgewählter Endknoten},
    // Die Stelle, an der das Popup-Fenster erscheint getRangeRect () {
      const Auswahl = Fenster.getSelection()
      const range = selection.getRangeAt(0) // ist ein generisches Objekt zum Verwalten von Auswahlbereichen const rect = range.getClientRects()[0] // Wähle einen Text aus und erhalte den Bereich des ausgewählten Textes const LINE_HEIGHT = 30
      zurückkehren {
        x: Rechteck.x,
        y: Rechteck.y + Zeilenhöhe
      }
    },
    // Ob @ angezeigt werden soll
    zeigeAt() {
      const node = this.getRangeNode()
      wenn (!node || node.nodeType !== Node.TEXT_NODE) ​​​​false zurückgeben
      const Inhalt = node.textContent || ''
      const regx = /@([^@\s]*)$/
      const match = regx.exec(content.slice(0, this.getCursorIndex()))
      Rückgabewert: Übereinstimmung und Übereinstimmungslänge === 2
    },
    // Holen Sie sich @user getAtUser () {
      const content = this.getRangeNode().textContent || ''
      const regx = /@([^@\s]*)$/
      const match = regx.exec(content.slice(0, this.getCursorIndex()))
      wenn (Match && Matchlänge === 2) {
        Rückspiel[1]
      }
      Rückgabe undefiniert
    },
    // Erstelle ein Label createAtButton (Benutzer) {
      const btn = document.createElement('span')
      btn.style.display = "Inline-Block"
      btn.dataset.user = JSON.stringify(Benutzer)
      btn.className = "at-Schaltfläche"
      btn.contentEditable = "falsch"
      btn.textContent = `@${Benutzername}`
      const Wrapper = Dokument.createElement('span')
      wrapper.style.display = "Inline-Block"
      wrapper.contentEditable = "false"
      const spaceElem = document.createElement('span')
      spaceElem.style.whiteSpace = "vor"
      spaceElem.textContent = "\u200b"
      spaceElem.contentEditable = "false"
      const clonedSpaceElem = spaceElem.cloneNode(true)
      Wrapper.AnhängenUntergeordnetesElement(spaceElem)
      Wrapper.AnhängenKind(btn)
      Wrapper.appendChild(geklontesSpaceElem)
      Rücksendeverpackung
    },
    replaceString (roh, Ersetzer) {
      returniere raw.replace(/@([^@\s]*)$/, Ersetzer)
    },
    // Füge @tag replaceAtUser (Benutzer) { ein.
      const node = dieser.knoten
      if (Knoten && Benutzer) {
        const Inhalt = node.textContent || ''
        const endIndex = this.endIndex
        const preSlice = this.replaceString(content.slice(0, endIndex), '')
        const restSlice = content.slice(endIndex)
        const parentNode = node.parentNode
        const nextNode = node.nextSibling
        const vorherigerTextNode = neuer Text(preSlice)
        const nextTextNode = neuer Text('\u200b' + restSlice) // 0 breite Zeichen hinzufügen const atButton = this.createAtButton(Benutzer)
        übergeordneter Knoten.entfernenUntergeordnetesElement(Knoten)
        // In das Textfeld einfügen if (nextNode) {
          parentNode.insertBefore(vorherigerTextNode, nächsterNode)
          parentNode.insertBefore(atButton, nächsterNode)
          parentNode.insertBefore(nächsterTextNode, nächsterNode)
        } anders {
          übergeordneter Knoten.anhängendesKind(vorherigerTextknoten)
          parentNode.anhängenKind(atButton)
          parentNode.appendChild(nächsterTextNode)
        }
        // Cursorposition zurücksetzen const range = new Range()
        const Auswahl = Fenster.getSelection()
        range.setStart(nächsterTextNode, 0)
        range.setEnd(nächsterTextNode, 0)
        Auswahl.AlleBereicheentfernen()
        Auswahl.addRange(Bereich)
      }
    },
    //Tastatur hoch eventhandkeKeyUp () {
      wenn (this.showAt()) {
        const node = this.getRangeNode()
        const endIndex = this.getCursorIndex()
        dieser.Knoten = Knoten
        dies.endIndex = endIndex
        diese.position = diese.getRangeRect()
        this.queryString = this.getAtUser() || ''
        this.showDialog = true
      } anders {
        this.showDialog = false
      }
    },
    //Tastaturkürzel handleKeyDown (e) {
      wenn (dieser.showDialog) {
        wenn (e.code === 'PfeilNachOben' ||
          e.code === 'Pfeil nach unten' ||
          e.code === 'Eingeben') {
          e.preventDefault()
        }
      }
    },
    // Verstecke das Auswahlfeld nach dem Einfügen des Tags handlePickUser (user) {
      this.replaceAtUser(Benutzer)
      this.user = Benutzer
      this.showDialog = false
    },
    //Auswahlfeld ausblenden handleHide () {
      this.showDialog = false
    },
    //Zeige das Auswahlfeld handleShow () {
      this.showDialog = true
    }
  }
}
</Skript>
 
<style scoped lang="scss">
  .Inhalt {
    Schriftfamilie: serifenlos;
    h1{
      Textausrichtung: zentriert;
    }
  }
  .Editor {
    Rand: 0 automatisch;
    Breite: 600px;
    Höhe: 150px;
    Hintergrund: #fff;
    Rand: 1px durchgehend blau;
    Rahmenradius: 5px;
    Textausrichtung: links;
    Polsterung: 10px;
    Überlauf: automatisch;
    Zeilenhöhe: 30px;
    &:Fokus {
      Gliederung: keine;
    }
  }
</Stil>

Wenn ein Klickereignis hinzugefügt wird, müssen die Knoten- und Cursorposition im [Keyboard Up Event] ermittelt und in den Daten gespeichert werden

 //Tastatur hoch eventhandkeKeyUp () {
      wenn (this.showAt()) {
        const node = this.getRangeNode() // Den Knoten abrufen const endIndex = this.getCursorIndex() // Die Cursorposition abrufen this.node = node 
        dies.endIndex = endIndex 
        diese.position = diese.getRangeRect()
        this.queryString = this.getAtUser() || ''
        this.showDialog = true
      } anders {
        this.showDialog = false
      }
    },

Erstellen Sie eine neue Komponente und bearbeiten Sie die Popup-Optionen 

<Vorlage>
<div
  Klasse="Wrapper"
  :style="{position:'fest',oben:position.y +'px',links:position.x+'px'}">
  <div v-if="!mockList.length" class="empty">Keine Suchergebnisse</div>
  <div
    v-für="(Element,i) in MockList"
    :Schlüssel="Artikel-ID"
    Klasse="Artikel"
    :Klasse="{'aktiv': i === index}"
    ref="BenutzerRef"
    @click="klickenBei($event,item)"
    @mouseenter="hoverAt(i)"
  >
    <div Klasse="name">{{item.name}}</div>
  </div>
</div>
</Vorlage>
 
<Skript>
const mockData = [
  { Name: 'HTML', ID: 'HTML' },
  { Name: "CSS", ID: "CSS" },
  { Name: 'Java', ID: 'Java' },
  { Name: 'JavaScript', ID: 'JavaScript' }
]
Standard exportieren {
  Name: "AtDialog",
  Requisiten: {
    sichtbar: Boolean,
    Position: Objekt,
    queryString: Zeichenfolge
  },
  Daten () {
    zurückkehren {
      Benutzer: [],
      Index: -1,
      mockList: mockData
    }
  },
  betrachten:
    Abfragezeichenfolge (Wert) {
      Wert? this.mockList = mockData.filter(({ name }) => name.startsWith(val)) : this.mockList = mockData.slice(0)
    }
  },
  montiert () {
    document.addEventListener('keyup', dieser.keyDownHandler)
  },
  zerstört () {
    document.removeEventListener('keyup', this.keyDownHandler)
  },
  Methoden: {
    keyDownHandler (e) {
      wenn (e.code === 'Escape') {
        dies.$emit('onHide')
        zurückkehren
      }
      //Tastatur gedrückt => ↓
      wenn (e.code === 'PfeilNachUnten') {
        wenn (dieser.index >= diese.mockList.length - 1) {
          dieser.index = 0
        } anders {
          dieser.index = dieser.index + 1
        }
      }
      //Tastatur gedrückt => ↑
      wenn (e.code === 'PfeilNachOben') {
        wenn (dieser.index <= 0) {
          dieser.index = diese.mockList.length - 1
        } anders {
          dieser.index = dieser.index - 1
        }
      }
      //Tastatur gedrückt => Enterif (e.code === 'Enter') {
        wenn (diese.mockList.length) {
          const Benutzer = {
            Name: diese.mockList[dieser.index].name,
            ID: diese.mockList[diesen.index].id
          }
          dies.$emit('onPickUser', Benutzer)
          dieser.index = -1
        }
      }
    },
    clickAt (e, Artikel) {
      const Benutzer = {
        Name: Artikelname,
        ID: Artikel-ID
      }
      dies.$emit('onPickUser', Benutzer)
      dieser.index = -1
    },
    hoverAt (Index) {
      dieser.index = index
    }
  }
}
</Skript>
 
<style scoped lang="scss">
  .wrapper {
    Breite: 238px;
    Rand: 1px durchgezogen #e4e7ed;
    Rahmenradius: 4px;
    Hintergrundfarbe: #fff;
    Kastenschatten: 0 2px 12px 0 RGB (0 0 0 / 10 %);
    Box-Größe: Rahmenbox;
    Polsterung: 6px 0;
  }
  .leer{
    Schriftgröße: 14px;
    Polsterung: 0 20px;
    Farbe: #999;
  }
  .Artikel {
    Schriftgröße: 14px;
    Polsterung: 0 20px;
    Zeilenhöhe: 34px;
    Cursor: Zeiger;
    Farbe: #606266;
    &.aktiv {
      Hintergrund: #f5f7fa;
      Farbe: blau;
      .Ausweis {
        Farbe: blau;
      }
    }
    &:erstes-Kind {
      Rahmenradius: 5px 5px 0 0;
    }
    &:letztes-Kind {
      Rahmenradius: 0 0 5px 5px;
    }
    .Ausweis {
      Schriftgröße: 12px;
      Farbe: rgb(83, 81, 81);
    }
  }
</Stil>

Oben finden Sie Einzelheiten zur Implementierung der @人-Funktion über Vue. Weitere Informationen zur Vue @人-Funktion finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Verwenden Sie vue3, um ein Mensch-Katze-Kommunikations-Applet zu implementieren
  • Realisierung der intelligenten Roboter-Antwortfunktion von Vue+AI
  • Vue.js implementiert h5-Roboter-Chat (Betaversion)
  • Vue+tracking.js implementiert die Gesichtserkennungsfunktion im Front-End
  • Mehrpersonen-Online-Chatroom basierend auf Vue und WebSocket
  • Eine Single-Page-Anwendungsfunktion, die mobiles QQ basierend auf Vue2 imitiert (Zugriff auf Chatbot)

<<:  Bootstrap 3.0 Studiennotizen CSS-bezogene Ergänzung

>>:  Tutorial zur Samba-Konfiguration für die Dateifreigabe im Linux-System

Artikel empfehlen

Verwenden Sie thead, tfoot und tbody, um eine Tabelle zu erstellen

Manche Leute verwenden diese drei Tags auf pervers...

Richtige Verwendung der Vue-Funktion Anti-Shake und Throttling

Vorwort 1. Entprellen: Nach dem Auslösen eines Ho...

Beispiele für optimistisches und pessimistisches Sperren in MySQL

Die Aufgabe der Parallelitätskontrolle in einem D...

So installieren Sie MySQL auf CentOS und richten den Fernzugriff ein

1. Laden Sie die MySQL-Repo-Quelle herunter $ wge...

Detaillierte Erläuterung der kombinierten MySQL-Abfrage

Verwenden von UNION Die meisten SQL-Abfragen best...

Detaillierte Erläuterung des MySQL-Isolationsebenen-Operationsprozesses (cmd)

Beispielvorgang für nicht festgeschriebenes Lesen...

SQL-Methode zum Berechnen der Zeitstempeldifferenz

SQL-Methode zum Berechnen der Zeitstempeldifferen...

Detaillierte Analyse der MySQL-Sperrblockierung

Bei der täglichen Wartung werden Threads häufig b...

So verwenden Sie CSS-Overflow: Hidden (Überlauf ausblenden und Floats löschen)

Überlauf ausblenden Damit ist gemeint, dass Text-...

Regeln für die Gestaltung des Anmeldeformulars

Ich habe „Patterns for Sign Up & Ramp Up“ vor ...