284 lines
6.2 KiB
Vue
284 lines
6.2 KiB
Vue
<template>
|
|
<div id="editor-container" :call="option" :change:call="editorModule.call"><!-- 编辑器 --></div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
timer:null,
|
|
option:null,
|
|
events:[],
|
|
}
|
|
},
|
|
methods: {
|
|
insertText(text,successFn,errorFn){
|
|
this.addEvent('insertText',text);
|
|
},
|
|
insertImgEmoji(src,successFn,errorFn){
|
|
this.addEvent('insertImgEmoji',src);
|
|
},
|
|
insertMention(username,userid){
|
|
this.addEvent('insertMention',{
|
|
username,
|
|
userid
|
|
});
|
|
},
|
|
clear(){
|
|
this.addEvent('clear');
|
|
},
|
|
blur(){
|
|
this.addEvent('blur');
|
|
},
|
|
focus(){
|
|
this.addEvent('focus');
|
|
},
|
|
setHtml(html){
|
|
this.addEvent('setHtml',html);
|
|
},
|
|
getText(){
|
|
this.addEvent('getText');
|
|
},
|
|
getHtml(){
|
|
console.log(this);
|
|
return 1;
|
|
this.addEvent('getHtml');
|
|
},
|
|
getSelectionPosition(){
|
|
this.addEvent('getSelectionPosition');
|
|
},
|
|
getParentNode(){
|
|
this.addEvent('getParentNode');
|
|
},
|
|
// 调用
|
|
call() {
|
|
if (this.timer) return;
|
|
// 消费事件队列(生产者/消费者机制)
|
|
this.timer = setInterval(() => {
|
|
if (this.events.length) {
|
|
this.option = this.events.shift();
|
|
console.log(this.option);
|
|
} else {
|
|
clearInterval(this.timer);
|
|
this.timer = null;
|
|
}
|
|
}, 10);
|
|
},
|
|
// 添加事件队列
|
|
addEvent(name, data) {
|
|
// #ifdef APP-PLUS
|
|
// tips:由于采用监听option改变来调用方法,
|
|
// 如果连续变化两次option,渲染层只会则监听到最后一次
|
|
// 导致调用丢失,所以采用事件队列形式解决,稍微延时10ms
|
|
// 等待渲染进程监听到option变化,在进行更改option
|
|
// 从性能上,几乎无感可以放心使用
|
|
const option = {
|
|
id: this.genId(),
|
|
name: `_${name}`,
|
|
data
|
|
};
|
|
this.events.push(option);
|
|
this.call();
|
|
// #endif
|
|
|
|
// #ifndef APP-PLUS
|
|
this[`_${name}`] && this[`_${name}`](data);
|
|
// #endif
|
|
},
|
|
genId() {
|
|
let result = '';
|
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
const charactersLength = characters.length;
|
|
for (let i = 0; i < 30; i++) {
|
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
}
|
|
return Date.now() + result;
|
|
},
|
|
// 开始拖拽地图
|
|
UserEvent(data) {
|
|
//console.log(data);
|
|
this.$emit('onUserEvent',data);
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<script module="editorModule" lang="renderjs">
|
|
export default {
|
|
data() {
|
|
return {
|
|
_editorIns:null
|
|
}
|
|
},
|
|
mounted() {
|
|
this._initEditor();
|
|
},
|
|
methods: {
|
|
_initEditor() {
|
|
if (typeof window.wangEditor === 'function') {
|
|
this._initialize();
|
|
} else {
|
|
const script = document.createElement('script');
|
|
script.onload = this._initialize;
|
|
script.src = "static/wangeditor/index.js";
|
|
document.head.appendChild(script);
|
|
|
|
const link = document.createElement('link');
|
|
link.href = "static/wangeditor/style.css";
|
|
link.rel = "stylesheet";
|
|
document.head.appendChild(link);
|
|
}
|
|
},
|
|
// 创建地图
|
|
_initialize() {
|
|
const _this = this;
|
|
// 创建地图实例
|
|
const {createEditor} = window.wangEditor
|
|
|
|
const editor = createEditor({
|
|
selector: '#editor-container',
|
|
html: '',
|
|
config: {
|
|
placeholder: '',
|
|
maxLength:100,
|
|
hoverbarKeys:{
|
|
divider: {menuKeys: [],},
|
|
link: {menuKeys: [],},
|
|
image: {menuKeys: [],},
|
|
pre: {menuKeys: [],},
|
|
table: {menuKeys: [],},
|
|
text: {menuKeys: [],},
|
|
video: {menuKeys: [],},
|
|
},
|
|
onCreated(){
|
|
_this.$ownerInstance.callMethod('UserEvent',{
|
|
type:'ready'
|
|
});
|
|
},
|
|
//onDestroyed(){},
|
|
onFocus(){
|
|
_this.$ownerInstance.callMethod('UserEvent',{
|
|
type:'focus'
|
|
});
|
|
},
|
|
onBlur(){
|
|
_this.$ownerInstance.callMethod('UserEvent',{
|
|
type:'blur'
|
|
});
|
|
},
|
|
//onDestroyed(){},
|
|
onChange(editor) {
|
|
const html = editor.getHtml()
|
|
const text = editor.getText()
|
|
//console.log('editor content', html)
|
|
// 也可以同步到 <textarea>
|
|
_this.$ownerInstance.callMethod('UserEvent',{
|
|
type:'onChange',
|
|
html,
|
|
text,
|
|
});
|
|
},
|
|
}
|
|
});
|
|
editor.on('atevent',()=>{
|
|
_this.$ownerInstance.callMethod('UserEvent',{
|
|
type:'atevent'
|
|
});
|
|
})
|
|
this._editorIns = editor;
|
|
console.log(editor.insertText);
|
|
this._editorIns.insertText("text");
|
|
},
|
|
|
|
_insertText(text){
|
|
console.log('_insertText',text);
|
|
this._editorIns.insertText(text);
|
|
},
|
|
_insertNode(node){
|
|
this._editorIns.insertNode(node);
|
|
},
|
|
_insertImgEmoji(src){
|
|
this._insertNode({
|
|
type: 'image',
|
|
style:{width:'30px',height:'30px'},
|
|
src: src,
|
|
children: [{text: ''}],
|
|
});
|
|
},
|
|
_insertMention(data){
|
|
this._insertNode({
|
|
type: 'mention',
|
|
username: data.username,
|
|
userid: data.userid,
|
|
children: [{
|
|
text: ''
|
|
}],
|
|
});
|
|
},
|
|
_clear(){
|
|
this._editorIns.clear();
|
|
},
|
|
_delete(){
|
|
this._editorIns.deleteBackward();
|
|
},
|
|
_blur(){
|
|
this._editorIns.blur();
|
|
},
|
|
_focus(){
|
|
this._editorIns.focus();
|
|
},
|
|
_setHtml(html){
|
|
this._editorIns.setHtml(html);
|
|
},
|
|
_getText(){
|
|
return this._editorIns.getText();
|
|
},
|
|
_getHtml(){
|
|
return this._editorIns.getHtml();
|
|
},
|
|
_getSelectionPosition(){
|
|
return this._editorIns.getSelectionPosition();
|
|
},
|
|
_getParentNode(){
|
|
return this._editorIns.getParentNode();
|
|
},
|
|
// 通过监听call来调用渲染层方法
|
|
call(newValue, oldValue, ownerInstance, instance) {
|
|
if(!newValue){
|
|
return false;
|
|
}
|
|
if (this[newValue.name] && typeof this[newValue.name] === "function") {
|
|
this[newValue.name](newValue.data);
|
|
}
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.custom_editor {
|
|
::v-deep.w-e-text-container{
|
|
background: transparent;
|
|
|
|
[data-slate-editor]{
|
|
padding: 0;
|
|
}
|
|
p,
|
|
span{
|
|
height: 60rpx;
|
|
line-height: 60rpx;
|
|
}
|
|
p{
|
|
white-space: pre-wrap; /* 保留空格 */
|
|
margin: 0;
|
|
}
|
|
img{
|
|
}
|
|
span{
|
|
}
|
|
span[data-w-e-type="mention"]{
|
|
background-color: #ccc;
|
|
margin-right: 10px;
|
|
}
|
|
}
|
|
}
|
|
</style> |