最近项目中需要使用富文本编辑器,之前用的是vue-quill-editor,但是测试的时候发现这个编辑器会把内联的样式都清除掉,去查了一圈文档和各路网友的问答,有说这个就是quill的特性,不支持内联样式,具体原因我也没看明白,总之是改不动了,所以换了summernote。
summernote官网:https://summernote.org/
在网上找到了几篇相关的博客,结合个人使用经验做下总结笔记
参考文章:
https://zhuanlan.zhihu.com/p/25854415
https://segmentfault.com/a/1190000005124524
目录
1. 需要安装的依赖包
2. 在webpack.base.conf.js中配置jquery
3. 在src/main.js中引入所需文件
4. 在页面中使用summernote
5. summernote取值和赋值
6. 上传图片
7. 自定义上传视频按钮
1 需要安装的依赖包:
"bootstrap": "^4.1.1",
"font-awesome": "^4.7.0",
"jquery": "^3.3.1",
"codemirror": "^5.37.0",
"summernote": "^0.8.10",
2 在webpack.base.conf.js中配置jquery
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'jquery': path.resolve(__dirname, '../node_modules/jquery/src/jquery')
}
},
3 在src/main.js中引入所需文件(注意:引用路径可能不一样)
import 'bootstrap/dist/js/bootstrap.bundle.min'
import 'bootstrap/dist/css/bootstrap.css'
import 'font-awesome/css/font-awesome.css'
import 'summernote'
import 'summernote/dist/lang/summernote-zh-CN'
import 'summernote/dist/summernote.css'
4 在页面中使用summernote
(1)引入jquery
import $ from 'jquery'
(2)view
<div id="summernote" v-model="richContent">div>
(3)在mounted中配置summernote
$('#summernote').summernote({
lang: 'zh-CN',
placeholder: '请输入内容',
height: 600,
width: 380,
htmlMode: true,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['fontsize', ['fontsize']],
['fontname', ['fontname']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['insert', ['link', 'picture']],
['mybutton', ['myVideo']]
],
fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],
fontNames: [
'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',
'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',
'Tahoma', 'Times New Roman', 'Verdana'
],
buttons: {
myVideo: myVideoBtn
},
callbacks: {
onSubmit: function() {
vm.richContent = $('#summernote').summernote('code')
}
}
})
官网:https://summernote.org/deep-dive/
5 summernote取值和赋值
取值:$('#summernote').summernote('code')
赋值:$('#summernote').summernote('code', this.richContent)
6 上传图片(在(3)中的callbacks里添加下面这个函数)
onImageUpload: function(files) {
upload(file,).then(url => { // 这个upload是自定义的上传文件函数,最后拿到图片的url,插入到富文本中
$('#summernote').summernote('insertImage', url)
})
}
7 自定义上传视频按钮
// mounted中加入下面这段
window.uploadVideo = function() {
vm.showLoading = true // 因ship上传比较耗时,所以加了个loading提示
upload($('#video')[0].files[0]).then(url => {// upload是自定义的上传文件函数,这里是上传成功的回调,拿到视频的url
var node = document.createElement('div') // 创建节点,用于包裹视频,再加这一层是方便调视频样式
node.innerHTML = '
node.cssText = 'width:100%;text-aligen:center;'
$('#summernote').summernote('insertNode', node)// 插入视频
vm.showLoading = false // 视频上传结束,去掉loading提示
})
}
var myVideoBtn = function(context) {
var ui = $.summernote.ui
// create button
var button = ui.button({
contents: '', // 这个是展示在富文本顶部的操作图标,这个rich-video-icon是自己写的
// tooltip: ''// todo 这个视频提示报错,未知原因
// click: function() {// 点击按钮触发事件,这边不需要用到
// context.invoke('editor.insertText', 'xxx')
// }
})
return button.render() // return button as jquery object
}
在(3)中的配置项中添加
buttons: {
myVideo: myVideoBtn
}
附录:
默认配置项概览:
options: {
modules: {
'editor': Editor,
'clipboard': Clipboard,
'dropzone': Dropzone,
'codeview': Codeview,
'statusbar': Statusbar,
'fullscreen': Fullscreen,
'handle': Handle,
// FIXME: HintPopover must be front of autolink
// - Script error about range when Enter key is pressed on hint popover
'hintPopover': HintPopover,
'autoLink': AutoLink,
'autoSync': AutoSync,
'placeholder': Placeholder,
'buttons': Buttons,
'toolbar': Toolbar,
'linkDialog': LinkDialog,
'linkPopover': LinkPopover,
'imageDialog': ImageDialog,
'imagePopover': ImagePopover,
'videoDialog': VideoDialog,
'helpDialog': HelpDialog,
'airPopover': AirPopover
},
buttons: {},
lang: 'zh-CN',
// toolbar工具栏默认
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['fontname', ['fontname']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['view', ['fullscreen', 'codeview', 'help']]
],
// popover
popover: {
image: [
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
['float', ['floatLeft', 'floatRight', 'floatNone']],
['remove', ['removeMedia']]
],
link: [
['link', ['linkDialogShow', 'unlink']]
],
air: [
['color', ['color']],
['font', ['bold', 'underline', 'clear']],
['para', ['ul', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture']]
]
},
// air mode: inline editor
airMode: false,
width: null,
height: null,
focus: false,
tabSize: 4,
styleWithSpan: false,
shortcuts: true,
textareaAutoSync: true,
direction: null,
styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
fontNames: [
'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',
'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',
'Tahoma', 'Times New Roman', 'Verdana'
],
fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],
// pallete colors(n x n)
colors: [
['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'],
['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'],
['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'],
['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'],
['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'],
['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'],
['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'],
['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031']
],
lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'],
tableClassName: 'table table-bordered',
insertTableMaxSize: {
col: 10,
row: 10
},
dialogsInBody: false,
dialogsFade: false,
maximumImageFileSize: null,
callbacks: {
onInit: null,//初始化回调函数
onFocus: null,//聚集
onBlur: null,//失去焦点
onEnter: null,//回车键的回调函数
onKeyup: null,
onKeydown: null,
onSubmit: null,//提交时回调函数
onImageUpload: null,//这就是上传图片的回调函数
onImageUploadError: null//上传图片出错
},
codemirror: {
mode: 'text/html',
htmlMode: true,
lineNumbers: true
},
keyMap: {
pc: {
'ENTER': 'insertParagraph',
'CTRL+Z': 'undo',
'CTRL+Y': 'redo',
'TAB': 'tab',
'SHIFT+TAB': 'untab',
'CTRL+B': 'bold',
'CTRL+I': 'italic',
'CTRL+U': 'underline',
'CTRL+SHIFT+S': 'strikethrough',
'CTRL+BACKSLASH': 'removeFormat',
'CTRL+SHIFT+L': 'justifyLeft',
'CTRL+SHIFT+E': 'justifyCenter',
'CTRL+SHIFT+R': 'justifyRight',
'CTRL+SHIFT+J': 'justifyFull',
'CTRL+SHIFT+NUM7': 'insertUnorderedList',
'CTRL+SHIFT+NUM8': 'insertOrderedList',
'CTRL+LEFTBRACKET': 'outdent',
'CTRL+RIGHTBRACKET': 'indent',
'CTRL+NUM0': 'formatPara',
'CTRL+NUM1': 'formatH1',
'CTRL+NUM2': 'formatH2',
'CTRL+NUM3': 'formatH3',
'CTRL+NUM4': 'formatH4',
'CTRL+NUM5': 'formatH5',
'CTRL+NUM6': 'formatH6',
'CTRL+ENTER': 'insertHorizontalRule',
'CTRL+K': 'linkDialog.show'
},
mac: {
'ENTER': 'insertParagraph',
'CMD+Z': 'undo',
'CMD+SHIFT+Z': 'redo',
'TAB': 'tab',
'SHIFT+TAB': 'untab',
'CMD+B': 'bold',
'CMD+I': 'italic',
'CMD+U': 'underline',
'CMD+SHIFT+S': 'strikethrough',
'CMD+BACKSLASH': 'removeFormat',
'CMD+SHIFT+L': 'justifyLeft',
'CMD+SHIFT+E': 'justifyCenter',
'CMD+SHIFT+R': 'justifyRight',
'CMD+SHIFT+J': 'justifyFull',
'CMD+SHIFT+NUM7': 'insertUnorderedList',
'CMD+SHIFT+NUM8': 'insertOrderedList',
'CMD+LEFTBRACKET': 'outdent',
'CMD+RIGHTBRACKET': 'indent',
'CMD+NUM0': 'formatPara',
'CMD+NUM1': 'formatH1',
'CMD+NUM2': 'formatH2',
'CMD+NUM3': 'formatH3',
'CMD+NUM4': 'formatH4',
'CMD+NUM5': 'formatH5',
'CMD+NUM6': 'formatH6',
'CMD+ENTER': 'insertHorizontalRule',
'CMD+K': 'linkDialog.show'
}
},
icons: {
'align': 'icon-align',
'alignCenter': 'icon-align-center',
'alignJustify': 'icon-align-justify',
'alignLeft': 'icon-align-left',
'alignRight': 'icon-align-right',
'indent': 'icon-indent-right',
'outdent': 'icon-indent-left',
'arrowsAlt': 'icon-resize-full',
'bold': 'icon-bold',
'caret': 'icon-caret-down',
'circle': 'icon-circle',
'close': 'icon-close',
'code': 'icon-code',
'eraser': 'icon-eraser',
'font': 'icon-font',
'frame': 'icon-frame',
'italic': 'icon-italic',
'link': 'icon-link',
'unlink': 'icon-chain-broken',
'magic': 'icon-magic',
'menuCheck': 'icon-check',
'minus': 'icon-minus',
'orderedlist': 'icon-list-ol',
'pencil': 'icon-pencil',
'picture': 'icon-picture',
'question': 'icon-question',
'redo': 'icon-redo',
'square': 'icon-square',
'strikethrough': 'icon-strikethrough',
'subscript': 'icon-subscript',
'superscript': 'icon-superscript',
'table': 'icon-table',
'textHeight': 'icon-text-height',
'trash': 'icon-trash',
'underline': 'icon-underline',
'undo': 'icon-undo',
'unorderedlist': 'icon-list-ul',
'video': 'icon-facetime-video'
}
}