功能演示 在 markdown
中使用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # 默认选择第2个 {% tabs Name, 2 %} <!-- tab first Tab--> tab 1 content <!-- endtab --> <!-- tab Second Tab--> tab 2 content <!-- endtab --> <!-- tab Third Tab--> tab 3 content <!-- endtab --> {% endtabs %}
最终渲染的内容如下:
first Tab Second Tab Third Tab
实现过程 首先需要了解下,对于渲染的原理:hexo
将 markdown
中的语法标签转换成对应的 html
结构, 然后为转换成的 html
内容添加样式和动画,所以实现的时候需要:
markdown中标签解析,并生成对一个的选项卡HTML的结构
javascript关于生成的选项卡的点击切换逻辑
css样式美化操作
将对应的标签转换成html结构 追踪hexo代码,其实现逻辑主要在 /themes/fluid/scripts/tags
目录下,在这个目录下创建一个tabs.js
的文件,并添加内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 'use strict' ;function postTabs (args, content ) { var tabBlock = /<!--\s*tab (.*?)\s*-->\n([\w\W\s\S]*?)<!--\s*endtab\s*-->/g ; args = args.join (' ' ).split (',' ); var tabName = args[0 ]; var tabActive = Number (args[1 ]) || 0 ; var matches = []; var match; var tabId = 0 ; var tabNav = '' ; var tabContent = '' ; !tabName && hexo.log .warn ('Tabs block must have unique name!' ); while ((match = tabBlock.exec (content)) !== null ) { matches.push (match[1 ]); matches.push (match[2 ]); } for (var i = 0 ; i < matches.length ; i += 2 ) { var tabParameters = matches[i].split ('@' ); var postContent = matches[i + 1 ]; var tabCaption = tabParameters[0 ] || '' ; var tabIcon = tabParameters[1 ] || '' ; var tabHref = '' ; postContent = hexo.render .renderSync ({text : postContent, engine : 'markdown' }).trim (); tabId += 1 ; tabHref = (tabName + ' ' + tabId).toLowerCase ().split (' ' ).join ('-' ); ((tabCaption.length === 0 ) && (tabIcon.length === 0 )) && (tabCaption = tabName + ' ' + tabId); var isOnlyicon = tabIcon.length > 0 && tabCaption.length === 0 ? ' style="text-align: center;"' : '' ; let icon = tabIcon.trim (); icon = icon.startsWith ('fa' ) ? icon : 'fa fa-' + icon; tabIcon.length > 0 && (tabIcon = `<i class="${icon} "${isOnlyicon} ></i>` ); var isActive = (tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1 ) ? ' active' : '' ; tabNav += `<li class="tab${isActive} "><button type="button" data-href="#${tabHref} ">${tabIcon + tabCaption.trim()} </button></li>` ; tabContent += `<div class="tab-pane${isActive} " id="${tabHref} ">${postContent} </div>` ; } tabNav = `<ul class="nav-tabs">${tabNav} </ul>` ; tabContent = `<div class="tab-content">${tabContent} </div>` ; return `<div class="tabs" id="${tabName.toLowerCase().split(' ' ).join('-' )} ">${tabNav + tabContent} </div>` ; } hexo.extend .tag .register ('tabs' , postTabs, {ends : true }); hexo.extend .tag .register ('subtabs' , postTabs, {ends : true }); hexo.extend .tag .register ('subsubtabs' , postTabs, {ends : true });
该代码的作用就是扫描markdown
文件中所有关于tabs
的标签,并将其转换成对应的HTML
块结构
javascript关于生成的选项卡的点击切换逻辑 这个主要是为了将生成的html块添加切换功能,是需要生成对应的静态文件的,所以编写在 /themes/fluid/source/js/
目录下, 在这个目录下创建 tabs.js
用于添加切换功能逻辑代码,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 const siblings = (ele, selector ) => { return [...ele.parentNode .children ].filter ((child ) => { if (selector) { return child !== ele && child.matches (selector) } return child !== ele }) } const tabsFn = { clickFnOfTabs : function ( ) { document .querySelectorAll (' .tab > button' ).forEach (function (item ) { item.addEventListener ('click' , function (e ) { const $this = this const $tabItem = $this.parentNode if (!$tabItem.classList .contains ('active' )) { const $tabContent = $tabItem.parentNode .nextElementSibling const $siblings = siblings ($tabItem, '.active' )[0 ] $siblings && $siblings.classList .remove ('active' ) $tabItem.classList .add ('active' ) const tabId = $this.getAttribute ('data-href' ).replace ('#' , '' ) const childList = [...$tabContent.children ] childList.forEach (item => { if (item.id === tabId) item.classList .add ('active' ) else item.classList .remove ('active' ) }) } }) }) } } tabsFn.clickFnOfTabs ()
之后需要告诉 fluid
添加自定义的 js
代码,即在 _config.fluid.yml
文件中找到自定义 custom_js
选项,将 /js/tabs.js
添加:
1 2 custom_js: - /js/tabs.js
css样式美化操作 之后就需要对生成的 HTML
颜色样式进行编写代码,同理,这个是给生成静态文件的样式,所以写在 /themes/fluid/source/css/
目录下, 在这个目录下创建 tabs.css
用于添加切换功能逻辑代码,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 :root { --nav-tabs-bg : #fff3e0 ; --primary : #ffecb3 ; --secondary : #f7f9ee ; --content-bg : #ffffff ; --border : #e9f5dc ; --activate-border : #a8e9ed ; --text : #6c757d ; --active-text : #2e647a ; --primary-shadow : rgba (255 , 127 , 80 , 0.2 ); --shadow : rgba (0 ,0 ,0 ,0.2 ); --tab-button-hover : #f6e4c6 ; }.tabs { max-width : 96% ; margin : 10px auto; border-radius : 12px ; overflow : hidden; box-shadow : 0 6px 12px var (--shadow); }.nav-tabs { display : flex; list-style : none; padding : 0 ; margin : 0 ; background : var (--nav-tabs-bg); border-radius : 12px 12px 0 0 ; box-shadow : 0 2px 6px var (--shadow); }.tabs > ul { padding : 0 ; margin : 0 ; }.tabs > ul > li { margin : 0 ; padding : 0 ; }.tab { flex-shrink : 0 ; padding : 0 8px ; }.tab > button { position : relative; padding : 8px 16px ; background : var (--secondary); border : none; cursor : pointer; font-size : 14px ; color : var (--text); transition : all 0.3s ease; border-radius : 12px 12px 0 0 ; border-right : 2px solid var (--border); border-left : 2px solid var (--border); border-top : 2px solid var (--border); }.tab > button :hover { background : var (--tab-button-hover); }.tab .active > button { background : var (--primary); color : var (--active-text); border-right : 2px solid var (--activate-border); border-left : 2px solid var (--activate-border); border-top : 2px solid var (--activate-border); box-shadow : inset 0 -3px 0 var (--primary-shadow); }.tab > button .active :hover { background-position : left bottom; }.tab-pane { display : none; }.tab-pane .active { display : block; }.tab-content { padding : 10px ; background : var (--content-bg); border-top : 1px solid var (--border); border-bottom-left-radius : 5px ; border-bottom-right-radius : 5px ; }
同理,在 _config.fluid.yml
文件中找到自定义 custom_css
选项,将 /css/tabs.css
添加:
1 2 custom_css: - /css/tabs.css
其实这个不算完整,因为 hexo
有主题切换功能,即 light
和 dark
主题切换操作。我这个实现都用了同一套颜色,肯定是有问题的。其实切换实现原理也简单,只需要将上述中 :root
颜色配置写到 themes\fluid\source\css\_pages\_base\color-schema.styl
中, 并分别配置两套不同的颜色组合,然后再在 /themes/fluid/source/css/tabs.css
中使用即可。