实现文字(标准、分段)换行

换行文字的保存和输出

在使用textarea文本域时可通过添加换行如下

当我们重新后台拿到保存的数据后发现数据格式如下。

看到数据中的箭头感觉怪怪的,怎么还会有这个玩意,不管怎么样将数据打印出来看看

  created() {
    console.log(
      'start' + '-'.repeat(15),
      this.growthData.teacherComment,
      '-'.repeat(15) + 'end'
    )
  }
复制代码

原来箭头的地方就是换行,而且在打印出来的数据中已经实现了换行的效果。

实现换行

结合上面的结果,我直接将数据丢到标签里

<span>{{growthData.teacherComment}}</span>
复制代码

发现并没有实现换行。
那看到打印台中的数据为什么会有换行的效果,我试了如下代码

/\n/.test(growthData.teacherComment) //true
/\r/.test(growthData.teacherComment) //false
复制代码

原因是在textarea中输入回车换行再存入数据库时,这些回车换行符是以/r/n的形式存入数据库的,取出来也同样,但是到页面时html是无法将/r/n当换行处理的。

<br/>换行

在后台从数据库取出数据的时候将/r/n转换成<br/>

/**
 * 函数的功能是将 \n,\r用 <br/>替代
 * @param {String} str  传入的字符串
 * @returns {String} 返回替换后的字符串
*/
function replaceWithBr(str) {
  return str ? str.replace(/\n|\r/g, '<br/>') : ''
}
复制代码
  • 将字符串中的\n,\r都替换成了'<br/>'本质上还是字符串,{{}}文本插值插值的方式是无法识别出'<br/>'是字符串还是换行符。
  • 需要使用v-html按普通 HTML插入
  <span v-html="replaceWithBr(growthData.teacherComment)"></span>
复制代码

这个 span 的内容将会被替换成为属性值 replaceWithBr(growthData.teacherComment)的返回值

换行和段落效果

文字正常换行和段落换行的间隙是不相同的,来看下图效果。1处表示正常的文字换行,2处表示段落之间的换行。我们需要将两者的差别体现出来。

想法

  • 1处的换行实现有两种方式
    • 文字外部标签如span设置好宽度,当文字宽度超过设置的宽度自动会换行
    • 手动设置一行需要显示字数,超过字数后在后面拼接一个<br/>
  • 2处的换行可以在需要换行的文字外部添加<p>标签包裹实现段落间距

实现及效果

/**
 * 函数的功能是将 \n 用 p 标签替代
 * @param {String} str  传入的字符串
 * @returns {String} 返回替换后的字符串
*/
export function replaceBreakWithPTag(str, style) {
  if (!str) {
    return ''
  } else {
    style = style || 'style="text-indent: 2em; margin: 10px 0;"'
    str = `<p ${style}>` + str
    return str.replace(/\n|\r/g, `</p><p ${style}>`)
  }
}

复制代码

需要注意的是如果需要给 p标签添加样式需要在往函数中传入style样式对象,这里我也设置了默认的样式对象。有人会向使用class定义样式可以吗,答案是否定的,原因引用官网的话如下:

在单文件组件里,scoped 的样式不会应用在 v-html 内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对 v-html 的内容设置带作用域的 CSS,你可以替换为 CSS Modules 或用一个额外的全局 <style> 元素手动设置类似 BEM 的作用域策略。

指定文字数换行

/**
 * 实现文本换行和段落换行,需指定当行文本长度
 * @param {String} str  传入的字符串
 * @param {Number} length 当行文本长度
 * @param {String} style p标签的行内样式
 * @returns {String} 返回替换后的字符串
*/
export function wrapTextNumber(str, length, style) {
  if (!str) {
    return ''
  } else {
    // 每个段落的字符串
    let resultList = []
    // 通过\n标志将字符串分段
    let phaseList = phaseWrapList(str)
    // 对每个段落内的文字进行换行转换
    phaseList.forEach(item => {
      resultList.push(line(item, length, style))
    })
    // 将所有段落整合成一个字符串
    return resultList.join('')
  }
}

// 以\n,\r作为标志将文本切割成多个段落
function phaseWrapList(str, length, style) {
  let phaseList = []
  let strLenth = str.length
  for (let i = 0, j = 0; i < strLenth; i++) {
    if (str[i] === '\n' || str[i] === '\r' || i === strLenth - 1) {
      phaseList.push(str.substr(j, i))
      j = i
    }
  }
  return phaseList
}
// 对每个段落进行单行文字数限制
function line(str, lineTextLength = 15, style) {
  style = style || 'style="text-indent: 2em; margin: 10px 0;"'
  let newString = ''
  let listLength = Math.ceil(str.length / lineTextLength)
  for (var i = 0; i < listLength; i++) {
    newString += str.substring(i * lineTextLength, (i + 1) * lineTextLength) +
        '<br/>'
  }
  return `<p ${style}>${newString}</p>`
}
复制代码

小结

介绍简单的<br/>换行给外部设定宽度,配合p标签指定单行的个数换行三种换行方式。最终都是通过v-html识别, 本质上是按普通 HTML插入的方式span 的内容将会被替换成为属性值 。前两种方式使用起来比较方便好理解,第三种换行也可以通过第二种方式指定宽度替代。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值