支持vue3.0+ts 的富文本记录

前言

用过很多的富文本,还是蛮喜欢鹅毛富文本,轻量级,
一般遇到富文本的案例,都会首先想到的是quill
目前vue3.0与react分裂两极,typescript霸占一方,javascript还在坚持,vue2.0日薄西山。
本文介绍vue3.0 ts支持的富文本的简单实用和文档地址

富文本Vue-Quill-Editor

官网文档

  • 安装
    yarn add @vueup/vue-quill@beta
    
  • 使用
    import { QuillEditor } from '@vueup/vue-quill'
    import '@vueup/vue-quill/dist/vue-quill.snow.css';
    
    <QuillEditor
            ref="QuillEditorRef"
            :options="options"
            :content="textarea"
            content-type="html"
            @update:content="textChange"
          />
    
    const options = {
      debug: 'info',
      modules: {
        // toolbar: ['bold', 'italic', 'underline'],
      },
      placeholder: '批量输入/粘贴 企业名称或者域名,以“行”为分割线;例如以下:\n北京安全共识科技有限公司\n百度网讯科技有限公司',
      readOnly: false,
      theme: 'snow',
    }
    
    const textChange = (e:any) => {
      textarea.value = e
      console.log(e, '98', textarea.value);
    }
    
    	// 设置ref:便于调用quill支持的方法
    	// 比如 弹窗打开时设置内容为空
    	const userSecret = async () => {
    	  if (QuillEditorRef.value) {
    	    QuillEditorRef.value.setText('')
    	  }
    	};
    
    注解:
    @update:content 内容改变事件
    options:配置项
    设置ref:便于调用quill支持的方法
    更多详细的请参考文档
    
    效果图
    在这里插入图片描述

富文本wangeditor

官网文档

  • 效果图
    在这里插入图片描述

  • 安装

	npm install wangeditor --save-dev
  • 封装
	<template>
     <div>
       <div className="shop">
         <div className="text-area">
           <div
             ref="editorElemMenu"
   
             style="backgroundColor: '#f1f1f1'; border:'1px solid #ccc'"
   
             className="editorElem-menu"
           />
           <div
             ref="editorElemBody"
             :className="value&&value!=='<p><br></p>'?'contentClass editorElem-body':'placeholderClass editorElem-body'"
             style="height: 300;border: '1px solid #ccc',borderTop: 'none'"
           />
         </div>
       </div>
     </div>
   </template>
   <script lang="ts" setup>
   import {
     onMounted, reactive, toRefs, defineComponent, ref,
   } from 'vue'
   
   import E from 'wangeditor'
   
   interface DataProps {
   	editor: any;
   	editorContent: string
   	getContent:(ref?: any) => void
   }
   const props = defineProps({
     options: {
       type: Object,
       default: () => ({}),
     },
     value: {
       type: String,
       default: '',
     },
   });
   const editorElemMenu = ref();
   const editorElemBody = ref();
   const data: DataProps = reactive({
     editorContent: '',
     editor: {},
     getContent: () => {
       data.editor.txt.html(props.value)
     },
   })
   const emit = defineEmits(['onEditor', 'update:value']);
   onMounted(() => {
     const elemMenu = editorElemMenu.value;
     const elemBody = editorElemBody.value;
     data.editor = new E(elemMenu, elemBody)
     // 使用 onchange 函数监听内容的变化,并实时更新到 state 中
     data.editor.config.placeholder = '批量输入/粘贴 企业名称或者域名,以“行”为分割线;例如以下:<br/>北京安全共识科技有限公司<br/>百度网讯科技有限公司<br/>百度移信网络技术(北京)有限公司<br/>百度时代网络技术(北京)有限公司<br/>中电国佳(北京)投资基金管理有限公司<br/>北京安全共识科技有限公司<br/>百度网讯科技有限公司<br/>百度移信网络技术(北京)有限公司<br/>百度时代网络技术(北京)有限公司<br/>中电国佳(北京)投资基金管理有限公司',
     data.editor.config.onchange = () => {
       console.log(data.editor.txt.html())
       data.editorContent = data.editor.txt.html()
       // 向外部返回一个处理过的值
       emit('onEditor', data.editor.txt.html())
       emit('update:value', data.editor.txt.html())
     }
     data.editor.config.customUploadImg = function (files: any, insert: any) {
       // files 是 input 中选中的文件列表insert 是获取图片 url 后,插入到编辑器的方法
       // let file;
       // if (files && files.length) {
       //     file = files[0];
       // } else {
       //     return
       // }
       // 图片上传
       console.log('files1', files)
       const formData = new FormData();
       formData.append('file', files[0]);
       console.log('files', files, insert)
       // formData.append('Banners',{id:editorinfo.id,naviChildId:editorinfo.naviChildId})
     }

     data.editor.config.menus = [
       'head', // 标题
       'bold', // 粗体
       'fontSize', // 字号
       'fontName', // 字体
       'italic', // 斜体
       'underline', // 下划线
       'strikeThrough', // 删除线
       'foreColor', // 文字颜色
       'backColor', // 背景颜色
       'link', // 插入链接
       'list', // 列表
       'justify', // 对齐方式
       'quote', // 引用
       'emoticon', // 表情
       'image', // 插入图片
       'table', // 表格
       'video', // 插入视频
       'code', // 插入代码
       'undo', // 撤销
       'redo', // 重复
     ]
     data.editor.config.uploadImgShowBase64 = true
     data.editor.create()
   
     // data.getContent()
   })
   const refData = toRefs(data);
   </script>
   <style scoped lang="scss">
   :deep(.w-e-text-container){
       min-height: 349px;
       max-height: 449px;
       overflow-y: auto;
       line-height: 32px;
       &:focus{
           outline: 0;
           box-shadow: 0 0 0 1px rgba(0, 88, 240, 1) inset;
       }
       &:active{
           outline: 0;
           box-shadow: 0 0 0 1px rgba(0, 88, 240, 1) inset;
       }
       &:visited{
           outline: 0;
           box-shadow: 0 0 0 1px rgba(0, 88, 240, 1) inset;
       }
       &::-webkit-scrollbar {/*滚动条整体样式*/
           width:0px;/*高宽分别对应横竖滚动条的尺寸*/
       }
       .placeholder{
           line-height: 32px;
           left: 16px;
           top: 16px;
           width: calc(100% - 16px);
       }
       .w-e-text{
           max-height: 449px;
           line-height: 32px;
           padding: 16px 16px;
           &::-webkit-scrollbar {/*滚动条整体样式*/
             width:0px;/*高宽分别对应横竖滚动条的尺寸*/
           }
           p{
               line-height: 32px;
               margin: 0px;
           }
       }
   }
   .placeholderClass{
         :deep(.w-e-text-container){
           background: #F2F3F5;
           border-radius: 2px;
           color: #D1D5DD;
           &:hover{
             outline: 0;
             box-shadow: none;
             // box-shadow: 0 0 0 1px #F2F3F5 inset;
           }
           &:focus{
             outline: 0;
             box-shadow: 0 0 0 1px rgba(0, 88, 240, 1) inset;
           }
         }
       }
       .contentClass{
         :deep(.w-e-text-container){
           background: #fff;
           border-radius: 2px;
           color: #171B23;
           box-shadow: 0 0 0 1px rgba(0, 88, 240, 1) inset;
           &:hover{
             outline: 0;
             box-shadow: none;
             box-shadow: 0 0 0 1px rgba(0, 88, 240, 1) inset;
           }
           &:focus{
             outline: 0;
             box-shadow: 0 0 0 1px rgba(0, 88, 240, 1) inset;
           }
         }
       }
   </style>
  • 使用
  <Editor
    ref="refEditor"
     :value="textarea"
     @onEditor="onEditor"
   />
   // 导入     
   import Editor from './Editor/wangEditor.vue'
   const textarea = ref<any>('')
   const refEditor = ref<any>();
   const onEditor = (value:any) => {
     console.log('父组件', value)
     textarea.value = value
   }

富文本数据处理

// 针对纯文本 提取里面的文字 push到data中
// <p>123</p>
let data = []
if(val !== undefined){
	// 段落文本
	val.replace(/<p>(([\s\S])*?)<\/p>/g, (match, capture) => {
	  data.push( capture );
	});
	// 图片
	val.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
	  data.push({
		files_url:capture,
		});
	});
}
多个标签,复杂的属性
// 匹配标签(不包括内容),过滤标签,保留内容。
var reg1 = /(<\/?font.*?>)/gi;
var reg2 = /(<\/?span.*?>)/gi;
var reg3 = /(<\/?a.*?>)/gi;
var reg4= /(<\/?font.*?>)|(<\/?span.*?>)|(<\/?a.*?>)/gi;

var str = '<span>span数据</span><a href="asdasd">a数据<font>font数据</font></a>';
console.log(str.replace(reg1, ''));
console.log(str.replace(reg2, ''));
console.log(str.replace(reg3, ''));
console.log(str.replace(reg4, ''));


// 只去掉标签内的属性(比如style和class)
var reg1 = /<span[^>]*>/gi;
var str1 = '<span style="color:red;">去除样式属性</span>123123';
console.log(str1.replace(reg1, '<span>'));
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值