1、创建对应文件及其文件夹
2、创建 emphasize.ts 自定义指令文件
// 匹配常用字符集 列表
// 根据业务需求 配置字符集
const characterList: any = {
"<": "<",
">": ">",
"&": "&",
"¥": "¥",
};
// 处理函数
const nodeChild = (node: any, val: any) => {
const children = Array.from(node.children);
let nodeSplicing: any = "";
// 判断是否为末级节点
if (children.length !== 0) {
// 子节点数据遍历
children.forEach((item: any) => {
// 递归 子节点
nodeChild(item, val);
// nodeSplicing 为当前节点的子级拼接后的字符串
nodeSplicing = nodeSplicing + item.outerHTML;
});
// 进行数据替换 防止标签内部 有需要标记的重复数据 导致标红后 标签外露
// innerHTML 返回标签开始和结束标签之间的HTML
node.innerHTML = node.innerHTML
.replaceAll(nodeSplicing, `*^(_)`)
.toString();
node.innerHTML = node.innerHTML.replaceAll(
val,
`<span style="color:red">${val}</span>`
);
node.innerHTML = node.innerHTML.replaceAll("*^(_)", nodeSplicing);
} else {
// 末级节点 不需要内部标签数据替换
node.innerHTML = node.innerHTML.replaceAll(
val,
`<span style="color:red">${val}</span>`
);
}
};
export default {
mounted(el: any, binding?: any) {
// 进行字符集匹配
const value: string = binding.value;
const valueArr: Array<string> = value.split("");
valueArr.forEach((item: string, index: number) => {
valueArr[index] = characterList[item] || item;
});
// 进行数据匹配 如当前绑定节点 整体并无需要标记内容 不进行DOM 操作
const idx: number = el.innerHTML.indexOf(valueArr.join(""));
if (idx != -1) {
nodeChild(el, valueArr.join(""));
}
},
// binding 数据改变 调用 初始不会调用
// 不建议 因为原始DOM已经被标记
// 可根据业务需要进行 原始数据传参 对原始数据进行操作 然后进行DOM替换即可
// beforeUpdate(el: any, binding?: any) {
// nodeChild(el, binding);
// },
};
3、 index.ts 引入
import emphasize from "./modules/emphasize";
// 统一入口
export default function directive(app: any) {
app.directive("emphasize", emphasize);
}
4、main.ts 中引入 指令入口文件
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
import router from "./router";
import store from "./store";
// 引入指令入口文件
import directive from "@/directive/index";
// 挂载
directive(app);
app.use(store);
app.use(router);
app.mount("#app");
5、使用
<template>
<div v-html="nodeStr" v-emphasize="emphasizeStr" class="nodestr"></div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { RouteLocationRaw, useRouter } from "vue-router";
const router = useRouter(); //路由初始化
const nodeStr = ref<string>(
'<div><div>9846531564路人甲,4564864<br><a herf="18866664444">18866664444,路人乙<br><a herf="18866664444">18866664444,路人丙<br></a></a></div></div>'
);
let emphasizeStr = ref<string>("18866664444");
</script>
6、效果