在项目需要用到富文本编辑器时, 自己也筛选过不少插件, 最终选择了 froala-editor,UI 简单功能强大, 官网也列出了很多国外大佬在使用, 自己实战后确实感觉比其他的富文本编辑器好.
官网: https://froala.com/
1, 安装
- NPM install font-awesome --save // 安装 font-awesome
- NPM i vue-froala-wysiwyg -S;// 样式失效重新安装
2, 引入
main.JS 或者写在其他 JS 文件再从 main.JS 引入
- import Vue from "vue";
- import "froala-editor/CSS/froala_editor.pkgd.min.css";
- import "froala-editor/css/froala_style.min.css";
- import "froala-editor/js/froala_editor.pkgd.min.js";
- import "froala-editor/js/languages/zh_cn.js";
- import "froala-editor/js/plugins.pkgd.min.js";
- import VueFroala from "vue-froala-wysiwyg";
- Vue.use(VueFroala); // 样式失效重新安装 NPM i vue-froala-wysiwyg -S;
3, 使用
1. 新建 froalaEditor.vue 文件
- <template>
- <div class="editor-wrap">
- <froala
- id="froala-editor"
- :tag="'textarea'"
- :config="config"
- v-model="body.content"
- />
- </div>
- </template>
- <script>
- const tool = [
- "undo",
- "redo",
- "clearFormatting",
- "bold",
- "italic",
- "underline",
- "strikeThrough",
- "fontFamily",
- "fontSize",
- "textColor",
- "color",
- "backgroundColor",
- "inlineStyle",
- "paragraphFormat",
- "align",
- "formatOL",
- "formatUL",
- "outdent",
- "indent",
- "quote",
- "insertLink",
- "insertImage",
- "insertVideo",
- "embedly",
- "insertFile",
- "insertTable",
- "emoticons",
- "specialCharacters",
- "insertHR",
- "selectAll",
- "print",
- "spellChecker",
- "html",
- "help",
- "fullscreen"
- ];
- export default {
- props: {
- // 显示的工具列表
- placeholder: {
- type: String
- // required: true
- },
- height: {
- type: Number
- },
- value: {
- type: String,
- default: null
- },
- index: {
- type: Number,
- default: 1
- }
- },
- name: "froala-editor",
- data() {
- const that = this;
- return {
- editor: null,
- uploadImage: {
- loading: false,
- previewVisible: false,
- previewImage: "",
- imgFile: {},
- isSize: false,
- isType: false
- },
- fileList: [],
- body: {
- content: null,
- textLen: 0,
- leftoverLen: 10000,
- sumLen: 10000,
- error_tip: "",
- error_show: false
- },
- config: {
- toolbarButtons: tool,
- // theme: "dark",// 主题
- placeholderText: this.placeholder || "编辑课程介绍",
- language: "zh_cn", // 国际化
- imageUploadURL: "", // 上传 url
- imageUploadParams: { token: "", i:"", ak: "", f: 9 },
- fileUploadURL: "",
- fileUploadParams: { token: "", i:"", ak: "", f: 9 },
- videoUploadURL: "",
- videoUploadParams: { token: "", i:"", ak: "", f: 9 },
- quickInsertButtons: ["image", "table", "ul", "ol", "hr"], // 快速插入项
- // toolbarVisibleWithoutSelection: true,// 是否开启 不选中模式
- // disableRightClick: true,// 是否屏蔽右击
- colorsHEXInput: true, // 关闭 16 进制色值
- toolbarSticky: false, // 操作栏是否自动吸顶,
- // Colors list.
- colorsBackground: [
- "#15E67F",
- "#E3DE8C",
- "#D8A076",
- "#D83762",
- "#76B6D8",
- "REMOVE",
- "#1C7A90",
- "#249CB8",
- "#4ABED9",
- "#FBD75B",
- "#FBE571",
- "#FFFFFF"
- ],
- colorsStep: 6,
- colorsText: [
- "#15E67F",
- "#E3DE8C",
- "#D8A076",
- "#D83762",
- "#76B6D8",
- "REMOVE",
- "#1C7A90",
- "#249CB8",
- "#4ABED9",
- "#FBD75B",
- "#FBE571",
- "#FFFFFF"
- ],
- zIndex: 2501,
- height: this.height || "250",
- // autofocus: true,
- events: {
- initialized: function() {
- that.editor = this;
- that.body.content = that.value;
- that.EditorChange();
- },
- blur: () => {
- console.log("blur....");
- that.$emit("blur");
- },
- contentChanged: () => {
- that.EditorChange();
- },
- "image.beforeUpload": function(images) {
- // 自定义上传图片
- that.beforeUpload(images[0]);
- return false;
- },
- "file.beforeUpload": function() {
- // Image was uploaded to the server.
- return true;
- },
- "video.beforeUpload": function() {
- // Image was uploaded to the server.
- return true;
- }
- }
- }
- };
- },
- watch: {
- value: {
- handler: function(news, old) {
- if (news) {
- this.body.content = this.value;
- }
- },
- deep: true // 对象内部的属性监听, 也叫深度监听
- },
- "body.content": function(newVal, old) {
- if (old !== newVal) {
- let val = this.getSimpleText(this.editor.HTML.get(true));
- }
- },
- label: function(newVal, old) {
- if (old !== newVal) {
- this.editor.HTML.set(newVal);
- }
- }
- },
- mounted() {
- setTimeout(() => {
- this.setIndex(this.index);
- }, 200);
- },
- methods: {
- // 更改富文本层级
- setIndex(val) {
- this.$nextTick(() => {
- let dv = document.getElementsByClassName("fr-box");
- for (let i in dv) {
- if (!dv[i].style) {
- return;
- }
- dv[i].style.cssText = "z-index:" + val;
- }
- });
- },
- // 富文本中提取纯文本
- getSimpleText: HTML => {
- var re1 = new RegExp('<p data-f-id="pbf".+?</p>', "g"); // 匹配 HTML 标签的正则表达式,"g" 是搜索匹配多个符合的内容
- var msg = HTML.replace(re1, ""); // 执行替换成空字符
- return msg;
- },
- EditorChange() {
- if (this.editor == null) return;
- console.log(this.editor, "this.editor");
- const editorCount = this.editor.charCounter.count();
- this.body.textLen = editorCount;
- this.body.leftoverLen = this.body.sumLen - editorCount;
- this.$emit("change", this.body);
- },
- beforeUpload(file) {
- const that = this;
- this.uploadImage.loading = true;
- const formData = new FormData();
- formData.append("formFile", file);
- this.$store
- .dispatch("UploadImg", formData)
- .then(res => {
- this.uploadImage.loading = false;
- if (res.code === 200) {
- that.uploadImage.imgFile = JSON.parse(res.data);
- const url = that.uploadImage.imgFile.data;
- // 插入图片
- that.editor.HTML.insert(
- "<img src=" + that.uploadImage.imgFile.data + ">", //HTML
- false // 在插入之前是否应清除 HTML
- ); // 插入图片
- } else {
- this.fileList = [];
- this.$message.error(res.msg);
- }
- })
- .catch(err => {
- this.uploadImage.loading = false;
- this.$message.error("上传失败");
- });
- }
- return false;
- }
- }
- };
- </script>
- <style>
- .editor-wrap> div {
- width: 100%;
- }
- .fr-wrapper> div[style*="z-index:9999;"],
- .fr-wrapper> div[style*="z-index: 9999;"] {
- height: 0;
- overflow: hidden;
- position: absolute;
- top: -1000000px;
- opacity: 0;
- }
- .fr-view{
- position: absolute;
- top: 0;
- }
- .fr-placeholder{
- margin-top: 0;
- }
- .fr-box .second-toolbar {
- display: none;
- }
- .fr-box .second-toolbar #logo {
- width: 0 !important;
- height: 0 !important;
- overflow: hidden;
- }
- .fr-box .fr-toolbar {
- border-radius: 4px 4px 0 0;
- border-color: #dcdfe6;
- }
- .fr-box .second-toolbar {
- border-radius: 0 0 4px 4px;
- border-color: #dcdfe6;
- }
- .fr-box .fr-wrapper {
- border-color: #dcdfe6 !important;
- }
- </style>
2. 自定义上传图片
- config: {
- events: {
- "image.beforeUpload": function(images) {
- // 自定义上传图片
- that.beforeUpload(images[0]);
- return false;
- },
- }
- }
- // 上传成功后插入图片
- that.editor.HTML.insert(
- "<img src=" + that.uploadImage.imgFile.data + ">", //HTML
- false // 在插入之前是否应清除 HTML
- ); // 插入图片
3. 小坑
该编辑器属于付费使用, 不付费默认会带上他的标语, 所以保存内容的时候要过滤
import froalaEditor from "@/components/froalaEditor.vue"; export default { components: { froalaEditor, }, data() { const that = this; return { editor: { p: '<p data-f-id="pbf"style="text-align: center; font-size: 14px; margin-top: 30px; opacity: 0.65; font-family: sans-serif;">Powered by <a href="https://www.froala.com/wysiwyg-editor?pb=1"title="Froala Editor">Froala Editor</a></p>', } } } } if (newData.seriesDetail.indexOf(this.editor.p)> -1) { newData.seriesDetail = newData.seriesDetail.replace( this.editor.p, "" ); }
4. 官网文档
https://froala.com/wysiwyg-editor/docs/framework-plugins/vue/#model
3, 效果
富文本编辑器. PNG
总结
用了这个富文本编辑器后, 感觉我很嫌弃以前用过的编辑器, 哈哈, 还有, 我添加了自定义上传图片的案例, 小伙伴们可以按照自己的实际情况来修改, 上传视频的话也是如此. 拜拜
--By kkc_hq
来源: http://www.jianshu.com/p/003719fcf8dc