vue+summernote富文本编辑器使用

7 篇文章 0 订阅

最近项目中需要使用富文本编辑器,之前用的是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 = '<video controls="controls" style="max-width:100%;" src="' + url + '" />'
        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: '<i class="rich-video-icon"/><input title="视频" onchange="uploadVideo()" type="file" id="videoInput" accept="video/*" style="opacity: 0; filter:Alpha(opacity=0);width:20px;height: 20px;margin-left: -20px;position:absolute;">', // 这个是展示在富文本顶部的操作图标,这个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'
  }
}
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值