前言
写公司的后台管理系统需要富文本编辑框 因为表格使用的是avue的框架,所以刚开始选择编辑器的时候是想用avue基于wangEditor封装的组件 avue-plugin-ueditor 但是由于过度封装的问题导致不适合我们公司上传照片的需求,我们是前端OSS直传的,需要在上传照片的时候把签名一起带过去验证 但是avue没办法带数据,且没办法自定义传输方法,无奈只能放弃,直接使用wangEditor,因为很多地方都会用到富文本编辑框,所以打算把它封装成一个组件 复用性比较强,比较方便
1.使用wangEditor
官网 www.wangeditor.com/v5/installa…
- 安装 editor 使用 npm install @wangeditor/editor --save
- 安装vue2所使用的组件 使用npm install @wangEditor/editor-for-vue --save
- 因为我这里使用的技术栈是vue2 所以只展示vue2的用法
2.封装
- 在组件中引入wangEditor组件
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
- 在组件中使用它
<template slot="detailsForm">
<!-- // wangEditor富文本编辑器的封装组件 -->
<div class="editWidth" style="border: 1px solid #ccc;">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editor"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="height: 500px; overflow-y: hidden;"
v-model="html"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="onCreated"
@onChange="increase"
/>
</div>
</template>
其中 toolbarConfig editorConfig 分别是富文本编辑器的工具栏配置和编辑配置 我这里工具栏使用的是默认配置,感兴趣或者有需求的同学可以去官网看
editorConfig: {
placeholder: "请输入内容...",
readOnly: false,
MENU_CONF: {
uploadImage: {
server: "上传服务器的地址",
customUpload: ""
}
}
},
这里是我所使用的编辑配置 重点说一下配置自定义上传方法 想要配置自定义上传方法必须要在 editorConfig配置下的MENU_CONF菜单下的uploadImage的customUpload里面定义方法 不清楚的可以自行去看官网(这里是定义在data里面的还没有定义方法)
- 定义自定义上传方法
this.editorConfig.readOnly = this.readOnly;
this.editorConfig.MENU_CONF["uploadImage"] = {
async customUpload(file, insertFn) {
let imageUrl = await that.$uploadImage(file);
insertFn(imageUrl);
}
};
我这里是定义在created生命周期里面的可以看到在里面我自定义了 customUpload上传方法 里面的 that.$uploadImage(file)是我自己按照公司需求封装的上传照片的方法,不是wangEditor自带的方法,你们可以写你们的上传方法 insertFn就是把图片插入编辑器里面的方法,这个是wangEditor自带的,直接使用,把后端返回的图片地址传入其中即可
有一点需要注意:就是 @onCreated="onCreated"方法时必须的,否则工具栏加载不出来
// 工具栏初始化
onCreated(editor) {
this.editor = Object.seal(editor); // 一定要用 Object.seal() ,否则会报错
console.log("我初始化了1", this.value);
this.html = this.value;
},
``
父子组件交互传值
既然是封装组件 那么就必须要和父组件有所交互,进行数据传输 主要就是实现父子组件使用v-model双向绑定数据 同步访问 有一下两种方式
第一种:利用 this.$emit("input","value");
首先 如果你在父组件中使用了v-model对子组件进行了值的绑定 比如
<wangEditor v-model="localValue" :readOnly="isreadOnly" />
我对wangEditor子组件进行了localValue的数据绑定 那么正常情况下在子组件中会默认将父组件中的v-model绑定的值 赋给子组件中名为value的props,但是你依然需要在子组件中的props定义value才行
value: {
type: String,
default: 0
},
readOnly: {
type: Boolean,
default: false
}
},
这里我在props声明的value接受的就是localValue传过来的值,因为编辑框是在在子组件中的 所以要把值传给父组件 所以这里就需要到了 this.$emit("input","value"); 这里绑定的事件是 input 所以可以直接把value直接传给父组件的localValue里面 通过wangEditor组件的@onChange监听increase方法 进行传值
increase() {
this.$emit("input", this.html);
}
还有就是 我在这里总共是给子组件传了两个参数 一个是 localValue 还有一个是控制是否可编辑的readOnly参数,需要注意的一点是 就是正常情况下 有时候只会在第一次加载的时候给子组件传的值他才会生效,后面你在父组件里面通过事件去改变传的值会不生效 原因并不是没把值传过去,而是他把值传过去了 但是并没有执行赋值操作 (第一次赋值是在子组件生命周期里面赋值,你再次传值并没有执行生命周期 所以相当于传过去了,但数据没有更新) 所以需要使用watch监听数据 来实时更新子组件的状态
watch: {
readOnly(newValue) {
this.editorConfig.readOnly = newValue;
},
value(newValue){
this.html= newValue
}
},
现在已经完成父子组件的双向绑定了,你在子元素中触发increase()函数或者在父组件中改变localValue变量,父子组件都会分别触发值的改变 配合watch就可以监听了
第二种方法 使用model进行绑定
我使用的是第一种方法 所以第二种方法仅仅是为了记录 下面是参考文档blog.csdn.net/qq_43061933…
可以去看vue的官网概念
允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。
简单来说就是父组件改变值,子组件的值会改变,子组件改变值,父组件的值也会改变;就是将父子组件实现数据双向绑定的效果。
<template>
<div> <son v-model='formData.value'></son> <button @click="changeVal">点击变化value</button> </div>
</template>
watch :{
value (val) {
console.log( '父组件看见的' + val)
}
},
这里使用 v-model绑定了值 changeVal方法就是的单纯改变formData.value的值而已
子组件
<div> <input type="text" v-model="childValue" @input="childInputChange"/> </div>
子组件里面 使用model 定义一个prop和event prop就是props声明的参数 它就相当于第一种方法种的value 接受的是父组件v-model绑定的值 childValueChange事件就是input事件 需要在data里面关联childValue和fatherValue 然后绑定 childValue
export default {
name: 'son',
model: { // 定义model
// 父组件v-model绑定的值传递给props中的fatherValue
prop: 'fatherValue',
// 通过emit触发childValueChange将内部值传递给父组件v-model绑定的值
event: 'childValueChange'
},
props:{
fatherValue:{ // 接受父组件传递的值
type: String,
default:''
}
},
data () {
return {
childValue: this.fatherValue// 关联值
}
},
watch :{
fatherValue (val) { //这一步重新赋值 是因为props里面的fatherValue改变了 但是data里面的childValue不会改变 从而视图不会更新
console.log( '父组件看见的' + val)
this.childValue = val
}
},
methods:{
childInputChange(){
// 通过$emit触发childValueChange(model内定义)事件,将内部值传递给给父组件
this.$emit('childValueChange', this.childValue)
}
},
}
</script>
————————————————
版权声明:本文为CSDN博主「平头的春天丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43061933/article/details/125392777