「TinyMCE富文本」实现@用户|联想功能,在Vue项目中

1,521 阅读2分钟

Vue, Tiny , UI component, AddButton, Autocompleter

通过Tiny的UI组件Autocompleter实现

业务场景:

  1. 用户输入@后再输入字符可查出相对应的用户列表。
  2. 选中后不可编辑,删除时全部删除。
  3. 富文本内容展示时如 “@Alice” 可点击访问用户个人信息。

项目中使用的是Tiny富文本,所以就在tiny的官网中找乱翻,嘿!还真给找着了。

完整代码:

codepen.io/menkounachu…

editor.ui.registry.addAutocompleter(name, configuration)

在输入特定的触发符号后触发联想(触发符号前面必须有分隔符,空格或换行)

所以可以利用这个功能实现用户输入@后开启用户选择列表,具体配置可以看官网,可以配置候选列表的样式,也可以实现级联等。

 setup: function (editor) {       
			// 注册@触发字符及事件
            editor.ui.registry.addAutocompleter('specialchars', {
                ch: '@', // 设置@为触发符
                minChars: 1, // 最小的触发字符
                columns: 1, // 待选区域展示列数
                onAction: remindSelectedHandle,
                fetch: this.getUserList // 待选区域数据,可返回promise
            });

            // @用户列表选择处理方法
						// autocompleteApi
            function remindSelectedHandle(autocompleteApi, rng, value) {
                let userObj = JSON.parse(value) // 反序列化拿到选择的用户对象
                editor.selection.setRng(rng);
                editor.insertContent(`<span class="clickable-hover" style="color:#078af9" contenteditable="false" data-remind-user-id="${userObj.id}">@${userObj.name} </span>`);
                autocompleteApi.hide();
            }
 }

当选择某个用户后拿到数据拼接html字符串

<span class="clickable-hover" style="color:#078af9" contenteditable="false" data-remind-user-id="${userObj.id}">@${userObj.name} </span>
  • contenteditable="false"保证渲染在富文本中的标签为一个整体,不可编辑并且删除时@连带用户名一起删除。
  • data-remind-user-id保存用户id,后面渲染html时添加点击事件实现查看被@用户的个人信息,详见最后。

如果需要在富文本上添加个@快捷按钮可以用下面👇这个方法

editor.ui.registry.addButton(identifier, configuration)

  • identifier: 按钮的唯一标识
  • configuration:
    • icon 图标
    • onAction 点击回调事件
 setup: function (editor) {       
		// 注册@功能
        registerAutocompleter(editor) {
            // 注册@快捷菜单
            editor.ui.registry.addButton('remind', {
                icon: 'user', // 菜单按钮图标
                onAction: function () {
                    editor.insertContent(' @'); // 前面加入空格保证触发Autocompleter
                }
            });
        },
 }

其他:

  1. 图标可以使用Tiny默认icons(直接通过名字使用),或者通过tinymce.editor.ui.Registry.addIcon.自定义图标。

  2. 渲染html字符串时可以不使用v-html,自己写个组件用render函数渲染,这样事件也会自动添加,也可以渲染自定义的组件标签。

 htmlStr.replace(/(data-remind-user-id="(\w+)")/g, function(match, p1, p2){
        return `${p1} @click="toSpacePage(${p2})"`;
    });