说到 JavaScript 模板引擎,大家首先想到的肯定是 Angular 和 React 这些时下比较流行的项目,它们让前端开发模式变的与传统的 WordPress 主题大不相同。
不同于 WordPress 的使用 PHP 在服务端处理一切,调用模板生成好 HTML 再返回给用户;JavaScript 模板引擎下,服务器只负责处理和生成数据,然后由 JavaScript 在浏览器前端,根据专门为它设计的模板生成出 HTML 代码。
这种开发模式对于制作和用户有大量交互的网站非常有优势,尤其是在使用 AJAX 上传和获取数据时,可以避免很多麻烦。虽然这种技术我很喜欢,也符合未来的发展趋势,但是因为搜索引擎相关的问题的不完善,导致 JavaScript 模板引擎只能在 Web APP 和管理后台之类的网页被使用。
不过,即使在普通网站中不能全面的应用,在一些特殊的地方,小范围的使用 JavaScript 模板生成 HTML 代码也是非常方便的,比如评论列表、设置选项和 AJAX 加载文章列表之类的,不需要搜索引擎抓取,又需要 JavaScript 参与的功能。
在 WordPress 核心中,提供了一个基于 Underscore.js 的简易 JavaScript 模板 「引擎」,被主题定制器大量的使用,今天我们就来一起学一下,相信只要合理利用它,就可以完美解决你拼接大量字符串的痛苦。
挂载脚本
在开始正式之前,首先要把用来支持 JavaScript 模板的 Underscore.js 引入进来,它在脚本排队系统中的名称是 wp-util
,可以直接挂载:
functionBing_enqueue_scripts(){ wp_enqueue_script('wp-util'); } add_action('wp_enqueue_scripts','Bing_enqueue_scripts'); |
也可以把它设置成我们的脚本的依赖:
functionBing_enqueue_scripts(){ wp_enqueue_script( 'base', get_template_directory_uri().'/js/base.js', array('jquery','wp-util'),//依赖 wp-util 脚本 '1.0' ); } add_action('wp_enqueue_scripts','Bing_enqueue_scripts'); |
存储模板
在大多数情况下,我们会在页面已经加载完成之后,调用模板并传入数据来生成 HTML,但是这些模板存放在哪是个麻烦的问题。首先,模板不能被用户看到,但是如果直接使用 CSS 隐藏,又会产生很大的 SEO 问题。
出于这个原因,我们在这里使用一对 <script>
标签来容纳模板本身,然后把 type
属性设置成 text/template
。这样,当浏览器和搜索引擎在看到是 <script>
标签之后,就不会把里边的模板代码当成网页内容,并且,由于无法理解 type
属性的值,也不会当做 JavaScript 代码来执行,是非常完美的解决方案。
<script type="text/template"id="tmpl-article"> <!--在这里存放模板代码--> </script> |
为了方便调用这个模板,还要给 <script>
标签的 id
参数设置成 tmpl-{id}
,在以后的使用中,就可以通过 ID 来指定调用哪个模板。
制作模板
模板往往是由 HTML 代码和一些动态的标签组成,也可以在里边运行 JavaScript 代码来完成逻辑上的操作。
最常有的语法有三种:
{{ var }}
- 输出进行了 HTML 转义的变量。{{{ var }}}
- 输出原始变量。<# runCode(); #>
- 运行 JavaScript 代码,就像 PHP 模板文件中的<?php run_code(); ?>
那样。
<script type="text/template"id="tmpl-article"> <article id="post-{{ data.id }}"class="entry"> <#if(data.hasThumbnail){#> <div class="entry-thumbnail"> <img src="{{ data.thumbnail }}"/> </div> <#}#> <h2 class="entry-title"> <ahref="{{ data.url }}">{{data.title}}</a> </h2> <div class="entry-summary">{{{data.excerpt}}}</div> </article> </script> |
上边的例子中,大量的使用了 data
变量,这是我们在调用模板生成 HTML 时所传入的参数 (下边会具体讲到),可以通过调用它的属性来动态获取数据,让我们的模板可以被复用。
在制作完成之后,我建议把一个模板单独存放在一个文件中,然后通过 wp_footer
钩子插入到页面底部,这里我直接使用 include
引入了存储模板代码的文件,这样可以保证代码的干净整洁。
functionBing_load_article_template(){ include(get_template_directory().'/templates/article-template.php'); } add_action('wp_footer','Bing_load_article_template'); |
生成数据
模板准备好了,在生成 HTML 之前,我们首先得有数据,这些数据一般是通过 AJAX 来获取,也可以直接放在 JavaScript 变量或者元素的 data-*
参数里,这个根据需求来决定,怎么方便怎么来。
在服务器中,我们要根据需求生成出数据,然后封装成 JSON,给前端使用。
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 |
functionBing_random_posts(){ $posts=get_posts('orderby=rand&posts_per_page=10'); $json =array(); foreach($postsas$post){ $json[$post->ID]=array( 'id' =>$post->ID, 'hasThumbnail'=>has_post_thumbnail($post->ID), 'url' =>get_permalink($post->ID), 'title' =>get_the_title($post), 'excerpt' =>get_the_excerpt($post) ); if($json[$post->ID]['hasThumbnail']){ $thumbnail_id=get_post_thumbnail_id($post->ID); $thumbnail =wp_get_attachment_image_src($thumbnail_id,'full'); $json[$post->ID]['thumbnail']=$thumbnail[0]; } } $json=array_values($json); wp_send_json($json); } add_action('wp_ajax_random-posts','Bing_random_posts'); add_action('wp_ajax_nopriv_random-posts','Bing_random_posts'); |
上边的代码中,制作好数据之后,我们讨巧的使用了 wp_send_json()
函数直接封装并发送 JSON 。如果需要直接把数据放在页面里,就得使用 wp_json_encode()
函数来封装 JSON 并获取,然后再在放到我们想要的位置。
<script type="text/javascript"> jQuery(document).on('click','.random',function(){ varposts='<?php echo wp_json_encode( $json ); ?>'; }); </script> |
使用模板
重头戏来了,现在有了模板也有了数据,就差把两者结合到一起,生成出 HTML 代码了。
首先,使用标题中提到的 wp.template()
方法,传入模板的 ID 来初始化它;然后使用返回的方法,传入 data
参数即可生成 HTML,总共说了一句话,就是这么简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
jQuery(document).on('click','.random',function(){ varcontent =jQuery('#content'); content.empty(); jQuery.get(adminAjax,'action=random-posts',function(data){ vartemplate=wp.template('article'); for(vari=data.length-1;i>=0;--i){ varhtml=template(data[i]); content.prepend(html); } }); returnfalse; }); |
上边的代码中,调用模板,传入数据,生成出 HTML 代码,再通过 jQuery 的 DOM 操作方法 append()
、 prepend()
、 after()
和 before()
把代码插入到想要的位置,或者直接用 html()
方法修改元素的内容。
后记
看到最后,你可能会有点小失望,前边的准备时间那么长,到最后只需要两步走就能完成操作。实际上,这个 JavaScript 模板的功能也就这么多,只能帮你生成 HTML,减少在 JavaScript 代码中大量拼接字符串的痛苦。
但是,如果能够利用好,也能在实际开发中解决大问题。就比如我最近想制作一个点击插件链接,就能直接弹出插件信息的功能,如果把所有插件的弹窗都在 PHP 中生成好 HTML 代码,会导致页面非常庞大,重复代码很多;直接在 JavaScript 中把弹窗代码拼接起来吧,更是让我非常痛苦,所以才盯上了这个模板。
在实际使用过程中,还是在 「制作模板」 这一步骤的可扩展性最强,因为你可以嵌入任意 JavaScript 代码,各种逻辑都能完成,比如上边所说的插件弹窗,就有一个插件的星级评价显示,这些都可以在模板中完成,PHP 只需要提供分数即可。