Vue.js 3.5中如何获取插槽的原始文本内容(保留换行格式)
Vue.js 3.5中如何获取插槽的原始文本内容(保留换行格式)
我太懂你的痛点了——做markdown可编辑组件的时候,换行和空白格式就是核心命脉,Vue默认处理插槽文本时确实会把多余的换行、空格给“自动优化”掉,但这绝对不是Vue的功能缺失,只是你需要用点小技巧绕过它的默认行为!
为什么你之前拿不到带换行的原始内容?
Vue的模板编译器为了优化渲染性能,会自动压缩文本节点里的多余空白、换行和制表符,哪怕是插槽传递的内容也不例外。而且你之前用innerText获取内容时,浏览器本身也会把连续的换行/空格转换成单个空格,双重作用下,自然就丢了你需要的格式。
解决方法:用<pre>标签+textContent保留原始格式
<pre>标签的原生特性就是会完整保留文本的换行、空格和缩进,而且Vue不会对<pre>内部的文本做空白压缩。我们可以把插槽内容塞进一个隐藏的<pre>里,再通过textContent(不是innerText)获取原始内容,完美解决问题。
下面是适配你场景的完整组件代码示例:
<template> <div class="markdown-editable"> <!-- 隐藏的pre标签:用来捕获带格式的原始插槽内容 --> <pre ref="rawSlotContent" class="visually-hidden"><slot></slot></pre> <!-- 非编辑模式:渲染markdown为HTML --> <div v-if="!editing"> <div v-html="parsedMarkdown"></div> <button @click="editing = true" class="btn btn-secondary"> <i class="fa fa-pencil"></i> 编辑 </button> </div> <!-- 编辑模式:显示文本框和操作按钮 --> <div v-else> <textarea v-model="text" rows="5" class="form-control w-100"></textarea> <button @click="editing = false" class="btn btn-danger mt-2 me-2"> <i class="fa fa-close"></i> 取消 </button> <button @click="saveEdit" class="btn btn-success mt-2"> <i class="fa fa-check"></i> 保存 </button> </div> </div> </template> <script setup> import { ref, onMounted, computed } from 'vue'; import marked from 'marked'; const rawSlotContent = ref(null); const editing = ref(false); const text = ref(''); // 组件挂载时,从pre标签获取原始插槽文本 onMounted(() => { if (rawSlotContent.value) { // textContent会完整保留原始文本的换行和空格 text.value = rawSlotContent.value.textContent.trimEnd(); // 这里加trimEnd是为了去掉插槽末尾可能的多余空行,根据你的需求可以调整 } }); // 计算属性:把文本转成HTML const parsedMarkdown = computed(() => { return marked.parse(text.value); }); // 保存编辑的方法(你的AJAX逻辑) const saveEdit = async () => { // 这里写你的AJAX请求,把text.value传给后端 // await axios.post('/api/save', { content: text.value }); editing.value = false; }; </script> <style scoped> /* 让pre标签隐藏但不脱离DOM */ .visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } .markdown-editable { margin: 1rem 0; } </style>
关键细节说明
- 用
<pre>而非<div>:<pre>的原生特性会强制保留所有文本格式,Vue不会对其内部内容做空白压缩,这是核心。 textContentvsinnerText:innerText会根据浏览器的布局规则自动处理换行和空格,而textContent是直接读取DOM节点里的原始文本内容,包括所有你需要的换行和空格。- 隐藏
<pre>的样式:visually-hidden类是标准的无障碍隐藏样式,保证元素存在于DOM中但完全不可见,不影响页面布局和渲染。
适配你的场景优势
- 组件初始化时,会自动从插槽获取带完整换行的原始markdown文本
- 非编辑模式正常渲染HTML,编辑模式文本框里的内容完全保留markdown格式
- 不需要额外的API请求,直接复用页面中已有的文本内容,完美支持无JS环境的浏览
这完全能解决你遇到的问题,不是Vue做不到,只是需要利用原生HTML的特性来绕过Vue的默认优化~
内容来源于stack exchange




