Прошло почти много времени с тех пор, как я обновлял статью.Из-за работы и жизни я, кажется, потерял вид, каким был в колледже, и стал ленивым. Когда я только вошел в общество, мне все еще нужно продолжать подталкивать себя. Есть много вещей, которым нужно научиться. Регулярное письмо - большое улучшение для меня. В процессе написания вы все еще думаете, и вам захочется сделать эту вещь лучше и показать ее другим. Это не будет похоже на то, чтобы написать бизнес, дополнив функции и требования и редко оптимизируя резюме с нуля. Также из-за недавнего спроса я видел очень мало информации в Интернете, поэтому у меня есть эта статья.
предисловие
С появлением передней части все больше и больше людей присоединялись к этой большой семье, а рамы и колеса ослепляли и расцветали повсюду. Это дает много преимуществ: уменьшает стоимость и время разработки, может быть, кто-то уже создал функцию, вам нужно только установить ее с помощью npm, и вы можете использовать ее, что очень быстро. Но нельзя недооценивать и недостатки: с увеличением проекта становится все больше и больше колес, которыми трудно управлять, и объем проекта также изменился с первоначальных 10 м > 20 м > 100 м... Это ужасная вещь вещь. С другой стороны, вы часто используете колеса, написанные другими, и редко придумываете и реализуете сами.Со временем ваши способности кодирования естественным образом снижаются. Поэтому я часто ограничиваюсь предложением: Вы можете использовать его как можно больше, частота использования колеса в разработке крайне низкая, а то и всего один раз, поэтому оно абсолютно не используется.
Всего одно требование: написание и презентация статьи в markdow. Функция почти аналогична Nuggets.Сегодня я представляю вам первый раздел, как создать каталог уценки.
1. Настройки точки привязки
Заголовок, состоящий из #, ##, ## в уценке, станет тегом h после преобразования и отображения на веб-странице с помощью таких инструментов, как помеченные, поэтому, когда вы получите страницу сведений о статье, вы можете извлечь все теги каталога из это, а именно h1, h2 ,h3....
const toc: string[] = data.content.match(/<[hH][1-6]>.*?<\/[hH][1-6]>/g) // 通过正则的方式
Настройки якоря можно сделать после получения этих заголовков. Есть много практик по поводу точки привязки в H5, мы будем использовать следующую практику:
①: Установить якорную ссылку<a href="#miao">去找喵星人</a>(Примечание: перед значением атрибута href должен стоять #)
②: Установите точку привязки в нужном месте на странице.<h1 id="miao"></h1>(Примечание: атрибут id должен быть записан в теге a, а значение атрибута должно быть таким же, как значение атрибута href в ①, без #)
После сопоставления всех тегов h в статье через обычный добавляем атрибут id в цикле и оборачиваем div
tocs.forEach((item: string, index: number) => {
let _toc = `<div name='toc-title' id='${index}'>${item} </div>`
data.content = data.content.replace(item, _toc)
})
Во-вторых, каталог преобразования
Мы видим, что каталоги Статьи обычно присутствуют в UL> Li> Форма метки, поэтому как получить статьи все теги H в UL LI или такую метку?
Из консоли видно, что h заголовки статей были извлечены, и следующее, что нужно сделать, это преобразовать эти теги h в форму ul>li. Прежде всего, есть структура данных, которую следует знать — стек. Короче говоря, это формат данных «первым пришел — последним вышел». Например, есть корзина, и мы кладем в нее яйца одно за другим. Вдруг однажды дно корзины вот-вот протечет. защитить яйца, мы должны взять яйца из корзины. , яйца вынимаются по порядку из самого внешнего слоя корзины, что является типичным примером «первым пришел — последним вышел». То же самое верно и для преобразования нашего тега h в ul>li.
export default function toToc(data: string[]) {
let levelStack: string[] = []
let result:string = ''
const addStartUL = () => { result += '<ul class="catalog-list">'; }
const addEndUL = () => { result += '</ul>\n'; }
const addLI = (index: number, itemText: string) => { result += '<li><a name="link" class="toc-link'+'-#'+ index + '" href="#' + index + '">' + itemText + "</a></li>\n"; }
data.forEach(function (item: any, index: number) {
let itemText: string = item.replace(/<[^>]+>/g, '') // 匹配h标签的文字
let itemLabel: string = item.match(/<\w+?>/)[0] // 匹配h?标签<h?>
let levelIndex: number = levelStack.indexOf(itemLabel) // 判断数组里有无<h?>
// 没有找到相应<h?>标签,则将新增ul、li
if (levelIndex === -1) {
levelStack.unshift(itemLabel)
addStartUL()
addLI(index, itemText)
}
// 找到了相应<h?>标签,并且在栈顶的位置则直接将li放在此ul下
else if (levelIndex === 0) {
addLI(index, itemText)
}
// 找到了相应<h?>标签,但是不在栈顶位置,需要将之前的所有<h?>出栈并且打上闭合标签,最后新增li
else {
while (levelIndex--) {
levelStack.shift()
addEndUL()
}
addLI(index, itemText)
}
})
// 如果栈中还有<h?>,全部出栈打上闭合标签
while (levelStack.length) {
levelStack.shift()
addEndUL()
}
return result
}
До сих пор все теги h были преобразованы в форму ui> li, и был добавлен якорь ссылки a, чтобы он соответствовал идентификатору тега h в предыдущей статье, и в статье реализован каталог и переход по щелчку.
3. Оптимизация каталога
На данный момент наша цель практически наполовину достигнута. Как преданные поклонники Nuggets, мы, конечно же, решили использовать CSS для оптимизации. CSS всегда кажется домашним заданием, поэтому я не буду здесь вдаваться в подробности, это примерно так
.catalog-list {
font-weight: 600;
padding-left: 10px;
position: relative;
font-size: 15px;
&:first-child::before {
content: "";
position: absolute;
top: 10px;
left: 12px;
bottom: 0;
width: 2px;
background-color: #ebedef;
opacity: .8;
}
}
& > li > a {
position: relative;
padding-left: 16px;
line-height: 20px;
@include catalogRound(0, 6px);
}
ul, li {
padding: 0;
margin: 0;
list-style: none;
}
ul > li > a {
font-size: 14px;
color: #333333;
padding-left: 36px;
font-weight: 500;
position: relative;
@include catalogRound(20px, 5px);
}
ul > ul > li > a {
line-height: 20px;
font-size: 14px;
color: #333333;
padding-left: 50px;
font-weight: normal;
@include catalogRound;
}
a {
color: #000;
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 4px 0 4px 12px;
&:hover {
background-color: #ebedef;
}
}
}
После модификации эффект каталога выглядит следующим образом, который кажется чем-то похожим. По крайней мере, не слишком уродливо. Далее в основном рассказывается, как реализовать связь между статьями и каталогами и связь между каталогами и статьями. Это важная особенность
4. Динамическая ассоциация
1, к каталогу статьи
Как директория управляет позицией отображения статьи, можно подумать 🤔: точка привязки реализуется тегом а, но большое количество кликов тега а не может быть захвачено, особенно мы используем преобразованный тег а , но точка привязки находится путем наблюдения. Значение хеша увеличит позицию привязки в URL-адресе, поэтому я придумал решение для захвата тега, на который нажали, прослушивая изменение URL-адреса. Так что следим за маршрутом
@Watch('$route')
private routechange(val: any) {
const data = document.getElementsByClassName(`toc-link-${val.hash}`)[0] as Element
this.linkLists.forEach((list:Element) => {
data == list ? list.classList.add('active') : list.classList.remove('active')
})
}
На этом этапе мы можем щелкнуть каталог, чтобы перейти к месту ответа на статью.Вот небольшой совет. Так как страница может иметь навигационное позиционирование навигации, часто статьи, по которым мы переходим, будут закрыты панелью навигации, поэтому нам нужно ее улучшить. характеристики.
2. Статья в каталог
Каталог к статье завершен, как прокрутить статью, чтобы реализовать автоматический переход в каталог? Мог бы также сначала иметь четкое представление:
- 1. Следите за расстоянием прокрутки браузера
- 2. Рассчитайте высоту каждого заголовка от верхней части браузера
- 3. Сопоставьте расстояние прокрутки между двумя заголовками, чтобы добиться автоматического перехода по каталогу.
Специфические этапы реализации:
Слушайте прокрутку мыши во время жизненного цикла mount()
window.addEventListener('scroll', this.handleScroll, true)
Получить все заголовки статей и оглавление
this.$nextTick(async () => {
await this.getTitleHeight()
await this.getCataloglist()
})
// 获取每个文章标题的距顶部的高度
private async getTitleHeight() {
let titlelist = Array.prototype.slice.call((this.$refs.article as Element).getElementsByClassName('toc-title'))
titlelist.forEach((item,index) => {
this.listHeight.push(item.offsetTop)
})
// 滚动的距离无法取到最后一个,因此在数组最后加上上一个两倍达到效果
this.listHeight.push(2 * (titlelist[titlelist.length-1].offsetTop))
}
// 获取目录的所有ul、a标签
private async getCataloglist() {
let catalogList = (this.$refs.catalog as Element).getElementsByClassName('catalog-list')
this.linkLists = document.getElementsByName('link')
this.target = Array.prototype.slice.call(catalogList)
}
Отслеживание прокрутки статьи в функции handleScroll
private handleScroll() {
const scrollY = window.pageYOffset
this.fixed = scrollY > 230 ? true : false
for (let i = 0; i < this.listHeight.length-1; i++) {
let h1: number = this.listHeight[i]
let h2: number = this.listHeight[i + 1]
if (scrollY >= h1 && scrollY <= h2) {
const data: Element = document.getElementsByClassName(`toc-link-#${i}`)[0] as Element // 获取文章滚动到目录的目标元素
this.linkLists.forEach((list: Element) => {
let top: number = 0
top = i > 7 ? -28 * (i-7) : 0
this.target[0].style.marginTop = `${top}px`
data == list ? list.classList.add('active') : list.classList.remove('active') // 其他移除active
})
}
}
}
Объяснение кода:
this.fixed = scrollY > 230 ? true : false
Оглавление не прокручивается вместе со страницей, поэтому вам нужно добавить фиксированный атрибут, чтобы сделать его фиксированным в правой части статьи, а 230 — это высота поля перед оглавлением. Когда мышь прокручивается до 230 пикселей, каталог фиксируется и приводится в действие.
let top: number = 0
top = i > 7 ? -28 * (i-7) : 0
this.target[0].style.marginTop = `${top}px`
Хотя каталог не следует за прокруткой страницы, но слишком длинный каталог может не отображаться, необходимо установить динамический каталог атрибута margin-top,
top = i > 7 ?-28 * (i-7) : 0 // начать прокрутку вверх с пункта 7
Заключение
Функция реализована, но есть еще много мест, которые можно оптимизировать, и я также надеюсь указать и дать мнения. Если вам не нравится такой каталог или ваши реальные потребности отличаются, это не более чем разница в CSS. Реализация функции часто определяет эффект, вы можете переписать css ul > li в соответствии с вашими потребностями. Это только часть моего фактического проекта. Это на самом деле намного сложнее, чем это. Но этого достаточно, в следующем выпуске я познакомлю вас с тем, как сделать редактор статей, реализующий стиль Nuggets, так что следите за обновлениями!