技术标签: vue 前端 vue.js javascript
vue2集成富文本编辑器,并开发一个选人插件,选中后加到编辑区域内。
npm install vue-quill-editor --save
// 导入插件,引用样式
import { quillEditor, Quill } from 'vue-quill-editor';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
// Vue-Quill-Editor放到组件中
components: {
quillEditor
},
<template>
<div class="app-quill-editor">
<!-- 编辑器 -->
<quill-editor ref="editorComp" v-model="content" class="quilleditor" :options="editorOption"> </quill-editor>
<!-- 选人列表 -->
<div id="myPanel" v-if="showMetric" style="position:absolute; top: 80px; left: 10px;background-color: #FFFFFF">
<el-card class="box-card" style="height: 150px; overflow-y: auto; overflow-x: hidden">
<div v-for="item in userList" class="box-div" style="width: 210px; height: 30px; background-color: #FFFFFF">
<el-button type="text" @click="handleClick(item)">
<span style="float: left; width: 50px;">{
{ item.name }}</span>
<span style="float: right; color: #8492a6; font-size: 13px; width: 150px; text-align: right">{
{ item.mobile }}</span>
</el-button>
</div>
</el-card>
</div>
</div>
</template>
insertMetric 声明选人插件
在handlers中控制插件
insertMetric: function () { let self = this.handlers.that; self.showMetric = !self.showMetric; self.quill_this = this; }
data() {
return {
user: '',
//父组件传过来
userList: [],
// 工具按钮
editorOption: {
modules: {
toolbar: {
container: [
['insertMetric'], //新添加的工具
['bold', 'italic', 'underline'],
[
{
size: ['small', false, 'large', 'huge']
}
],
[
{
list: 'ordered'
},
{
list: 'bullet'
}
],
[
{
color: []
},
{
background: []
}
],
],
handlers: {
shadeBox: null,
that: this,
insertMetric: function () {
let self = this.handlers.that;
self.showMetric = !self.showMetric;
self.quill_this = this;
}
}
}
}
},
// 提醒
toolbarTips: [
{
Choice: '.ql-bold',
title: '加粗'
},
{
Choice: '.ql-italic',
title: '倾斜'
},
{
Choice: '.ql-underline',
title: '下划线'
},
{
Choice: '.ql-header',
title: '段落格式'
},
{
Choice: '.ql-strike',
title: '删除线'
},
{
Choice: '.ql-blockquote',
title: '块引用'
},
{
Choice: '.ql-size',
title: '字体大小'
},
{
Choice: '.ql-list[value="ordered"]',
title: '编号列表'
},
{
Choice: '.ql-list[value="bullet"]',
title: '项目列表'
},
{
Choice: '.ql-align',
title: '对齐方式'
},
{
Choice: '.ql-color',
title: '字体颜色'
},
{
Choice: '.ql-background',
title: '背景颜色'
},
{
Choice: '.ql-image',
title: '图像'
},
{
Choice: '.ql-video',
title: '视频'
},
{
Choice: '.ql-link',
title: '添加链接'
},
{
Choice: '.ql-formula',
title: '插入公式'
},
{
Choice: '.ql-clean',
title: '清除格式'
},
{
Choice: '.ql-indent[value="-1"]',
title: '向左缩进'
},
{
Choice: '.ql-indent[value="+1"]',
title: '向右缩进'
},
{
Choice: '.ql-header .ql-picker-label',
title: '标题大小'
},
{
Choice: '.ql-header .ql-picker-item[data-value="1"]',
title: '标题一'
},
{
Choice: '.ql-header .ql-picker-item[data-value="2"]',
title: '标题二'
},
{
Choice: '.ql-header .ql-picker-item[data-value="3"]',
title: '标题三'
},
{
Choice: '.ql-header .ql-picker-item[data-value="4"]',
title: '标题四'
},
{
Choice: '.ql-header .ql-picker-item[data-value="5"]',
title: '标题五'
},
{
Choice: '.ql-header .ql-picker-item[data-value="6"]',
title: '标题六'
},
{
Choice: '.ql-header .ql-picker-item:last-child',
title: '标准'
},
{
Choice: '.ql-size .ql-picker-item[data-value="small"]',
title: '小号'
},
{
Choice: '.ql-size .ql-picker-item[data-value="large"]',
title: '大号'
},
{
Choice: '.ql-size .ql-picker-item[data-value="huge"]',
title: '超大号'
},
{
Choice: '.ql-size .ql-picker-item:nth-child(2)',
title: '标准'
},
{
Choice: '.ql-align .ql-picker-item:first-child',
title: '居左对齐'
},
{
Choice: '.ql-align .ql-picker-item[data-value="center"]',
title: '居中对齐'
},
{
Choice: '.ql-align .ql-picker-item[data-value="right"]',
title: '居右对齐'
},
{
Choice: '.ql-align .ql-picker-item[data-value="justify"]',
title: '两端对齐'
},
{
Choice: '.ql-insertMetric',
title: '插入用户'
}
],
// 编辑器内容
content: '',
// 是否显示选人插件
showMetric: false,
quill_this: this,
};
},
mounted() {
this.initButton();
},
methods: {
initButton() {
document.getElementsByClassName('ql-editor')[0].dataset.placeholder = '';
for (let item of this.toolbarTips) {
let tip = document.querySelector('.quill-editor ' + item.Choice);
if (!tip) continue;
tip.setAttribute('title', item.title);
}
const sourceEditorButton = document.querySelector('.ql-insertMetric');
sourceEditorButton.innerHTML = '<i class="el-icon-user-solid" style="font-size: 18px; color: black"></i>';
},
handleClick(row) {
this.insert(row);
this.showMetric = false;
this.user = ''
},
insert(user) {
const name = user.name;
let quill_this = this.quill_this;
let range = quill_this.quill.getSelection(true);
quill_this.quill.insertEmbed(range.index, 'atusertag', {text:`@${name} `,id: user.id}, Quill.sources.USER);
quill_this.quill.insertText(range.index + 1, ' ');
quill_this.quill.setSelection(range.index + 2);
quill_this.quill.focus()
quill_this.quill.update()
},
}
此时@用户需要作为一个整体组件,方便删除。新建一个js文件,LinkUserBlot.js
// 引入组件js,并注册 import LinkUserBlot from './LinkUserBlot.js' Quill.register(LinkUserBlot, true)
import {
Quill
} from 'vue-quill-editor'
const Embed = Quill.import("blots/embed");
class LinkUserBlot extends Embed {
static create(value) {
// console.log('value', value)
let node = super.create();
node.innerHTML = value.text
node.setAttribute('id', value.id);
node.setAttribute('contenteditable', false);
node.setAttribute('class', 'at-some-one');
// @人样式不受影响
node.setAttribute('style', 'color:#4498F0;text-decoration: none;display: inline-block;font-style: normal;background-color: #fff;margin: 0 2px;');
return node;
}
static value(node) {
return {
id: node.getAttribute('id'),
text: node.innerHTML.trim()
};
}
}
LinkUserBlot.blotName = 'atusertag';
LinkUserBlot.tagName = 'span';
LinkUserBlot.className = 'user-at-span';
export default LinkUserBlot
这两处通过 atusertag 关联
quill_this.quill.insertEmbed(range.index, 'atusertag', {text:`@${name} `,id: user.id}, Quill.sources.USER);LinkUserBlot.blotName = 'atusertag';
<style lang="scss">
.app-quill-editor {
position: relative;
.ql-container {
height: 200px;
}
.el-card__body {
padding: 10px;
}
.box-card {
}
}
::v-deep {
@media only screen and (max-width: 1280px) {
.quilleditor {
height: 240px !important;
}
}
@media only screen and (max-width: 900px) {
.quilleditor {
height: 240px !important;
}
.ql-container {
height: 85%;
}
}
}
</style>
<style>
.editor, .ql-toolbar {
white-space: pre-wrap !important;
line-height: normal !important;
}
.quill-img {
display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体";
}
.footer {
float: right;
padding: 10px;
}
</style>
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数