Directorio de artículos personalizados de Vue

1. Demanda

Extraiga las etiquetas H1-H6 de acuerdo con el contenido del artículo del tipo de cadena, genere la visualización de la estructura del directorio del artículo y genere los puntos de anclaje correspondientes, haga clic para saltar.

2. Representación

3. Implementación del código

1. Código de plantilla

<a-card style="margin:10px 10px 0 20px;position: absolute;top:30%;width:15%;">   
<b>文章目录</b>   
<p></p>   
<p v-for="menuitem in menuTree" :key="menuitem"><a :href="getElementmaodian(menuitem)" :style="menustyle(menuitem)">{
   
   {getElementcontent(menuitem)}}</a></p></a-card>

2. Código del método

1) Generar una estructura de directorio basada en el contenido del artículo.

/*设置文章目录结构*/  
getCenceptQuerySelect(){   
    const str_content = this.selectConcept.contents   
    const regex = /<h[1-6](.*?)>(.*?)<\/h[1-6]>/g;//正则表达式匹配提取所有H1-H6标签         
    var match    
    while((match = regex.exec(str_content)) !== null{     
        this.menuTree.push(match[0])    
    }  
},

2) estilo de directorio

/*文章结构标题缩进*/  
menustyle(menuiten){ 
    var type = menuiten.slice(1,3)   
    var menutyle = ''   
    switch(type){ 
        case 'h1': menutyle = 'margin-left:10px;';break    
        case 'h2': menutyle = 'margin-left:20px;';break    
        case 'h3': menutyle = 'margin-left:30px;';break    
        case 'h4': menutyle = 'margin-left:40px;';break    
        case 'h5': menutyle = 'margin-left:50px;';break    
        case 'h6': menutyle = 'margin-left:60px;';break    
        default: break   
    }       
    return menutyle  
},

3) Obtener el ancla de la etiqueta

/*获取标签锚点*/  
getElementmaodian(item){   
    var placeholder = document.createElement('div')   
    placeholder.innerHTML = item       //返回id锚点   
    return '#' + placeholder.firstElementChild.id  
},

4) Agregue el código

Dado que el contenido generado mediante el uso de texto enriquecido para crear un artículo no tiene un punto de anclaje, es necesario personalizarlo:

const str_content = this.addConcept.contents    
const regex = /<h[1-6]>(.*?)<\/h[1-6]>/g;         
var match    var menuTree = []    
while((match = regex.exec(str_content)) !== null){        
    menuTree.push(match[0])    
}         
menuTree.forEach(item=>{     
    var placeholder = document.createElement('div')     
    placeholder.innerHTML = item

    //生成有锚点的元素,锚点value为显示的内容     
    var rep = item.replaceAll('>'+placeholder.firstElementChild.innerHTML+'<', ' id=\'' +     placeholder.firstElementChild.innerHTML + '\'>'+placeholder.firstElementChild.innerHTML+'<')      
    this.addConcept.contents = this.addConcept.contents.replaceAll(item, rep) //替换有锚点的元素 
})

4. Avanzado - árbol de directorios

necesidad

La estructura de árbol del directorio se puede ampliar y contraer.

representaciones

 

Código

1. Generar el Json de la estructura de árbol de directorios

menuTree_json almacena datos estructurales

 generateDirectoryTree_Json(content){
   const regex = /<h[1-6](.*?)>(.*?)<\/h[1-6]>/g;
   var match
   while ((match = regex.exec(content)) !== null) {
    var item = {
     level: this.menuItemLevel(match[0]),   //层级:H1-1/H2-2/H3-3/H4-4/H5-5/H6-6
     anchor: this.getElementmaodian(match[0]), //锚点
     title: this.getElementcontent(match[0]), //内容
     child: [],                //子节点
     isExpand:true               //默认该树节点展开
    }
      
    this.addMenuitem(this.menuTree_json,item) //从树根节点开始添加子节点
   }
  },
   
  /*递归插入*/
  addMenuitem(menu, item){
   if (menu.length === 0) {
    menu.push(item)
   }
   else {
    if (item.level > menu[menu.length - 1].level) {
     //递归添加子节点
     this.addMenuitem(menu[menu.length - 1].child, item)
    }
    else if (menu.length - 1 === 0) {
     menu.push(item)
    }
    else {
     menu.push(item)
    }
   }
  },

2. El directorio se genera recursivamente según el Json de la estructura de árbol de directorios en la plantilla.

Aquí, esta parte se define como un componente para facilitar las llamadas recursivas.

Llamada de componente:

<ContentMenu :menu="menuTree_json"></ContentMenu>

Definición de componente:

<template>
 <div>
<div v-for="menuitem in menu" :key="menuitem" style="overflow: auto;margin-top:10px;">
   <svg @click="menuitem.isExpand=!menuitem.isExpand" v-if="menuitem.child.length != 0 && !menuitem.isExpand" t="1682300013635" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3229" width="16" height="16"><path d="M946.33106 697.353498 541.30749 284.093337c-15.690354-16.009625-41.469484-16.009625-57.160861 0l-405.024593 413.260162c-24.819269 25.323758-6.877641 68.028373 28.579919 68.028373l810.048163 0C953.209724 765.381871 971.150328 722.677257 946.33106 697.353498z" fill="#1296db" p-id="3230"></path></svg>
   <svg @click="menuitem.isExpand=!menuitem.isExpand" v-if="menuitem.child.length != 0 && menuitem.isExpand" t="1682300082130" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3505" width="16" height="16"><path d="M79.123059 327.850933l405.024593 413.260162c15.690354 16.009625 41.469484 16.009625 57.160861 0l405.02357-413.260162c24.819269-25.323758 6.877641-68.028373-28.579919-68.028373L107.704001 259.82256C72.245418 259.82256 54.30379 302.527175 79.123059 327.850933z" fill="#1296db" p-id="3506"></path></svg>
   <a href="javascript:void(0)" @click="goAnchor(menuitem.anchor)" style="margin-left:5px;margin-top:3px;">
    <span v-html="menuitem.title"></span>
</a>
   <div v-if="menuitem.isExpand" style="margin-left:30px;margin-top:10px;">
    <!--递归生成目录树,递归自己-->
    <contentMenu :menu="menuitem.child"></contentMenu>
   </div>
  </div>
 </div>
</template>
<script>
import { mixins_menutree } from '../../mixin/menutree'
export default {
 name:'contentMenu', //定义name才能组件自己递归调用自己
 mixins:[mixins_menutree],
 props:{
menu:[]
 }
}
</script>

5. Búsqueda de directorio

necesidad

Cuando hay demasiadas entradas de directorio, se requiere filtrado de búsqueda

Efecto

 

Código

<a-input-search    
    size="small"    
    placeholder="文章目录"    
    v-model = "searchMenu"   
    @search="onSearchMenu"
></a-input-search>

/*onSearchMenu 
  搜索目录,重新生成目录
  */
  onSearchMenu() {
   this.menuTree_json = []
    
   this.menu_init.forEach(item => {
    if (item.title.toLowerCase().indexOf(this.searchMenu.toLowerCase()) != -1) {
item.child = [] //孩子节点直接去掉
     this.addMenuitem(this.menuTree_json, item)
    }
   })
  },

6. Problemas encontrados

1. Problema de error de la consola de salto china del punto de anclaje

 El punto de anclaje chino #punto de anclaje 1  se escapa a #%E9%94%9A%E7%82%B91 , lo que hace que la consola informe un error, pero puede funcionar y saltar correctamente. . .

2. Una etiqueta href salta al IIS después de que el salto se publica debido a un error.

<a :href="getElementmaodian(menuitem)"

resolver:

<a href="javascript:void(0)" @click="goAnchor(getElementmaodian(menuitem))"

goAnchor(selector){ //锚点跳转    document.querySelector(selector).scrollIntoView({  behavior:'smooth'    })},

3. Si el punto de anclaje comienza con un número, se considerará ilegal

Solución 1 : después de procesar la cadena de título, se genera la identificación del ancla para garantizar que el ancla sea correcta.

Todavía hay problemas:

1. Los dos últimos dígitos de la cadena cifrada con btoa son '==' y el punto de anclaje no será válido. Solución temporal: extraiga solo los primeros 20 dígitos

2. Si solo se extraen los 20 bits superiores, pueden existir los mismos puntos de anclaje

//标题字符串处理,保证锚点正确

var str64 = window.btoa(window.encodeURIComponent(placeholder.firstElementChild.innerHTML)).slice(0,20)

var rep = item.replaceAll('>'+placeholder.firstElementChild.innerHTML+'<', ' id=\'' + str64 + '\'>'+placeholder.firstElementChild.innerHTML+'<') this.addConcept.contents = this.addConcept.contents.replaceAll(item, rep)

Solución dos :

Cadena de números aleatorios

//标题字符串处理,保证锚点正确var str64 = window.btoa(window.encodeURIComponent(placeholder.firstElementChild.innerHTML))
//移除特殊字符
str64 = str64.replaceAll('=', '')
//生成随机数转成36进制,再截取后8位
var str_random = Math.random().toString(36).slice(-8)

str64 = str64 + str_random
var rep = item.replaceAll('>'+placeholder.firstElementChild.innerHTML+'<', ' id=\'' + str64 + '\'>'+placeholder.firstElementChild.innerHTML+'<') 
this.addConcept.contents = this.addConcept.contents.replace(item, rep)//使用replace而不是replaceAll,否则可能替换所有

Solución tres:

Genere directamente tres números aleatorios y conviértalos a 36 hexadecimales, intercepte los últimos 8 dígitos respectivamente y luego empalme

​
var str_random1 = Math.random().toString(36).slice(-8)
var str_random2 = Math.random().toString(36).slice(-8)
var str_random3 = Math.random().toString(36).slice(-8)var str_random = str_random1 + str_random2 + str_random3

​

Supongo que te gusta

Origin blog.csdn.net/gcf10080353/article/details/130616738
Recomendado
Clasificación