好的文章要有好的提纲
前言
如果在写文章之前,构建好结构,那么写起来就不那么费事,井井有条。这就是标题的技巧了,对于WP文章,我们可以把它单独列出来,像百度百科,一目了然式的导航,同时也特别适合于长篇文章。效果图:
分析
那么要怎么实现这样子的结构呢,其实有2种方案。
方案一:利用JS,读取文章内容,过滤标题,生成文章目录,插入到页面中。
方案二:利用PHP,因为WP本来就是基于PHP的,我们可以在文章输出之前生成目录再一次性渲染页面。
总之,就是利用正则表达式过滤标题,生成目录。而我现在使用的是第二种方案,大概是处于这样的考虑:利用JS操作时,可能会造成浏览器的重排与重绘,影响渲染,而PHP就不会,所以就用第二种方法实现出来了。
生成目录
在functions.php中添加以下代码,已经写了注释,具体效果请查看轩枫阁的文章左侧目录导航(大部分文章都有)
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 |
/* * author:轩枫 * time: 2013/12/15 */ function article_index($content) { $matches = array(); $ul_li = ''; //匹配出h2、h3标题 $rh = "/<h[23]>(.*?)<\/h[23]>/im"; $h2_num = 0; $h3_num = 0; //判断是否是文章页 if(is_single()){ if(preg_match_all($rh, $content, $matches)) { // 找到匹配的结果 foreach($matches[1] as $num => $title) { $hx = substr($matches[0][$num], 0, 3); //前缀,判断是h2还是h3 $start = stripos($content, $matches[0][$num]); //匹配每个标题字符串的起始位置 $end = strlen($matches[0][$num]); //匹配每个标题字符串的结束位置 if($hx == "<h2"){ $h2_num += 1; //记录h2的序列,此效果请查看百度百科中的序号,如1.1、1.2中的第一位数 $h3_num = 0; // 文章标题添加id,便于目录导航的点击定位 $content = substr_replace($content, '<h2 id="h2-'.$num.'">'.$title.'</h2>',$start,$end); $title = preg_replace('/<.+?>/', "", $title); //将h2里面的a链接或者其他标签去除,留下文字 $ul_li .= '<li class="h2_nav"><a href="#h2-'.$num.'" class="tooltip" title="'.$title.'">'.$title."</a><i class=\"post_nav_dot\"></i></li>\n"; }else if($hx == "<h3"){ $h3_num += 1; //记录h3的序列,此熬过请查看百度百科中的序号,如1.1、1.2中的第二位数 $content = substr_replace($content, '<h3 id="h3-'.$num.'">'.$title.'</h3>',$start,$end); $title = preg_replace('/<.+?>/', "", $title); //将h3里面的a链接或者其他标签去除,留下文字 $ul_li .= '<li class="h3_nav"><a href="#h3-'.$num.'" class="tooltip" title="'.$title.'">'.$title."</a><i class=\"post_nav_dot\"></i></li>\n"; } } } // 将目录拼接到文章 $content = $content . "<div class=\"post_nav\"><ul class=\"post_nav_content\">\n" . $ul_li . "</ul></div>\n"; return $content; }elseif(is_home){ return $content; } } add_filter( "the_content", "article_index" ); |
规则
匹配文章中的h2、h3标题,生成文章目录导航。此次升级版本,兼容在标题中包含链接,如<h2><a>前言</a></h2>;也兼容标题里面包含其他的标签的情况。但是不支持给h2、h3标签增加属性,如:<h2 id=”h2″ style=”float:left”></h2>。只支持纯净的标题标签
技巧
在编写文章时,有一定的技巧。快速设置2级标题h2的快捷键:Ctrl+2,3级标题h3是:Ctrl+3。
其他效果
像本站的导航就有个箭头随着页面的滚动而指向不同的目录标题,这个功能是来源于jQuery的插件OnePageNav。而点击标题时,动画滚动到页面相应位置而不是直接跳到相关内容,是来源于animatescroll这个jQuery插件。
小结
功能介绍完了,其实写这个的时候,由于正则表达式不是很扎实,学了又忘;而且对PHP也不是很熟,所以写的比较久。不过也是一种锻炼吧,很多功能不是很有必要,但是如果能提升用户体验,那就是一个好功能。
码云笔记是一个关注web前端开发、javascript教程、css教程的独立个人前端技术博客,记录本人工作中遇到的问题,以及经验总结和分享
博主你好,我用你的代码目录倒是能正常显示,但是它是显示在文章的结尾处……如何才能拼接至开头的地方啊求点破迷津!!
借鉴了下你的目录实现思路。我试了一下,貌似通过js来添加目录,如果只是像你的思路里面正则匹配文本,第一个操作生成导航目录并添加进页面,第二个操作给h标签添加上id,再把整个文档内容替换,这两个DOM操作貌似并没有进行进行大规模的重绘,我用chrome的timeline统计了几次,感觉添加菜单和不添加菜单页面完成的速度并没有大的差别。
不错
点开有惊喜:https://www.baidu.com/s?ie=utf-8
点开有惊喜:https://www.baidu.com/s?ie=utf-8
点开有惊喜:https://www.baidu.com/s?ie=utf-8
你的目录做得很漂亮啊
能不能做成一个插件啊/?在想要的文章调用
不会写插件[可怜]而且代码加起来也挺简单的呀
我把你代码加到我的网站,网站挂掉了。。。我3天的心血全没了,wordpress 自动重装了,昨天通宵弄的,心都吐血了
没有备份吗 – – 网站挂掉了,把新加的代码删掉就好了呀,重装之后主题还是在的。现在问题在哪,3天做了什么
增加了很多小东西,手动17篇文章,啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
不懂怎么手动加的,加的东西要么还在数据库,要么在文件里吧
而且不都是本地写好,再线上弄的吗 – –
直接线上
我的意思是不要全部文章调用你这个目录,需要的文章才调用,你这些代码加进去我的网站打不开,删掉才打得开网站
这里是文章页就会调用的,可以在这里过滤掉不用的文章
//判断是否是文章页
if(is_single()){
用不了,网站挂了
博主能升级下吗?
目前没时间研究呢,具体得看看是哪里得代码不兼容导致的,替换下就好啦
好啊~~~~~~
能不能不直接插入呢 可以直接调用吗?
需要写代码,具体在文章中应该写清楚了
就是被这个吸引进来的~ 在wordpress里加这个可不容易
收藏了
好东西 借鉴了
好牛逼的博客
很好,我之前也想写写类似的功能,无奈技术不扎实,时间不充足,对你写的表示赞一个
想实现的挡都挡不住
这个很赞呢,你的js是怎么控制光标选中的啊
就是 那个 蓝色小箭头 。是用scroll时间来判断吗?
箭头随着页面的滚动而指向不同的目录标题,这个功能是来源于jQuery的插件OnePageNav。而点击标题时,动画滚动到页面相应位置而不是直接跳到相关内容,是来源于animatescroll这个jQuery插件
我也做了一个不用插件的。那个库太大了 ,我用了2K左右代码搞定了。
2K代码实现OnePageNav插件相同效果?
可以看看我的嘛
怎么样式也抄,虽然说我是抄百度的→_→ 用了什么插件
我改进了好多东西呢。
能不能提供一下完整的代码呀?关于JS的
//标记自动定位$(“.post_nav_content”).onePageNav({ currentClass: “active”, changeHash: false, easing: “easeInOutExpo”, filter: “:not(.external)”, scrollSpeed: 800, scrollOffset: 0, scrollThreshold: 0.1, begin: false, end: false, scrollChange: false});// 页面滚动至相应位置$(“.post_nav_content li a”).click(function(){ var jumpId = $(this).attr(“href”); $(jumpId).animatescroll({padding:adminBar}); return false;});
都是插件的函数调用