vue3 引入@vueup/vue-quill 封装富文本组件
- 终端下载
npm install @vueup/vue-quill@alpha --save
或者
npm install @vueup/vue-quill@latest --save
- 封装子组件QuillEditor
<template>
<QuillEditor
theme="snow"
:options="editorOption"
contentType="html"
/>
</template>
<script lang="js" setup>
import { QuillEditor, Quill } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import '@vueup/vue-quill/dist/vue-quill.bubble.css'
// 富文本配置
const fontSize = Quill.import('attributors/style/size') // 引入这个后会把样式写在style上
fontSize.whitelist = [false, '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px']
Quill.register(fontSize, true)
// 自定义字体类型
const fonts = [false, 'SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif', '宋体', '黑体']
const Font = Quill.import('attributors/style/font')
Font.whitelist = fonts
Quill.register(Font, true);
const editorOption = {
modules: {
toolbar: [
// ['bold', 'italic', 'underline', 'strike'], // 加粗,斜体,下划线,删除线
['bold', 'italic'], // 下划线,删除线无效
// [{ header: 1 }, { header: 2 }], // 标题,键值对的形式;1、2表示字体大小
[{ align: [] }], // 对齐方式
[{ list: 'ordered' }, { list: 'bullet' }], // 列表
[{ indent: '-1' }, { indent: '+1' }], // 缩进
// [{ direction: 'ltl' }, { direction: 'rtl' }], // 文本方向
[{ size: fontSize.whitelist }], // 字体大小
[{ font: Font.whitelist }], // 字体
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 几级标题
[{ script: 'sub' }, { script: 'super' }], // 上下标
[{ color: [] }, { background: [] }], // 字体颜色,字体背景颜色
['clean'], // 清除字体样式
]
},
placeholder: '(如果选是,具体列出职责事项)',
}
// 鼠标悬停设置无效
// const addQuillTitle = () => {
// const titleConfig = {
// 'ql-bold': '加粗',
// 'ql-color': '颜色',
// 'ql-font': '字体',
// 'ql-code': '插入代码',
// 'ql-italic': '斜体',
// 'ql-link': '添加链接',
// 'ql-background': '背景颜色',
// 'ql-size': '字体大小',
// 'ql-strike': '删除线',
// 'ql-script': '上标/下标',
// 'ql-underline': '下划线',
// 'ql-blockquote': '引用',
// 'ql-header': '标题',
// 'ql-indent': '缩进',
// 'ql-list': '列表',
// 'ql-align': '文本对齐',
// 'ql-direction': '文本方向',
// 'ql-code-block': '代码块',
// 'ql-formula': '公式',
// 'ql-image': '图片',
// 'ql-video': '视频',
// 'ql-clean': '清除字体样式'
// }
// const oToolBar = document.querySelector('.ql-toolbar')
// if (!oToolBar) {
// return false
// }
// const aButton = oToolBar.querySelectorAll('button')
// const aSelect = oToolBar.querySelectorAll('select')
// aButton.forEach(function (item) {
// if (item.className === 'ql-script') {
// item.value === 'sub' ? item.title = '下标' : item.title = '上标'
// } else if (item.className === 'ql-indent') {
// item.value === '+1' ? item.title = '向右缩进' : item.title = '向左缩进'
// } else {
// item.title = titleConfig[item.classList[0]]
// }
// })
// aSelect.forEach(function (item) {
// item.parentNode.title = titleConfig[item.classList[0]]
// })
// }
// const hhh = () => {
// showDialog.value = true
// addQuillTitle()
// }
</script>
<script lang="js">
export default {
name: 'QuillEditor'
}
</script>
<style scoped lang="scss">
// 汉化 父组件中不生效,需要在父组件中重新设置
:deep{
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
content: '12px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
content: "16px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
content: "20px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
content: "24px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28px"]::before {
content: "28px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {content: "32px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "字号";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "正文" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;}
.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" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "字体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Arial"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Arial"]::before {
content: "Arial" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimSun"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimSun"]::before {
content: "SimSun" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimHei"]::before {
content: "SimHei" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Microsoft-YaHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Microsoft-YaHei"]::before {
content: "微软雅黑" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Arial"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Arial"]::before {
content: "Arial" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Times-New-Roman"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Times-New-Roman"]::before {
content: "罗马" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="KaiTi"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="KaiTi"]::before {
content: "楷体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="sans-serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="sans-serif"]::before {
content: "sans-serif" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="宋体"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="宋体"]::before {
content: "宋体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="黑体"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="黑体"]::before {
content: "黑体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="FangSong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="FangSong"]::before {
content: "仿宋" !important;
}
}
</style>
- 父组件引入子组件QuillEditor
<template>
<div>
// 其他代码...
<QuillEditor v-model:content="duty_content" />
</div>
<template/>
<script lang="js" setup>
import { ref } from 'vue'
import QuillEditor from '@/components/QuillEditor.vue'
// 绑定变量值
const duty_content = ref('')
</script>
<style scoped lang="scss">
// 汉化 子组件设置不生效
:deep{
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
content: '12px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
content: "16px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
content: "20px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
content: "24px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28px"]::before {
content: "28px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {content: "32px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "字号";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "正文" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;}
.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" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "字体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Arial"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Arial"]::before {
content: "Arial" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimSun"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimSun"]::before {
content: "SimSun" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimHei"]::before {
content: "SimHei" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Microsoft-YaHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Microsoft-YaHei"]::before {
content: "微软雅黑" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Arial"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Arial"]::before {
content: "Arial" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Times-New-Roman"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Times-New-Roman"]::before {
content: "罗马" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="KaiTi"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="KaiTi"]::before {
content: "楷体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="sans-serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="sans-serif"]::before {
content: "sans-serif" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="宋体"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="宋体"]::before {
content: "宋体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="黑体"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="黑体"]::before {
content: "黑体" !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="FangSong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="FangSong"]::before {
content: "仿宋" !important;
}
}
</style>
控制台有警告,不知道后面会不会出现兼容问题
[Deprecation] Listener added for a synchronous 'DOMNodeInserted' DOM Mutation Event. This event type is deprecated (w3c.github.io/uievents/#l…) and work is underway to remove it from this browser. Usage of this event listener will cause performance issues today, and represents a risk of future incompatibility. Consider using MutationObserver instead.