这是我参与「第五届青训营」伴学笔记创作活动的第 10 天
呜呜呜
好难顶呜呜呜,应该是因为自己基础不够扎实,对于一些dom操作不熟悉,导致开发效率真的低,昨晚一个获取标题标签搞了两三小时,今晚一个attributes也搞我好久
真心bug很搞人心态,眼睛都累了
继上篇md字符串转html | 青训营笔记 - 掘金 (juejin.cn)把strapi项目拿到的md字符串转html之后,渲染在页面上,然后就想获取所有标题标签实现导航
类似掘金的这个
实现思路
最最重要的代码思路
<article class="article-content" v-html="htmls" id="articleContent"></article>
我是先获取element元素,然后,就是这里一句很关键,我试着打印,发现获取到的值是不一样的
这就一直导致我遍历node节点失败,一直报错,很惨
发现这个问题之后,我就利用settimeout,来“等一会”再执行遍历,这下终于就成功了
由于a标签瞄点功能对应的标签需要有name属性,所以用setAttribute把id给复制一份过去(marked插件渲染出来的标签自带id,id是innerText)
这样就获取所有满足tags数组里的标题数组,再利用组件通信把数组传出去,这里建议记得加.value
再利用tags定义目标标题,h1~4,利用findIndex函数获取node节点有没有可以展示的,定义一个数组来存放
组件的调用就基本这样了
因为我把marked渲染html封装在组件中,所以在父组件中调用组件时要监听事件getNavTree 然后动态添加a标签,导航基本就实现了
这里添加的点击事件,是因为有一个顶部tab,但a标签的瞄点功能直接把那个标题顶到最上边,会被挡住的,所以我搜了好久好久,看了好多好多,才发现有这么个解决方法,我真的得回去重新好好学学js了,蠢哭了
重要代码
a.addEventListener("click", (e) => {
window.scrollTo(0, 100);
// console.log(e.target.innerText);
let item = document.getElementById(e.target.innerText);
console.log(item.offsetTop);
setTimeout(() => {
console.log("aaa");
window.scrollTo({
left: 0,
top: item.offsetTop - 100,
behavior: "smooth",
});
}, 200);
});
watch(htmls, () => {
let htmlNode = document.getElementsByTagName("article") || null;
// 浏览器控制台展开console的时候会重新获取值
setTimeout(() => {
let iindex = -1;
for (let i = 0; i < htmlNode[0].children.length; i++) {
iindex = Tags.findIndex((item) => {
return item == htmlNode[0].children[i].tagName;
});
htmlNode[0].children[i].setAttribute("name", htmlNode[0].children[i].id);
if (iindex !== -1) {
navTree.value.push({
tagName: htmlNode[0].children[i].tagName,
id: htmlNode[0].children[i].innerText,
navIndex: iindex + 1,
});
}
}
emits("navigations", navTree.value);
}, 3000);
});