vue项目中 一行文本 文字 根据关键字 改变颜色 改变展示颜色

本文介绍如何在Vue项目中使用v-html结合计算属性实现列表项关键字的动态高亮显示,通过具体代码示例展示了如何将指定词汇变更为带有颜色标记的HTML格式。

在这里插入图片描述

  • 搜索农业 农业颜色变为蓝色
  • 代码 v-html=“item.title”
<el-form-item label="">
     <el-radio-group  v-model="form.secondRadioID">
              <el-row  v-for="item in disposeRadioList" :key="item.value">
                <el-radio :label="item.code"><span v-html="item.title"></span></el-radio>
              </el-row>
            </el-radio-group>
          </el-form-item>
  • 计算属性中对原有的数据进行更改为html的
computed:{
    disposeRadioList() {
      let tworadioList = JSON.parse(JSON.stringify(this.radioList))
      tworadioList.forEach(e=>{
        e.title = e.title.replace(/-/g, ' / ') // 吧- 替换为 /
        e.title = e.title.replace(this.value, `<font color='#409eff'>${this.value}</font>`)
        return e   // 吧对应的关键字 替换为 `<font color='#409eff'>${this.value}</font>`
              }) 
      return tworadioList
    },
  },
  • v-for=“item in disposeRadioList” v-html 使用即可

有更好的希望下面回复 谢谢

可以的大家点点关注-总结不易谢谢大家-也可以留言需要哪类的我也可以尝试

<think>我们面对的需求是:在uni-app微信小程序中,提取字符串中《》内的内容,并将其高亮显示(改变颜色),然后重新拼接回原字符串。 思路: 1. 我们需要识别字符串中的《》符号,并提取其中的内容。 2. 将提取的内容用特定的样式(比如红色)包裹。 3. 将处理后的内容重新拼接回原字符串,同时保持非《》内的内容不变。 但是,小程序中不能直接使用HTML字符串(因为小程序使用自己的标签体系,且不能直接解析HTML字符串),所以我们需要用其他方法。 参考引用中提供的方法: 引用[1]和[2]展示了在uni-app中如何实现关键字高亮。他们的做法是: - 使用字符串的replace方法,将关键字替换成用<view>标签包裹并设置样式的字符串。 - 然后在页面上使用rich-text组件或者直接使用v-html(注意:uni-app中v-html在h5端支持,但在小程序端不支持,所以需要使用rich-text)来渲染。 但是,我们的需求不是关键字高亮,而是将《》内的内容高亮。因此,我们需要用正则表达式匹配《》及其中的内容,然后替换成带样式的文本。 步骤: 1. 定义一个正则表达式,用于匹配《》以及其中的内容。例如:/《([^》]+)》/g 解释:匹配以《开头,以》结尾,中间内容为至少一个非》字符的字符串,并且我们使用捕获组来获取《》内的内容。 2. 使用replace方法,将匹配到的部分替换成我们需要的格式。注意,我们不能直接使用HTML标签,所以我们可以使用类似引用[2]中的方法,但注意小程序端不能使用<span>,而应该使用<view>或者<text>,并且使用内联样式。 3. 但是,由于小程序中不能直接渲染HTML字符串,我们需要使用rich-text组件来渲染,或者将字符串拆分成数组,然后使用数组渲染(每个部分用<text>包裹,并设置样式)。 这里我们采用第二种方法(数组渲染): - 将原字符串按照正则表达式拆分成数组,数组中的元素可能是普通字符串,也可能是需要高亮的字符串(即《》内的内容)。 - 然后遍历数组,对于需要高亮的部分,用<text>标签包裹并设置样式。 具体步骤: - 使用split方法结合正则表达式来分割字符串,但是split不能同时保留匹配项。因此,我们可以使用正则表达式的exec或matchAll来获取所有匹配项的位置,然后手动分割。或者使用一个更简单的方法:使用replace方法并传入一个函数,在函数中记录每个部分。 但是,我们也可以使用一个更直接的方法:使用正则表达式匹配所有部分(包括非匹配部分),然后生成一个数组。 例如:使用正则表达式:/(《[^》]+》)/g 来分割字符串,这样可以将字符串分割成普通文本和《》包裹的文本交替的数组。 但是,这样分割后,我们还需要知道哪些部分是匹配的(即《》内的),哪些不是。 我们可以这样: let parts = str.split(/(《[^》]+》)/g); 这样,数组parts中,奇数索引(0,2,4...)是普通文本,奇数索引(1,3,5...)是《》包裹的文本(包括《》符号)。但我们希望只高亮《》内的内容(不包括《》符号),所以我们需要进一步处理。 进: - 我们使用正则表达式:/(《([^》]+)》)/g 来捕获整个匹配项(包括《》)和内部内容(不包括《》)。但是split不能使用捕获组来分割。 另一种方法:使用match方法,但是要匹配所有非匹配部分和匹配部分,我们可以写一个正则表达式:/(?:[^《]+)|(?:《[^》]+》)/g,这样可以将字符串拆分成多个部分。 示例代码: let str = "这是一段《示例》文本,用于《测试》"; let reg = /(?:[^《]+)|(?:《[^》]+》)/g; let parts = str.match(reg); 然后遍历parts数组,如果数组中的元素以《开头且以》结尾,则说明是需要高亮的部分(注意,我们匹配的时候已经保证了《》内的内容不含》),那么我们就提取其中的内容(去掉《》),然后用<text>包裹并设置样式。同时,我们也要保留原字符串(因为可能包含《》符号,但我们要高亮的是内容,所以要去掉《》符号?) 但是,需求是:高亮显示《》内的文字,注意是文字,所以《》符号本身不需要高亮。所以我们需要将《》符号作为普通文本,而中间的内容作为高亮文本。 因此,我们需要更精确地分割: - 我们可以将字符串拆分成:普通文本、《、高亮内容、》、普通文本。这样太复杂。 另一种思路:使用正则表达式匹配《》内的内容(不包括《》符号),然后记录每个匹配项的起始位置和结束位置,然后分割字符串为多个片段,每个片段标记是否为高亮。 这里,我们采用一个更简单的方法:使用replace方法,但是不是替换成字符串,而是替换成一个对象,然后生成一个数组。 步骤: let segments = []; // 用于存放分割后的片段 let lastIndex = 0; let match; let reg = /《([^》]+)》/g; while ((match = reg.exec(str)) !== null) { // 匹配前的普通文本 if (match.index > lastIndex) { segments.push({ text: str.substring(lastIndex, match.index), isHighlight: false }); } // 匹配到的高亮内容(注意:match[1]是捕获组,即括号内的内容) segments.push({ text: match[1], isHighlight: true }); lastIndex = reg.lastIndex; // 更新lastIndex到匹配结束的位置 } // 最后还有一段普通文本 if (lastIndex < str.length) { segments.push({ text: str.substring(lastIndex), isHighlight: false }); } 这样,我们就得到了一个数组segments,每个元素是一个对象,包含text和isHighlight属性。 然后在模板中,我们可以遍历这个数组: <view> <template v-for="(segment, index) in segments"> <text v-if="segment.isHighlight" :key="index" style="color: red;">{{ segment.text }}</text> <text v-else :key="index">{{ segment.text }}</text> </template> </view> 注意:这里使用<text>标签包裹,因为<text>在小程序中可以嵌套,并且可以设置样式。 但是,这里有一个问题:原字符串中的《》符号去哪里了? - 在匹配时,我们只提取了《》内的内容(即match[1]),而《》符号本身被我们跳过了(因为我们在匹配前和匹配后分别截取)。实际上,在匹配时,正则表达式匹配的是整个《...》,所以我们在匹配前的普通文本中包含了《之前的文本,匹配后我们添加了高亮内容(即《》内的文字),然后跳过了》符号。但是,在匹配后的普通文本中,我们并没有包含》符号后面的内容?不对,我们使用的是reg.exec,它会将整个匹配项作为match[0],而捕获组是match[1]。然后我们更新lastIndex到整个匹配项结束的位置(即》之后的位置)。所以,在匹配后的普通文本中,我们是从》之后开始截取的,所以《》符号本身没有被包含在任何片段中。 因此,我们需要调整:在匹配时,我们应该将《和》作为普通文本的一部分,而只将中间的内容作为高亮。所以我们需要在普通文本中包含《》符号,但这样我们就无法区分了。 修正则表达式:我们匹配《》时,需要分别匹配《、中间内容、》,然后分别处理。 但是这样正则表达式会变得复杂,而且需要多个捕获组。 另一种思路:在生成segments数组时,我们不仅要记录高亮内容,还要记录《和》符号。但是这样会使得数组元素过多。 我们可以这样: - 在匹配前,将《之前的文本作为普通文本。 - 然后匹配到《,但是我们无法用同一个正则匹配到《和》之间的内容,所以需要分步。 重新设计: let segments = []; let lastIndex = 0; let reg = /《([^》]+)》/g; let match; while ((match = reg.exec(str)) !== null) { // 匹配前的普通文本(包括《符号前面的部分) if (match.index > lastIndex) { segments.push({ text: str.substring(lastIndex, match.index), highlight: false }); } // 匹配到整个《...》,然后我们将其拆分成三部分:'《'、中间内容、'》' // 但是,我们实际上已经通过捕获组得到了中间内容,所以我们手动添加: // 先添加一个普通文本《(注意:这个《符号在匹配项的开始位置,即match.index处) segments.push({ text: '《', highlight: false }); // 再添加中间内容(高亮) segments.push({ text: match[1], highlight: true }); // 再添加普通文本》(注意:》在匹配项的结束位置-1处,因为整个匹配项的长度是match[0].length,结束位置是reg.lastIndex,所以》的位置是reg.lastIndex-1,但是我们直接添加字符串即可) segments.push({ text: '》', highlight: false }); lastIndex = reg.lastIndex; } if (lastIndex < str.length) { segments.push({ text: str.substring(lastIndex), highlight: false }); } 但是,这样处理会使得数组中有很多小片段,可能影响性能(但对于一般字符串来说,片段不会太多)。 另外,注意正则表达式匹配的整个字符串是match[0](例如“《示例》”),而捕获组是match[1](例如“示例”)。然后我们分别将《、示例、》作为三个片段。 这样,我们在模板中就可以分别渲染了。 但是,有没有更简单的方法?我们可以不拆分《和》,只将中间的内容高亮,而《和》作为普通文本。这样我们在上面的第一种方法中,将《和》保留在普通文本中,而只将中间的内容作为高亮片段。那么,我们就需要将普通文本中的《和》与高亮内容相邻的部分拆开。 我们修第一种方法:在生成普通文本时,如果普通文本中包含《,那么我们需要将其拆分成《之前的部分、《、然后等待后面的高亮内容?这样不行,因为普通文本中可能包含多个《,而且我们无法预知后面的内容。 因此,我们采用第二种方法,即显式地将《、高亮内容、》作为三个片段。 代码实现: 在数据中,我们有一个字符串,然后我们写一个方法,将这个字符串转换成segments数组。 例如: processString(str) { let segments = []; let lastIndex = 0; // 正则表达式匹配《...》,注意:这里我们使用非贪婪匹配?但是我们的正则[^》]已经保证了不会跨越多对《》 let reg = /《([^》]+)》/g; let match; while ((match = reg.exec(str)) !== null) { // 匹配前的普通文本(从lastIndex到match.index) if (match.index > lastIndex) { segments.push({ text: str.substring(lastIndex, match.index), highlight: false }); } // 将《、中间内容、》分别加入 segments.push({ text: '《', highlight: false }); segments.push({ text: match[1], highlight: true }); segments.push({ text: '》', highlight: false }); // 更新lastIndex lastIndex = reg.lastIndex; } // 最后一段普通文本 if (lastIndex < str.length) { segments.push({ text: str.substring(lastIndex, str.length), highlight: false }); } return segments; } 然后在data中,我们可以将原始字符串处理成segments,并绑定到模板中。 注意:如果字符串中有多个《》,这个正则表达式会依次匹配,因为使用了g标志。 但是,如果字符串中有单个《没有闭合,那么正则表达式会匹配失败,所以不会处理,这些《会留在普通文本中。 在模板中: <view> <template v-for="(segment, index) in segments"> <text :key="index" v-if="segment.highlight" style="color: red;">{{ segment.text }}</text> <text :key="index" v-else>{{ segment.text }}</text> </template> </view> 注意:这里使用两个<text>标签,分别根据highlight属性渲染不同的样式。 但是,这样可能会产生多个<text>标签,如果字符串很长,可能会影响性能。不过一般情况下,这种高亮不会太多。 另外,我们也可以使用一个<text>标签包裹所有内容,然后在里面用条件判断,但是小程序中不能在<text>标签内使用v-for和v-if,所以只能这样。 或者,我们可以使用rich-text,但是rich-text需要nodes数组,我们可以将segments数组转换成nodes数组。 例如: nodes: [ { type: 'text', text: '普通文本', style: '' }, { type: 'text', text: '高亮文本', style: 'color: red;' } ] 但是,rich-text的nodes结构比较复杂,而且可能涉及标签嵌套。我们可以这样生成: let nodes = []; segments.forEach(segment => { nodes.push({ type: 'text', text: segment.text, style: segment.highlight ? 'color: red;' : '' }); }); 然后在模板中使用: <rich-text :nodes="nodes"></rich-text> 但是,rich-text会将这些文本节点合并成一个连续的文本,但是注意,rich-text中的文本节点是连续的,不会换行。所以用rich-text也可以。 两种方式都可以,这里我们选择使用rich-text,因为它只需要一个标签,可能性能更好。 但是,rich-text在微信小程序中支持,在uni-app中也是支持的。 因此,我们可以这样: data() { return { str: "这是一段《示例》文本,用于《测试》", nodes: [] // 由str处理得到的nodes数组 } }, methods: { processString(str) { // 同上,生成segments数组 // 然后转换成nodes let segments = []; // 通过上面的函数得到 // ...省略生成segments的代码 let nodes = segments.map(segment => { return { type: 'text', text: segment.text, style: segment.highlight ? 'color: red;' : '' }; }); return nodes; } }, created() { this.nodes = this.processString(this.str); } 但是,注意:如果字符串中有换行符,rich-text会保留换行吗?使用text节点会保留换行,因为text节点会原样输出。 另外,如果字符串中有特殊字符,比如<、>,rich-text会将其解析为标签吗?不会,因为我们使用的是text类型节点,所以会原样输出。 所以,使用rich-text是安全的。 但是,我们也可以使用第一种方法(多个<text>标签),这里我们选择使用rich-text。 最后,我们还需要考虑性能:如果字符串很长,并且有很多《》,那么处理起来会不会卡顿?一般来说,字符串不会太长,而且正则表达式是高效的。 总结步骤: 1. 定义处理字符串的函数,将字符串拆分成片段(普通文本和高亮文本,以及《》符号作为普通文本)。 2. 将片段数组转换成rich-text需要的nodes数组,其中高亮片段设置样式(红色)。 3. 在模板中使用rich-text组件渲染。 但是,注意:我们这里将《和》符号作为普通文本,而中间内容作为高亮。这样在显示时,《》符号是普通颜色,中间内容是红色。 如果需求是《》符号也要高亮,那么我们可以将《、中间内容、》作为一个整体高亮。但是需求是“《》中的文字”,所以应该只是文字高亮。 因此,我们按照上述方法实现。 代码示例: 在vue文件中: <template> <view> <rich-text :nodes="nodes"></rich-text> </view> </template> <script> export default { data() { return { str: "这是一段《示例》文本,用于《测试》", nodes: [] } }, created() { this.nodes = this.processString(this.str); }, methods: { processString(str) { let segments = []; let lastIndex = 0; let reg = /《([^》]+)》/g; let match; while ((match = reg.exec(str)) !== null) { // 匹配前的普通文本 if (match.index > lastIndex) { segments.push({ text: str.substring(lastIndex, match.index), highlight: false }); } // 将《、中间内容、》分别加入 segments.push({ text: '《', highlight: false }); segments.push({ text: match[1], highlight: true }); segments.push({ text: '》', highlight: false }); lastIndex = reg.lastIndex; } if (lastIndex < str.length) { segments.push({ text: str.substring(lastIndex), highlight: false }); } // 转换成nodes return segments.map(segment => { return { type: 'text', text: segment.text, style: segment.highlight ? 'color: red;' : '' }; }); } } } </script> 注意:如果字符串中有多个《》,例如“《a》《b》”,那么正则表达式会匹配两次,第一次匹配《a》,第二次匹配《b》。 但是,如果字符串中有嵌套的《》,例如“《a《b》c》”,那么正则表达式会匹配到内层的《b》,然后外层的《a》和c》可能无法正确匹配。因为正则表达式[^》]会匹配到b后面的》,所以匹配到的是《b》,而《a《b会被当作普通文本?然后后面的c》又会匹配失败。 所以,这个正则表达式不支持嵌套。但是通常,书名号不会嵌套。如果需求中可能有嵌套,那么我们需要更复杂的处理(比如使用栈),但这里按照需求,我们只处理一层。 因此,我们按照上述代码实现。 相关问题: 1. 如果字符串中没有《》,会怎样? 正则匹配不到,所以segments数组只有一个元素(整个字符串),普通文本。 2. 如果字符串中有单个《没有闭合? 正则匹配不到,所以会保留在普通文本中。 3. 如果字符串中有》出现在《前面? 正则匹配会从第一个《开始,直到遇到第一个》就结束,所以后面的》会留在普通文本中。 所以,这个正则表达式在正常情况下(成对出现)是有效的。 最后,我们输出相关问题。</think>在uni-app微信小程序中,实现提取字符串中《》内的内容并高亮显示,可以通过以下步骤实现: ### 解决方案 #### 1. 核心思路 - **正则匹配**:使用正则表达式 `《([^》]+)》` 匹配《》及其内部内容 - **字符串分割**:将原字符串拆分为普通文本和高亮文本片段 - **动态渲染**:通过`<text>`组件分段渲染,对高亮内容添加样式 #### 2. 完整代码实现 ```vue <template> <view class="container"> <!-- 渲染处理后的文本 --> <text class="content"> <template v-for="(item, index) in processedText" :key="index"> <text v-if="item.highlight" class="highlight">{{ item.text }}</text> <text v-else>{{ item.text }}</text> </template> </text> </view> </template> <script> export default { data() { return { originalText: "这是一段《示例文本》,需要高亮《关键内容》", processedText: [] // 处理后的文本数组 }; }, mounted() { this.processText(); }, methods: { processText() { const reg = /《([^》]+)》/g; // 匹配《》及内部内容 let lastIndex = 0; const segments = []; let match; // 循环匹配所有《》内容 while ((match = reg.exec(this.originalText)) !== null) { // 添加《之前的普通文本 if (match.index > lastIndex) { segments.push({ text: this.originalText.substring(lastIndex, match.index), highlight: false }); } // 添加高亮内容(去掉《》符号) segments.push({ text: match[1], // match[1]表示括号捕获的内容 highlight: true }); lastIndex = reg.lastIndex; // 更新最后匹配位置 } // 添加剩余文本 if (lastIndex < this.originalText.length) { segments.push({ text: this.originalText.substring(lastIndex), highlight: false }); } this.processedText = segments; } } }; </script> <style> .highlight { color: #ff0000; /* 红色高亮 */ font-weight: bold; /* 加粗 */ } .content { line-height: 1.5; } </style> ``` #### 3. 关键代码解析 1. **正则表达式**: ```js /《([^》]+)》/g ``` - `《`:匹配左书名号 - `([^》]+)`:捕获组,匹配除`》`外的任意字符(至少一个) - `》`:匹配右书名号 - `g`:全局匹配 2. **文本分割逻辑**: - 遍历正则匹配结果,将字符串分为三部分: - 普通文本(匹配前的字符) - 高亮内容(《》内的字符) - 剩余文本(最后一次匹配后的字符) - 为每个片段标记`highlight`属性 3. **模板渲染**: ```vue <text v-if="item.highlight" class="highlight">{{ item.text }}</text> <text v-else>{{ item.text }}</text> ``` - 动态切换样式类,实现条件渲染 ### 技术要点说明 1. **正则优化**: - 使用`[^》]+`确保匹配到最近的`》`,避免跨越多段内容 - 捕获组`()`精确提取《》内部文本 2. **性能考虑**: - 避免在模板中使用复杂计算,提前在`processText`中处理数据 - 小程序中`<text>`组件支持嵌套,但需保持结构扁平 3. **样式扩展**: - 修`.highlight`类的CSS可自定义颜色/字体 - 支持添加背景色等更多样式: ```css .highlight { background-color: #fff9d7; padding: 0 4rpx; border-radius: 4rpx; } ``` ### 相关问题 1. **如何实现多层级嵌套《》的高亮?** 需使用递归或栈结构解析嵌套标签,可通过`while`循环匹配内层《》[^1] 2. **正则表达式无法匹配时如何处理?** 添加兜底逻辑:当无匹配时,直接返回整个字符串为普通文本 3. **是否支持其他符号如【】?** 修正则即可,例如:`/【([^】]+)】/g` 4. **性能优化建议** - 长文本使用虚拟滚动 - 缓存处理结果避免重复计算 - 复杂场景考虑WebWorker后台处理[^2] [^1]: 嵌套解析可通过维护匹配栈实现,参考《编译原理》词法分析章节 [^2]: uni-app支持WebWorker,详见官方文档并发处理章节
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值