Vue で @person 関数を実装する方法

Vue で @person 関数を実装する方法

この記事ではvueを使用し、マウスクリックイベントといくつかの小さなページの最適化を追加します。

基本構造

関数の基本構造を記述するためのsandBox.vueファイルを作成する

 <div class="content">
    <!--テキストボックス-->
    <div
      クラス="エディター"
      ref="divRef"
      コンテンツ編集可能
      @keyup="handkeKeyUp"
      @keydown="ハンドルキーダウン"
    </div>
    <!--オプション-->
    <ダイアログ
      v-if="showDialog"
      :visible="ダイアログを表示"
      :position="位置"
      :queryString="クエリ文字列"
      @onPickUser="ハンドルPickUser"
      @onHide="ハンドルを非表示"
      @onShow="ハンドル表示"
    </ダイアログ>
  </div>
<スクリプト>
'../components/AtDialog' から AtDialog をインポートします。
エクスポートデフォルト{
  名前: 'サンドボックス',
  コンポーネント: { AtDialog },
  データ () {
    戻る {
      node: '', // ノードを取得 user: '', // 選択された項目の内容 endIndex: '', // 最後のカーソル位置 queryString: '', // 検索値 showDialog: false, // ポップアップウィンドウを表示するかどうか position: {
        x: 0,
        年: 0
      }//ポップアップウィンドウの表示位置}
  },
  メソッド: {
    // カーソル位置を取得する getCursorIndex () {
      定数選択 = window.getSelection()
      return selection.focusOffset // 先頭の focusNode のオフセットを選択します},
    // ノードを取得する getRangeNode () {
      定数選択 = window.getSelection()
      return selection.focusNode // 選択された終了ノード},
    // ポップアップウィンドウが表示される場所 getRangeRect () {
      定数選択 = window.getSelection()
      const range = selection.getRangeAt(0) // 選択範囲を管理するための汎用オブジェクトです const rect = range.getClientRects()[0] // テキストを選択し、選択されたテキストの範囲を取得します const LINE_HEIGHT = 30
      戻る {
        x: 矩形x、
        y: rect.y + LINE_HEIGHT
      }
    },
    // @を表示するかどうか
    表示At() {
      定数ノード = this.getRangeNode()
      if (!node || node.nodeType !== Node.TEXT_NODE) ​​falseを返す
      定数コンテンツ = node.textContent || ''
      定数regx = /@([^@\s]*)$/
      定数マッチ = regx.exec(content.slice(0, this.getCursorIndex()))
      マッチ&&match.length === 2を返す
    },
    // @user を取得する getAtUser () {
      const コンテンツ = this.getRangeNode().textContent || ''
      定数regx = /@([^@\s]*)$/
      定数マッチ = regx.exec(content.slice(0, this.getCursorIndex()))
      マッチ&&マッチ.長さ=== 2の場合{
        リターンマッチ[1]
      }
      未定義を返す
    },
    // ラベルを作成する createAtButton (user) {
      const btn = document.createElement('span')
      btn.style.display = 'インラインブロック'
      btn.dataset.user = JSON.stringify(user)
      btn.className = 'at-button'
      btn.contentEditable = 'false'
      btn.textContent = `@${user.name}`
      const ラッパー = document.createElement('span')
      wrapper.style.display = 'インラインブロック'
      wrapper.contentEditable = 'false'
      定数スペース要素 = document.createElement('span')
      spaceElem.style.whiteSpace = 'pre'
      スペース要素.textContent = '\u200b'
      spaceElem.contentEditable = 'false'
      const clonedSpaceElem = spaceElem.cloneNode(true)
      wrapper.appendChild(スペース要素)
      wrapper.appendChild(btn)
      wrapper.appendChild(クローンされたスペース要素)
      返品ラッパー
    },
    replaceString (raw, replacer) {
      raw.replace(/@([^@\s]*)$/, replacer) を返します
    },
    // @ タグを挿入 replaceAtUser (user) {
      定数ノード = this.node
      if (ノード && ユーザー) {
        定数コンテンツ = node.textContent || ''
        定数 endIndex = this.endIndex
        const preSlice = this.replaceString(content.slice(0, endIndex), '')
        const restSlice = content.slice(endIndex)
        定数 parentNode = ノード.parentNode
        定数 nextNode = node.nextSibling
        const previousTextNode = 新しい Text(preSlice)
        const nextTextNode = new Text('\u200b' + restSlice) // 0 個のワイド文字を追加 const atButton = this.createAtButton(user)
        親ノードの子ノードを削除します。
        // テキストボックスに挿入 if (nextNode) {
          親ノード。前のテキストノード、次のノードの前に挿入します。
          親ノード。ボタンの前に挿入します。次のノード。
          親ノード。次のテキストノードの前に挿入します。
        } それ以外 {
          親ノード.appendChild(前のテキストノード)
          親ノード.appendChild(ボタン上)
          親ノード。次のテキストノードに子を追加します。
        }
        // カーソル位置をリセットする const range = new Range()
        定数選択 = window.getSelection()
        範囲.setStart(次のテキストノード、0)
        範囲.setEnd(次のテキストノード、0)
        選択範囲をすべて削除()
        選択範囲を追加します(範囲)
      }
    },
    //キーボードアップイベントhandkeKeyUp() {
      if (this.showAt()) {
        定数ノード = this.getRangeNode()
        定数 endIndex = this.getCursorIndex()
        this.node = ノード
        this.endIndex = 終了インデックス
        this.position = this.getRangeRect()
        this.queryString = this.getAtUser() || ''
        this.showDialog = true
      } それ以外 {
        this.showDialog = false
      }
    },
    //キーボード押下イベント handleKeyDown (e) {
      ダイアログを表示する
        if (e.code === 'ArrowUp' ||
          e.code === '矢印下' ||
          e.code === 'Enter') {
          e.preventDefault()
        }
      }
    },
    // タグを挿入した後、選択ボックスを非表示にする handlePickUser (user) {
      this.replaceAtUser(ユーザー)
      this.user = ユーザー
      this.showDialog = false
    },
    //選択ボックスを非表示にするhandleHide() {
      this.showDialog = false
    },
    // 選択ボックスを表示する handleShow () {
      this.showDialog = true
    }
  }
}
</スクリプト>
 
<スタイル スコープ lang="scss">
  。コンテンツ {
    フォントファミリー: サンセリフ;
    h1{
      テキスト配置: 中央;
    }
  }
  .エディター{
    マージン: 0 自動;
    幅: 600ピクセル;
    高さ: 150px;
    背景: #fff;
    境界線: 1px 青
    境界線の半径: 5px;
    テキスト配置: 左;
    パディング: 10px;
    オーバーフロー:自動;
    行の高さ: 30px;
    &:集中 {
      アウトライン: なし;
    }
  }
</スタイル>

クリックイベントが追加された場合、ノードとカーソルの位置は[キーボードアップイベント]で取得され、データに保存される必要があります。

 //キーボードアップイベントhandkeKeyUp() {
      if (this.showAt()) {
        const node = this.getRangeNode() // ノードを取得 const endIndex = this.getCursorIndex() // カーソルの位置を取得 this.node = node 
        this.endIndex = 終了インデックス 
        this.position = this.getRangeRect()
        this.queryString = this.getAtUser() || ''
        this.showDialog = true
      } それ以外 {
        this.showDialog = false
      }
    },

新しいコンポーネントを作成し、ポップアップオプションを編集します 

<テンプレート>
<div
  クラス="ラッパー"
  :style="{位置:'固定'、上:位置.y +'px'、左:位置.x+'px'}">
  <div v-if="!mockList.length" class="empty">検索結果はありません</div>
  <div
    v-for="(item,i) in mockList"
    :key="アイテムID"
    クラス="アイテム"
    :class="{'アクティブ': i === インデックス}"
    ref="ユーザー参照"
    @click="clickAt($event,item)"
    @mouseenter="hoverAt(i)"
  >
    <div class="name">{{item.name}}</div>
  </div>
</div>
</テンプレート>
 
<スクリプト>
const モックデータ = [
  { 名前: 'HTML'、 ID: 'HTML' },
  { 名前: 'CSS'、 ID: 'CSS' },
  { 名前: 'Java'、 ID: 'Java' },
  { 名前: 'JavaScript'、 ID: 'JavaScript' }
]
エクスポートデフォルト{
  名前: 'AtDialog',
  小道具: {
    表示: ブール値、
    位置: オブジェクト、
    クエリ文字列: 文字列
  },
  データ () {
    戻る {
      ユーザー: [],
      インデックス: -1,
      モックリスト: モックデータ
    }
  },
  時計:
    クエリ文字列 (値) {
      val ? this.mockList = mockData.filter(({ name }) => name.startsWith(val)) : this.mockList = mockData.slice(0)
    }
  },
  マウントされた(){
    document.addEventListener('keyup'、this.keyDownHandler) は、
  },
  破壊された(){
    document.removeEventListener('keyup'、this.keyDownHandler) を削除します。
  },
  メソッド: {
    キーダウンハンドラ(e) {
      if (e.code === 'エスケープ') {
        これを$emit('onHide')
        戻る
      }
      //キーボードが押された => ↓
      if (e.code === 'ArrowDown') {
        this.index >= this.mockList.length - 1 の場合 {
          this.index = 0
        } それ以外 {
          this.index = this.index + 1
        }
      }
      //キーボードが押された => ↑
      if (e.code === 'ArrowUp') {
        (this.index <= 0)の場合{
          this.index = this.mockList.length - 1
        } それ以外 {
          this.index = this.index - 1
        }
      }
      //キーボードが押された => Enterif (e.code === 'Enter') {
        if (this.mockList.length) {
          定数ユーザー = {
            名前: this.mockList[this.index].name,
            id: this.mockList[this.index].id
          }
          this.$emit('onPickUser', ユーザー)
          this.index = -1
        }
      }
    },
    clickAt (e, アイテム) {
      定数ユーザー = {
        名前: アイテム名、
        id: アイテム.id
      }
      this.$emit('onPickUser', ユーザー)
      this.index = -1
    },
    hoverAt (インデックス) {
      this.index = インデックス
    }
  }
}
</スクリプト>
 
<スタイル スコープ lang="scss">
  .ラッパー{
    幅: 238ピクセル;
    境界線: 1px 実線 #e4e7ed;
    境界線の半径: 4px;
    背景色: #fff;
    ボックスシャドウ: 0 2px 12px 0 rgb(0 0 0 / 10%);
    ボックスのサイズ: 境界線ボックス;
    パディング: 6px 0;
  }
  。空の{
    フォントサイズ: 14px;
    パディング: 0 20px;
    色: #999;
  }
  。アイテム {
    フォントサイズ: 14px;
    パディング: 0 20px;
    行の高さ: 34px;
    カーソル: ポインタ;
    色: #606266;
    &。アクティブ {
      背景: #f5f7fa;
      色: 青;
      .id {
        色: 青;
      }
    }
    &:最初の子 {
      境界線の半径: 5px 5px 0 0;
    }
    &:最後の子 {
      境界線の半径: 0 0 5px 5px;
    }
    .id {
      フォントサイズ: 12px;
      色: rgb(83, 81, 81);
    }
  }
</スタイル>

以上がVueで@人機能を実装する方法の詳細です。Vueの@人機能の詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • vue3を使用して人間と猫のコミュニケーションアプレットを実装する
  • Vue+AI知能ロボット返信機能の実現
  • Vue.js は h5 ロボット チャットを実装します (ベータ版)
  • Vue+tracking.jsはフロントエンドの顔検出機能を実装します
  • Vue と Websocket をベースにした複数人用オンライン チャット ルーム
  • Vue2ベースのモバイルQQを模倣したシングルページアプリケーション機能(チャットボットへのアクセス)

<<:  Bootstrap 3.0 学習ノート CSS関連補足

>>:  Linux システムファイル共有 samba 設定チュートリアル

推薦する

初心者がHTMLタグを学ぶ(1)

初心者は、いくつかの HTML タグを理解することで HTML を学習できます。この入門書は、初心者...

CentOS の起動時に RabbitMq ソフトウェアを自動的に起動する方法

1. /etc/init.dディレクトリに新しいrabbitmqを作成します。 [root@loca...

Dockerイメージの作成、アップロード、プル、デプロイを理解するための記事

目次1. 画像1. 鏡とは何ですか? 2. 画像の構成と目的(1) Dockerファイル(2)スクラ...

レスポンシブ Web デザイン手法を実装し、ウォーターフォール モデルに別れを告げる 5 つのステップ (グラフィック チュートリアル)

次の Web デザイン プロジェクトはレスポンシブにする必要があると上司をようやく納得させることがで...

XHTML 入門チュートリアル: よく使われる XHTML タグ

<br />記事と同様に、Web ページにも明確な段落と重要度の異なるタイトルが必要です...

jQuery を使用してカルーセル効果を実装する

この記事では、jQueryでカルーセルチャートを実装するための具体的なコードを参考までに共有します。...

CSS3 列を使用したカード ウォーターフォール レイアウトを実装するためのサンプル コード

この記事では、カード ウォーターフォール レイアウトを実現するための CSS3 列のサンプル コード...

HTML テーブル マークアップ チュートリアル (38): ヘッダーの境界線の色属性 BORDERCOLOR

テーブルを美しくするために、ヘッダーに異なる境界線の色を設定できます。基本的な構文<TH 境界...

Vue3 における ref と reactive の詳細な説明と拡張

目次1. 参照と反応1. 反応的2.参照2. shallowRef と shallowReactiv...

要素テーブルの行と列のドラッグを実装する例

要素 ui テーブルにはドラッグ アンド ドロップによる並べ替え機能が組み込まれておらず、サードパー...

CentOS7.5 の MySQL8.0.19 のインストールチュートリアルの詳細な手順

1. はじめにこの記事には MySQL インストール部分のスクリーンショットがないので、ある程度の基...

MySQLでビューを作成する方法

基本的な構文CREATE VIEW ステートメントを使用してビューを作成できます。構文の形式は次のと...

純粋な CSS で「テキストオーバーフローの切り捨てと省略」を実装するいくつかの方法

私たちの日常的な開発作業では、テキストのオーバーフロー、切り捨て、省略は、考慮する必要がある非常に一...

ポータルサイト再設計のユーザーエクスペリエンス

<br />2006年10月12日のNetEaseの新ホームページの公開から、2008年...

Vue でインデックスをキー属性値として使用することが推奨されないのはなぜですか?

目次序文キーの役割差分アルゴリズムにおけるキーの役割ヘッドノードを同期するテールノードを同期する新し...