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