Vue中Tiptap富文本写入JSON遇值为空问题(含动态表格场景)
动态表格中Tiptap富文本内容无法写入JSON的解决方案
问题描述
在Vue文件中使用Tiptap富文本编辑器,动态表格内也嵌入了该编辑器,但尝试将表格中的富文本内容写入JSON时,对应值显示为undefined或null,无法正常添加。以下是原始代码:
<template> <v-container> <v-form lazy-validation ref="form"> <v-card class="pa-5" >rich text editor <v-row> <Tiptap v-model="richText" /> </v-row> </v-card> <table class="responsive-table"> <thead> <tr> <th scope="col">#</th> <th class="text-left">Sample Depth</th> <th class="text-left">Text</th> </tr> </thead> <tbody> <tr v-for="(imageTable, index) in imageTables" :key="index"> <td scope="row" class="trashIconContainer"> <i class="far fa-trash-alt" @click="deleteimageRow(index, imageTable)" ></i> </td> <td data-label="sampleDepth"> <input v-model="imageTable.sampleDepth" class="form-control" type="number" /> </td> <td> <Tiptap v-model="text" /> </td> <td> <button @click="deleteimageRow" class="is-danger">Delete</button> </td> </tr> </tbody> </table> <button type="button" class="btn btn-info" @click="addimageRow"> <i class="fas fa-plus-circle"></i> Add </button> <v-row> <v-col> <v-btn width="100%" class="primary" :loading="isPdfGenerating" @click="generateReport(true)" >Generate draft report</v-btn > </v-col> </v-row> <v-row> <v-col> <v-btn width="100%" class="primary" :disabled="!isPdfGenerated" @click="savePdf" >Download generated report</v-btn > </v-col> <v-col> <v-btn width="100%" class="primary" :disabled="!isPdfGenerated" @click="generateReport(false)" >Make report official</v-btn > </v-col> </v-row> </v-form> </v-container> </template> <script> import Tiptap from "/src/components/TiptapView.vue"; export default { name: "TableView", components: { Tiptap, }, data: () => ({ field: null, fieldRule: [], fieldLines: null, isPdfGenerating: false, isPdfGenerated: false, pdfData: null, imageUploaded: false, imageTables: [{ sampleDepth: "", text: "" }], }), created() {}, methods: { addimageRow() { this.imageTables.push({ sampleDepth: "", sampleNumber: "", zoomFactor: "", text: "", }); console.log(this.imageTables); }, uppercase() { //pass }, deleteimageRow(index, imageTables) { var idx = this.imageTables.indexOf(imageTables); console.log(idx, index); this.imageTables.splice(idx, 2); }, generateReport: function (isDraft = true) { this.$refs.form.validate(); this.$emit("pdfGenerated", null); this.isPdfGenerating = true; this.isPdfGenerated = false; let jsonData = { richText: this.richText, imageTables: this.imageTables, key: this.$store.state.key, isDraft: isDraft, }; console.log(jsonData); this.$axios .post(this.$backendUrl + "/table", jsonData) .then((response) => { console.log(response); this.pdfData = { data: response.data }; this.$emit("pdfGenerated", this.pdfData); this.isPdfGenerated = true; this.isPdfGenerating = false; }) .catch((error) => { console.log(error); this.isPdfGenerating = false; this.isPdfGenerated = false; if (error.response.status == 401) { this.$emit("unauthorized"); } if (error.response.status == 404) { window.alert(error.response.data.message); } }) .then(function () {}); }, savePdf: function () { var blob = new Blob([this.pdfData.data], { type: "application/pdf" }); var link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); var fileName = "Output"; link.download = fileName; link.click(); }, }, }; </script>
问题根源
- 表格内Tiptap绑定错误:表格中的Tiptap组件绑定的是全局
text变量,而非当前行imageTable对象的text属性,导致富文本内容无法存入imageTables数组。 richText未初始化:顶部Tiptap绑定的richText未在data中定义,会导致该值为undefined。- 删除行方法逻辑错误:
deleteimageRow中splice(idx, 2)会一次性删除2行,应该改为splice(idx, 1)只删除当前行。
修复后的代码
<template> <v-container> <v-form lazy-validation ref="form"> <v-card class="pa-5"> rich text editor <v-row> <Tiptap v-model="richText" /> </v-row> </v-card> <table class="responsive-table"> <thead> <tr> <th scope="col">#</th> <th class="text-left">Sample Depth</th> <th class="text-left">Text</th> </tr> </thead> <tbody> <tr v-for="(imageTable, index) in imageTables" :key="index"> <td scope="row" class="trashIconContainer"> <i class="far fa-trash-alt" @click="deleteimageRow(index)" ></i> </td> <td data-label="sampleDepth"> <input v-model="imageTable.sampleDepth" class="form-control" type="number" /> </td> <td> <Tiptap v-model="imageTable.text" /> </td> <td> <button @click="deleteimageRow(index)" class="is-danger">Delete</button> </td> </tr> </tbody> </table> <button type="button" class="btn btn-info" @click="addimageRow"> <i class="fas fa-plus-circle"></i> Add </button> <v-row> <v-col> <v-btn width="100%" class="primary" :loading="isPdfGenerating" @click="generateReport(true)" >Generate draft report</v-btn> </v-col> </v-row> <v-row> <v-col> <v-btn width="100%" class="primary" :disabled="!isPdfGenerated" @click="savePdf" >Download generated report</v-btn> </v-col> <v-col> <v-btn width="100%" class="primary" :disabled="!isPdfGenerated" @click="generateReport(false)" >Make report official</v-btn> </v-col> </v-row> </v-form> </v-container> </template> <script> import Tiptap from "/src/components/TiptapView.vue"; export default { name: "TableView", components: { Tiptap, }, data: () => ({ field: null, fieldRule: [], fieldLines: null, isPdfGenerating: false, isPdfGenerated: false, pdfData: null, imageUploaded: false, richText: "", imageTables: [{ sampleDepth: "", text: "" }], }), created() {}, methods: { addimageRow() { this.imageTables.push({ sampleDepth: "", sampleNumber: "", zoomFactor: "", text: "", }); console.log(this.imageTables); }, uppercase() { //pass }, deleteimageRow(index) { this.imageTables.splice(index, 1); }, generateReport: function (isDraft = true) { this.$refs.form.validate(); this.$emit("pdfGenerated", null); this.isPdfGenerating = true; this.isPdfGenerated = false; let jsonData = { richText: this.richText, imageTables: this.imageTables, key: this.$store.state.key, isDraft: isDraft, }; console.log(jsonData); this.$axios .post(this.$backendUrl + "/table", jsonData) .then((response) => { console.log(response); this.pdfData = { data: response.data }; this.$emit("pdfGenerated", this.pdfData); this.isPdfGenerated = true; this.isPdfGenerating = false; }) .catch((error) => { console.log(error); this.isPdfGenerating = false; this.isPdfGenerated = false; if (error.response.status == 401) { this.$emit("unauthorized"); } if (error.response.status == 404) { window.alert(error.response.data.message); } }); }, savePdf: function () { var blob = new Blob([this.pdfData.data], { type: "application/pdf" }); var link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); var fileName = "Output"; link.download = fileName; link.click(); }, }, }; </script>
验证
修改后点击"Generate draft report",console.log(jsonData)会显示imageTables数组中每个对象的text属性已正确存储富文本内容,richText也能正常取值。
内容的提问来源于stack exchange,提问作者Mohamed Hassan
相关产品推荐
相关产品推荐

