《Vue如何渲染文本》

背景

为适应业务需求,规则说明的固定内容转换为由接口动态获取,这就要求前端对规则说明的渲染改变技术方案~其中使用v-html渲染文本,需要注意的是顺序标签的渲染~

技术点

  • Vue渲染文本的方式
  • style属性scoped相关
  • a标签点击事件

技术点解析

Vue渲染文本的方式

  • v-text
  • {{}}
  • v-html

v-text

  • 将元素当成纯文本输出
  • 相对比较安全
  • 可简写为{{}},支持逻辑运算
  • 且不会出现{{}}一闪而过之后消失,重新渲染元素的体验,但是使用起来不如{{}}方便
 <p v-text="message"></p>

{{}}

  • 将元素当成纯文本输出
  • 当页面渲染过大过慢时,会出现{{}}一闪而过之后消失重新渲染元素的体验
 <p> {{}} </p>

v-html

  • 将元素当成HTML标签解析后输出
  • 存在安全性问题
 <p v-html="html"></p>

style属性scoped相关

定义

  • HTML5中的新属性
  • 数据类型为布尔类型

作用

  • 实现组件的私有化
  • 只作用于当前组件的元素
  • 组件之间互不污染,实现模块化

原理

  • css带属性选择器
  • scoped会在DOM结构及css样式上加上唯一性的标记【data-v-something】属性
<style scoped>
.a >>> .b { /* ... */ }
</style>

将上述代码编译以后如下所示:

.a[data-v-f3f3eg9] .b { /* ... */ }

穿透

任何事物都有两面性,scoped也不例外,其使用起来虽然方便,但也会存在局限性。当需要修改公共组件时,便需要了解穿透的解决方案-深度作用选择器

  • >>>
  • /deep/  (sass或less) 如果使用/deep/报错或不生效,使用::v-deep
  • 使用两个style标签,一个带scoped,一个不带scoped,用以达到修改第三方组件的目的

解决方案

  • 使用v-html渲染接口获取的规则说明
  • 去掉scoped修饰
  • 在添加scoped属性的前提下,使用深度选择器进行样式穿透,成功渲染顺序标签

代码

方案一:v-html +  去掉scoped修饰:这个方法不建议使用,会改变布局,导致组件之间样式冲突

<template>
    <div class="rule-main">
        <div v-html="integralRule"></div>
    </div>
</template>

<script>

export default {
  data() {
    return {
      integralRule: ''
    }
  },
  mounted() {
    this.getRule()
  },
  methods: {
    async getRule() {
      const res = {
        "data": "\n <ol><li>suger and solt</li></ol>"
      }
      this.integralRule = res.data
    }
  }
}
</script>

<style lang="less">
.rule-main {
    min-height: 100vh;
    padding: 10rpx 24rpx 30rpx 48rpx;
    color: #333;
    background: #f6f6f6;
}
ol, li {
  list-style: decimal;
}

</style>

方案二:v-html + scoped修饰 + 深度选择器

<template>
    <div class="rule-main">
        <div v-html="integralRule"></div>
    </div>
</template>


<style lang="less" scoped>
.rule-main {
    min-height: 100vh;
    padding: 10rpx 24rpx 30rpx 48rpx;
    color: #333;
    background: #f6f6f6;
}
/deep/ li {
  list-style: decimal;
}
</style>

方案三:定义两个style标签,一个含有scoped属性,一个不含有scoped属性,将需要穿透的属性放在不含有scoped属性的style标签中

<style lang="less">
.hight-color {
  color: #FF5E29;
}
.font-weight {
  font-weight: 500;
}

</style>

<style lang="less" scoped>
.in-box {
  margin: .16rem .12rem 0;
  padding-bottom: .16rem;
}

方案四:通过给各个组件的第一层标签设置唯一class或者id,使用scss,然后去掉scoped。

注意:需要严格控制class 和 id 的 根命名。保证其唯一性。

UI

扩展

<a>标签点击事件 

v-html原理

v-html是vue中用来将string形式的html内容按普通HTML插入的命令 - 并且插入的内容不会作为 Vue 模板进行编译 ,继而相关标签的事件则会导致无效

解决方案(使用事件代理解决v-html点击事件无效

<div @click="eventGet" class="mid-rule" v-html="midRule"></div>
midRule() {
   const replaceRuleFCopy = this.activityInfo?.ruleFCopy?.replace('$awardSendTime$', `<span class="hight-color font-weight">${this.activityInfo.awardSendTime || ''}</span>`)
        .replace('$goodsSpan$', `<span class="hight-color font-weight">${this.activityInfo.goodsSpan || ''}</span>`)
        .replace('$seeGoodsDetail$', `<a style="text-decoration: underline;" @click="jumpGoodsLandingPage">${this.activityInfo.seeGoodsDetail || '查看活动商品>'}</a>`)
   return replaceRuleFCopy
}
  methods: {
    eventGet(e) {
      // 在判断事件目标节点的时候,考虑到兼容性应该统一转换成大写或小写进行判断
      if (e.target.localName.toLowerCase() === 'a') {
        // 通过判端目标节点,在这里对其进行操作
        this.jumpGoodsLandingPage() // 调用点击事件方法
      }
    },
    jumpGoodsLandingPage() {
      const getQueryString = () => new URLSearchParams(window.location.search).toString()
      const urlSearchParams = getQueryString()
      const pageUrl = `${this.activityInfo?.packageGoodsLandingPageUrl}?${urlSearchParams}`
      window.location.href = pageUrl
    }
  }

UI

 扩展

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值