通过pre标签进行json格式化展示,并实现搜索高亮和通过鼠标进行逐个定位的功能

本文介绍了如何使用Vue.js和Element-Plus构建一个功能,实现在JSON内容中搜索关键词并高亮显示,同时处理输入框监听、编辑提示和确认退出。开发者详细展示了HTML结构、JavaScript方法以及相关组件的运用。
摘要由CSDN通过智能技术生成

功能说明

  1. 实现一个对json进行格式化的功能
  2. 添加搜索框,回车进行关键词搜索,并对关键词高亮显示
  3. 搜索到的多个关键词,回车逐一匹配
  4. 监听json框,如果发生了编辑,需要在退出时提示,在得到用户确认的情况下再退出

效果展示

在这里插入图片描述

说明:如上图中,输入“编程”两个字,每回车一下,就定位到匹配到的第二个位置,并将当前匹配到的文字滚动到顶部。

实现步骤

第一步:编写HTML

分别添加一个输入框、一个用于展示json的pre标签、和一个取消按钮

说明:此处的其它功能有省略

<template>
    <div>
        <el-input class="input" v-model="searchValue" @keyup.enter.native="handleEnter" placeholder="输入关键词回车搜索"></el-input>
        
        <pre class="content" id="json-pre" contenteditable="true" v-html="preJsonHtml"></pre>

        <el-button @click="handleCancle">取消</el-button>
    </div>
</template>

第二步:实现JavaScript方法

2.1 定义必要的变量和进行变量监听

<script lang="ts" setup>
import { computed, nextTick, onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ElMessageBox } from 'element-plus';

const route = useRoute()
const router = useRouter()

// 存放获取到的json文件的内容
let jsonData = ref()

// 搜索框内容
let searchValue = ref()

// 用于在pre标签里展示的HTML
let preJsonHtml = ref()

// 表示json是否被修改
let isPreEdit = ref(false)

// 当前搜索匹配到第几个
let matchNum = ref(0)

// 拼接一个获取json文件的地址
const jsonUrl = computed(() => {

    // 这是亚马逊上面部署的一个pdfjs服务,及存放json文件的文件夹拼接地址
    const aws_server = 'http://xxx.s3-website-xxx.amazonaws.com/pdfjs-4.0.379-dist/web/docs/'

    // 从路由中获取到文件名称
    const json_name = route.query.json as string

    // 拼接得到最终的文件地址
    return `${aws_server}${json_name}`
})

// 监听jsonData,修改后需要动态更新文本框里显示的内容
watch(() => jsonData.value, val => {
    preJsonHtml.value = JSON.parse(JSON.stringify(val, null, 4))
})

// 监听搜索框的内容,主要目的是:当搜索框中的内容变化了,需要将matchNum重置为0,开始新输入内容的第一个搜索
watch(() => searchValue.value, val => {
    matchNum.value = 0
})

onMounted(() => {

    // 这里注意,需要使用nexttick,在页面渲染出来以后再做计算
    nextTick(() => {

        // json-pre
        var preTag = document.getElementById('json-pre');
        var originalContent = preTag?.textContent;

        // 添加监听事件
        preTag?.addEventListener('input', function() {

            if (preTag?.textContent !== originalContent) {

                console.log('内容已被修改');

                isPreEdit.value = true // 标记json被修改了
            }
        });
    })

    // 获取json文件,并赋值给jsonData
    fetch(jsonUrl.value).then(res => res.json()).then(r => {
        jsonData.value = JSON.stringify(r, null, 4)
    })
})
</script>

2.2 输入框回车事件

// 输入框回车事件
// 之所以使用这个方法,是因为input输入框在输入一个文字后,需要多次联系重复搜索
const handleEnter = (event) => {

    // 判断下jsonData的类型,需要一个字符串格式
    let result = typeof jsonData.value !== 'string' && JSON.stringify(jsonData.value) || jsonData.value

    // 正则表达式,对输入框中的内容全匹配
    const Reg = new RegExp(searchValue.value, 'g')

    // 获取这种全匹配下,有多少个匹配结果
    // 这一步非常重要,因为需要多次进行搜索和修改样式,所以必须要记录匹配结果
    let matchs = result.match(Reg)

    // 判断:
    // 匹配到结果 且 当前搜索到匹配结果的最后一位时,重新开始搜索第一个
    if((matchs && matchs.length) && matchNum.value + 1 >= matchs.length) {
        matchNum.value = 0
    }
    // 否则,继续向下
    matchNum.value += 1

    // 如果匹配有结果
    if(result) {

        // 定义一个替换方案
        // 将匹配结果替换为一个span标签,id为highLight,颜色为黄色
        let replacement = `<span id="highlight" style="background: yellow;">${searchValue.value}</span>`

        // 调用字符串匹配方法:在后文中有写
        const res = replaceNumMatch(Reg, result, replacement, matchNum.value);

        // preJsonHtml赋值,将它包裹在了一个div中
        preJsonHtml.value = `<div>${JSON.parse(JSON.stringify(res, null, 4))}</div>`

        /**
         * 这里是实现dom结构的滚动
         */
        const div = document.getElementById('json-pre');
        const span = document.getElementById('highlight');

        if (div && span) {
            // 计算滚动位置
            const scrollTo = span.offsetTop - div.offsetTop - 10; // 这里多了一个10px的间距
            
            // 滚动到指定位置

            // 当搜索第一个时,滚动到顶部
            if(matchNum.value === 1) {
                div.scrollTop = 0
                return
            }
            // 其它滚动到指定为止
            div.scrollTop = scrollTo;
        }
    }
}

2.3 正则表达式进行字符串匹配和替换方法

/**
 * 使用正则表达式进行字符串替换的方法
 */
function replaceNumMatch(regexp, str, replacement, i) {

    let count = 0;

    return str.replace(regexp, function(matched) {
        count++;
        if (count === i) {
            return replacement; // 替换第i个匹配字符为指定的字符串
        } else {
            return matched; // 保持其他匹配字符不变
        }
    });
}

2.4 json对话框编辑取消方法

/**
 * 取消方法:
 * 这里的要求是,当json被修改后退出需要提醒
 * 所以这里增加了一个isPreEdit的变量,标记json是否被修改
 */
const handleCancle = () => {

    if(isPreEdit.value) {
        // 如果被修改增加提醒
        ElMessageBox.confirm('内容有修改,是否进行保存?', '提示',
            {
                confirmButtonText: '是',
                cancelButtonText: '否',
                type: 'warning',
                closeOnClickModal: false,
                showClose: false
            }).then(() => {

                // do something 

                // 如可以保存数据等

            }).catch(() => {
                // 否则 跳转到指定路由
                router.push({ path: '/xxx' })
            })
        return
    }

    // 如果没有被修改,则跳转到指定路由
    router.push({ path: '/xxx' })
}

第三步:样式

pre在文字过长时,不换行。此处的目的是为了让长段的pre换行

<style lang="scss" scoped>

// 让pre里的文字自动换行
pre {
    white-space: pre-wrap;
    white-space: -moz-pre-wrap;
    white-space: -pre-wrap;
    white-space: -o-pre-wrap;
    word-wrap: break-word;
}
</style>
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值