点击@和输入@,防微信@功能

点击@和输入@,防微信@功能

一、具体效果图

在这里插入图片描述

二、具体代码

npm i vue-quill-editor quill-mmention --save
<template>
  <div id="at">
    <!-- state & action -->
    <van-row>
      <van-col span="24">输入方式:{{ isChineseInputMethod ? '中文输入' : '英文输入' }}</van-col>
      <!-- <van-col span="24">是否为 中文输入法状态:{{ isChineseInputMethod }}</van-col> -->
      <!-- <van-col span="24">是否为 点击@按钮打开菜单弹框:: {{ isClickMention }}</van-col> -->
      <van-col span="24">@列表出现方式:{{ isClickMention ? '点击@' : '手动输入@' }}</van-col>
    </van-row>
    <van-row>
      <van-col span="24">
        打开@菜单弹框:
        <van-button type="info" size="small" @click="openPopup">Show @ Menu</van-button>
      </van-col>
      <van-col span="24">
        以编程方式@某人:
        <van-button type="warning" size="small" @click="insertItem(userList[0])">
          Add Mention Programmatically
        </van-button>
      </van-col>
    </van-row>
    <!-- editor -->
    <quill-editor
      class="editor"
      ref="myQuillEditor"
      v-model="content"
      :options="editorOption"
      @compositionstart.native="onCompositionstart"
      @compositionend.native="onCompositionend"
      @keydown.native="onKeyDownInput"
      @keyup.native="onKeyUpInput"
    />
    <div id="toolbar"></div>
    <!-- userList -->
    <van-popup
      id="edit"
      v-model="show"
      round
      position="bottom"
      :style="{ height: '40%' }"
      @close="closePopup"
    >
      <van-search v-model="search" placeholder="请输入搜索关键词" @search="onSearch">
        <template #action>
          <van-button type="warning" size="small" @click="onSearch">搜索</van-button>
        </template>
      </van-search>
      <van-cell-group>
        <van-cell
          :title="`编号为:${item.id}`"
          :value="`用户名为:${item.name}`"
          v-for="item in userList"
          :key="item.id"
          @click="selectItem(item)"
        />
      </van-cell-group>
    </van-popup>
  </div>
</template>

<script>
import { quillEditor } from 'vue-quill-editor';
import 'quill/dist/quill.snow.css';
import 'quill-mention';

export default {
  name: 'at-mention',
  components: {
    quillEditor,
  },
  data() {
    return {
      content: '',
      isClickMention: false, // 是否点击@按钮打开@菜单弹框
      isChineseInputMethod: false, // 是否中文输入法状态
      show: false, // 弹框显示状态
      editorOption: {
        placeholder: '说点什么呢。。。',
        modules: {
          toolbar: {
            container: '#toolbar',
          },
          history: {
            // history 配置(History模块负责处理Quill的撤销和重做)
            delay: 0, // 将延迟设置为0,那么几乎每次输入字符都会被记录成一个变化,然后,撤销动作就会一次撤销一个字符
          },
          mention: {
            // 将 quill-mention 配置传递给 quill
            allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
            mentionDenotationChars: ['@', '#'],
            // spaceAfterInsert: false,
            // fixMentionsToQuill: true, // 设置为 true 时,提及菜单将呈现在 quill 容器的上方或下方。否则,提及菜单将跟踪外延字符;
            // defaultMenuOrientation: 'bottom', // 选项是'bottom'和'top'。Quill-mention 将尝试在编辑器上方或下方呈现菜单。
            // // showDenotationChar: true // 是否打开@符号, 默认true
            // positioningStrategy: "fixed", // 选项是'normal'和'fixed'。时'fixed',菜单将附加到正文并使用固定定位。
            // dataAttributes: [['id', 'value', 'denotationChar', 'link', 'target', 'disabled', 'time']],
            source: function (searchTerm, renderList, mentionChar) {
              console.log(searchTerm, renderList, mentionChar);
              renderList([], searchTerm);
            },
          },
        },
      },
      search: '', // 搜索人名
      userList: [
        // 用户列表
        { name: '小张', id: '001' },
        { name: '小李', id: '002' },
        { name: '小安', id: '003' },
        { name: '小发', id: '004' },
        { name: '小刚', id: '005' },
      ],
    };
  },
  computed: {
    editor() {
      return this.$refs.myQuillEditor.quill;
    },
  },
  methods: {
    // 中文输入触发
    onCompositionstart() {
      this.isChineseInputMethod = true;
    },
    // 中文输入关闭
    onCompositionend() {
      this.isChineseInputMethod = false;
    },
    // 键盘按下
    onKeyDownInput(e) {
      // 判断状态非中文输入法,并且监听到了@的事件
      if (!this.isChineseInputMethod && this.isAtCode(e)) {
        // 输入@打开@菜单弹框
        this.show = true;
      }
    },
    // 键盘弹起
    onKeyUpInput(e) {
      // 判断状态非中文输入法,并且监听到了@的事件
      if (!this.isChineseInputMethod && this.isAtCode(e)) {
        // 隐藏虚拟键盘
        this.editor.blur();
      }
    },
    // 判断设备是否为 Mobile (注意,请勿在浏览器调试模式下,切换为手机模式,否则会导致bug)
    isMobile() {
      return navigator.userAgent.match(
        /(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i
      );
    },
    // 判断按键是否为 @
    isAtCode(e) {
      return this.isMobile()
        ? (e.keyCode === 229 || e.keyCode === 50) && e.code === 'Digit2' && e.key === '@'
        : ((e.keyCode === 50 && e.key === '@') || (e.keyCode === 229 && e.code === 'Digit2')) &&
            e.shiftKey;
    },
    // 点击@按钮打开@菜单弹框
    openPopup() {
      this.show = true;
      this.isClickMention = true;
    },
    // 关闭@菜单弹框
    closePopup() {
      this.show = false;
      this.search = '';
      this.isClickMention = false;
    },
    // 搜索用户
    onSearch(value) {
      this.userList = new Array(10).fill(5).map((item, index) => {
        return {
          name: `${value} - ${index}`,
          id: index,
        };
      });
    },
    // 选择要@的用户
    selectItem(item) {
      // 如果不是通过@按钮打开的弹框,则需要删除多余的@符号
      if (!this.isClickMention) {
        // 撤销一步,删除手动输入的@符号(需在modules中配置history: { delay: 0 })
        this.undo();
      }
      this.insertItem(item);
      this.show = false;
    },
    // 插入@内容
    insertItem(item) {
      const mention = this.editor.getModule('mention');
      mention.insertItem({ id: item.id, value: item.name, denotationChar: '@' }, true);
    },
    // 撤销
    undo() {
      this.editor.history.undo();
    },
  },
};
</script>

<style>
#at {
  padding: 10px;
}

/* quill */
.quill-editor {
  height: 200px;
}

/* quill-toolbar */
.ql-toolbar {
  padding: 0 !important;
  border: 0 !important;
}

/* @内容 */
.mention {
  color: #24afd6;
}

.van-col {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}
</style>

注意:输入框不能不能设置为display: inline-block;不然初始化的时候获取输入的光标是无法获取到的

链接: https://blog.csdn.net/weixin_44388523/article/details/124960758

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值