説到 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 只需要提供分數即可。