需求:
页面局部文本内容需要编辑
实现:
方案一:
texteara 内容换行‘\n’ 替换未<br> ,不支持富文本内容,加粗斜线等等
方案二:
使用@toast-ui/vue-editor富文本编辑 封装editor和viewer
“@toast-ui/vue-editor”: “^3.2.3”,
思想来源于vue-element-admin
vue-element-admin github
vue-editor使用方法
@toast-ui/editor使用
实现过程
封装editor
<template>
<editor
:ref="refEditor"
:initial-value="editorText"
:options="editorOptions"
initial-edit-type="markdown"
preview-style="vertical"
@change="onEditorChange"
/>
</template>
<script>
import '@toast-ui/editor/dist/toastui-editor.css'
import { generateUUID } from '@/utils/generateUUID'
import { Editor } from '@toast-ui/vue-editor'
export default {
components: {
editor: Editor
},
props: {
editorValue: {
type: String,
default: ''
},
refEditor: {
type: String,
default: generateUUID()
}
},
data() {
return {
editorText: '',
editorOptions: {
minHeight: '100px',
language: 'zh-CN',
useCommandShortcut: true,
usageStatistics: true,
hideModeSwitch: true,
toolbarItems: [
['heading', 'bold', 'italic', 'strike'],
['hr', 'quote'],
['ul', 'ol', 'task', 'indent', 'outdent'],
['table', 'image', 'link'],
['code', 'codeblock'],
['scrollSync']
]
}
}
},
watch: {
editorValue: {
handler: function(newVal) {
this.$nextTick(() => {
this.editorText = this.$refs[this.refEditor].invoke('setHTML', newVal)
})
},
immediate: true
}
},
methods: {
onEditorChange() {
this.$emit('onEditorChange', this.$refs[this.refEditor].invoke('getHTML'))
},
cancel() {
this.editorText = this.$refs[this.refEditor].invoke('setHTML', this.editorValue)
}
}
}
</script>
封装viewer
关键代码 this.$refs[this.editorRef].editor.preview.setHTML(newVal)
<template>
<Viewer
:ref="editorRef"
:initial-value="viewerText"
:options="editorOptions"
/>
</template>
<script>
import '@toast-ui/editor/dist/toastui-editor-viewer.css'
import { Viewer } from '@toast-ui/vue-editor'
export default {
components: {
Viewer
},
props: {
editorValue: {
type: String,
default: ''
},
editorRef: {
type: String,
required: false,
default() {
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
}
}
},
data() {
return {
flag: false,
viewerText: '',
editorOptions: {
minHeight: '100px',
language: 'zh-CN',
useCommandShortcut: true,
usageStatistics: false,
hideModeSwitch: true,
toolbarItems: [
['heading', 'bold', 'italic', 'strike'],
['hr', 'quote'],
['ul', 'ol', 'task', 'indent', 'outdent'],
['table', 'image', 'link'],
['code', 'codeblock'],
['scrollSync']
]
}
}
},
computed: {
// viewerText: {
// get() {
// return this.editorValue
// },
// set(val) {
// // this.$emit('input', [...val])
// }
// },
// viewerText() {
// return this.editorValue
// }
},
watch: {
editorValue: {
handler: function(newVal) {
this.viewerText = newVal
this.$refs[this.editorRef].editor.preview.setHTML(newVal)
}
}
},
mounted() {
this.$refs[this.editorRef].editor.preview.setHTML(this.editorValue)
}
}
</script>
使用viewer和editor
<template>
<div class="charts-show">
<div v-if="chartTitle" class="chart-title"> {{ chartTitle }}</div>
<div v-if="chartId">
<Chart
:id="chartId"
:height="`${chartHeight}px`"
width="100%"
:options="chartOptions"
@chartClick="handleChartClick"
@chartDblClick="handleChartDblClick"
/>
</div>
<slot />
<div v-if="chartEditor !== 'null'">
<div v-if="showEditor" class="editor-wrap">
<div class="editor-info">
<Editor :ref-editor="`${chartId}-Editor`" :editor-value="chartEditorVal" @onEditorChange="handleEditorChange" />
</div>
<div class="editor-wrap-icon">
<i class="el-icon-check" style="color: #409EFF" @click="ok" />
<i class="el-icon-close" style="color: #409EFF;margin-top: 10px;" @click="cancel" />
</div>
</div>
<div v-else class="viewer-wrap" @dblclick="handleViewer">
<Viewer :editor-ref="`${chartId}-Viewer`" :editor-value="chartViewerVal" />
<!-- <Viewer :initialValue="chartViewerVal" /> -->
<!-- <div v-html="chartViewerVal" /> -->
</div>
</div>
</div>
</template>
<script>
import Chart from '@/components/Charts/CommonChart.vue'
// import MarkdownEditor from '@/components/MarkdownEditor/index.vue'
import '@toast-ui/editor/dist/toastui-editor.css'
import Editor from '@/components/MarkdownEditor/Editor.vue'
import Viewer from '@/components/MarkdownEditor/Viewer.vue'
// import Viewer from "@/components/MarkdownEditor/index.vue";
import '@toast-ui/editor/dist/toastui-editor-viewer.css'
// import Viewer from '@toast-ui/editor/dist/toastui-editor-viewer'
export default {
name: 'ChartsShow',
components: {
Chart,
Editor,
Viewer
},
props: {
chartTitle: {
require: true,
type: String,
default: ''
},
chartId: {
require: true,
type: String,
default: ''
},
chartOptions: {
require: true,
type: Object,
default: () => {}
},
chartHeight: {
type: Number,
default: 500
},
chartEditor: {
type: String,
default: ''
},
chartEditorId: {
type: String,
default: ''
},
analysisType: {
type: String,
default: ''
}
},
data() {
return {
chartEditorVal: '',
chartViewerVal: '',
showEditor: false,
editorOptions: {
minHeight: '100px',
language: 'zh-CN',
useCommandShortcut: true,
usageStatistics: false,
hideModeSwitch: true,
toolbarItems: [
['heading', 'bold', 'italic', 'strike'],
['hr', 'quote'],
['ul', 'ol', 'task', 'indent', 'outdent'],
['table', 'image', 'link'],
['code', 'codeblock'],
['scrollSync']
]
}
}
},
watch: {
chartEditor(newVal) {
this.chartEditorVal = newVal
this.chartViewerVal = newVal
},
chartId(newVal) {
this.showEditor = false
}
},
// create() {
// this.showEditor = false
// },
methods: {
ok() {
this.$emit('editorChange', { id: this.chartEditorId, analysisType: this.analysisType, analysisContent: this.chartViewerVal })
this.showEditor = false
},
cancel() {
this.chartEditorVal = this.chartEditor
this.chartViewerVal = this.chartEditor
this.showEditor = false
},
handleEditorChange(value) {
this.chartEditorVal = value
this.chartViewerVal = value
},
// 切换分析内容
handleChartClick(value) {
console.log('handleChartClick', { id: this.chartEditorId, analysisType: this.analysisType, month: value.name })
this.$emit('chartClick', { id: this.chartEditorId, analysisType: this.analysisType, month: value.name })
this.showEditor = false
},
// 跳转页面
handleChartDblClick(value) {
console.log('handleChartDblClick', value)
this.$emit('chartDblClick', { projectKey: value.seriesId })
},
// 双击查询
handleViewer() {
this.showEditor = !this.showEditor
}
}
}
</script>
<style lang="scss" scoped>
.charts-show {
margin-bottom: 36px;
.chart-title {
border-left: 3px solid #1890ff;;
padding-left: 8px;
margin-left: 16px;
}
.editor-wrap{
margin-left: 3%;
margin-right: 4%;
display: flex;
.editor-info {
flex: 1;
}
.editor-wrap-icon {
width: 20px;
margin-left: 10px;
display: flex;
flex-direction: column;
justify-content: center;
}
}
.viewer-wrap{
margin-left: 3%;
margin-right: 4%;
padding: 8px 16px;
border: 1px solid #2f2f2f;
}
}
</style>