You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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>

关键细节说明

  1. <pre>而非<div><pre>的原生特性会强制保留所有文本格式,Vue不会对其内部内容做空白压缩,这是核心。
  2. textContent vs innerTextinnerText会根据浏览器的布局规则自动处理换行和空格,而textContent是直接读取DOM节点里的原始文本内容,包括所有你需要的换行和空格。
  3. 隐藏<pre>的样式visually-hidden类是标准的无障碍隐藏样式,保证元素存在于DOM中但完全不可见,不影响页面布局和渲染。

适配你的场景优势

  • 组件初始化时,会自动从插槽获取带完整换行的原始markdown文本
  • 非编辑模式正常渲染HTML,编辑模式文本框里的内容完全保留markdown格式
  • 不需要额外的API请求,直接复用页面中已有的文本内容,完美支持无JS环境的浏览

这完全能解决你遇到的问题,不是Vue做不到,只是需要利用原生HTML的特性来绕过Vue的默认优化~

内容来源于stack exchange

火山引擎 最新活动