Creating a Custom Directive for WordPress Post Listing on the Front End

Creating a Custom Directive for WordPress Post Listing on the Front End

在本系列的前一部分中,我們引導(dǎo)了 AngularJS 應(yīng)用程序,為不同視圖配置了路由,并圍繞帖子、用戶和類別的路由構(gòu)建了服務(wù)。使用這些服務(wù),我們現(xiàn)在終于能夠從服務(wù)器獲取數(shù)據(jù)來為前端提供動(dòng)力。

在本系列的這一部分中,我們將致力于為帖子列表功能構(gòu)建自定義 AngularJS 指令。在本系列的當(dāng)前部分中,我們將:

  • 介紹 AngularJS 指令以及為什么我們應(yīng)該創(chuàng)建一個(gè)
  • 規(guī)劃帖子列表功能的指令及其所需的參數(shù)

  • 為帖子列表創(chuàng)建自定義 AngularJS 指令及其模板

所以讓我們首先介紹一下 AngularJS 指令以及為什么我們需要它們。

AngularJS 指令簡(jiǎn)介

AngularJS 中的指令是一種修改 HTML 元素行為和重用可重復(fù)代碼塊的方法。它們可用于修改 HTML 元素及其子元素的結(jié)構(gòu),因此它們是引入自定義 UI 小部件的完美方式。

在分析本系列第一部分中的線框圖時(shí),我們注意到帖子列表功能在三個(gè)視圖中使用,即:

  1. 發(fā)布列表
  2. 作者簡(jiǎn)介

  3. 類別帖子列表

因此,我們可以創(chuàng)建一個(gè)自定義 AngularJS 指令,其中包含使用我們?cè)诒鞠盗星懊娌糠謩?chuàng)建的服務(wù)來檢索帖子的業(yè)務(wù)邏輯,而不是編寫單獨(dú)的功能來列出這三個(gè)頁面上的帖子。除了業(yè)務(wù)邏輯之外,該指令還將包含在某些視圖上列出帖子的渲染邏輯。也在該指令中定義了帖子分頁和根據(jù)某些條件檢索帖子的功能。

因此,為帖子列表功能創(chuàng)建自定義 AngularJS 指令允許我們僅在一個(gè)位置定義該功能,這將使我們將來更容易擴(kuò)展或修改此功能,而無需更改其中的代碼使用它的所有三個(gè)實(shí)例。

話雖如此,讓我們開始為帖子列表功能編寫自定義指令。

規(guī)劃帖子列表的自定義 AngularJS 指令

在我們開始編寫用于構(gòu)建帖子列表功能指令的任何代碼之前,讓我們分析一下指令中所需的功能。

在最基本的層面上,我們需要一個(gè)可以在帖子列表、作者個(gè)人資料和類別頁面的視圖上使用的指令。這意味著我們將創(chuàng)建一個(gè)放置在 HTML 中的自定義 UI 小部件(或 DOM 標(biāo)記),AngularJS 將根據(jù)我們?yōu)橹噶畹奶囟▽?shí)例提供的選項(xiàng)來處理其余的事情。

因此,我們將創(chuàng)建一個(gè)由以下標(biāo)記標(biāo)識(shí)的自定義 UI 小部件:

<post-listing></post-listing>

但是我們還需要這個(gè)指令是靈活的,即將參數(shù)作為輸入并采取相應(yīng)的行動(dòng)。考慮用戶個(gè)人資料頁面,我們只希望顯示屬于該特定用戶的帖子,或者類別頁面,其中將列出屬于該類別的帖子。這些參數(shù)可以通過以下兩種方式提供:

  1. 在 URL 中作為參數(shù)
  2. 直接將指令作為屬性值

在 URL 中提供參數(shù)似乎是 API 的本機(jī),因?yàn)槲覀円呀?jīng)熟悉這樣做了。因此,用戶可以通過以下方式檢索屬于特定用戶的一組帖子:

https://127.0.0.1:8080/#/posts?author=1 

上述功能可以通過AngularJS提供的$routeParams服務(wù)來實(shí)現(xiàn)。我們可以在此處訪問用戶在 URL 中提供的參數(shù)。我們?cè)诒鞠盗械那耙徊糠种凶?cè)路由時(shí)已經(jīng)研究過它。

至于直接向指令提供參數(shù)作為屬性值,我們可以使用如下內(nèi)容:

<post-listing post-args="{author=1}"></post-listing>

上面代碼片段中的 post-args 屬性采用參數(shù)來檢索一組特定的帖子,目前它采用作者 ID。此屬性可以采用任意數(shù)量的參數(shù)來檢索 /wp/v2/posts 路由支持的帖子。因此,如果我們要檢索由 ID 為 1 且屬于 ID 10 類別的用戶撰寫的一組帖子,我們可以執(zhí)行如下操作:

<post-listing post-args="{author=1, filter[cat]=10}"></post-listing>

上述代碼中的 filter[cat] 參數(shù)用于檢索屬于某個(gè)類別的一組帖子。

分頁也是使用帖子列表頁面時(shí)的一個(gè)基本功能。該指令將處理后分頁,并且此功能將由服務(wù)器返回的 X-WP-Total 和 X-WP-TotalPages 標(biāo)頭的值驅(qū)動(dòng)與響應(yīng)主體。因此,用戶將能夠在上一組帖子和下一組帖子之間來回導(dǎo)航。

確定了用于發(fā)布列表的自定義指令的實(shí)質(zhì)內(nèi)容后,我們現(xiàn)在已經(jīng)有了相當(dāng)堅(jiān)實(shí)的基礎(chǔ)來開始編寫代碼。

為帖子列表構(gòu)建自定義指令

為帖子列表功能構(gòu)建指令包括兩個(gè)步驟:

  1. 創(chuàng)建用于檢索帖子和處理其他內(nèi)容的業(yè)務(wù)邏輯。
  2. 為這些帖子創(chuàng)建一個(gè)渲染視圖以顯示在頁面上。

我們的自定義指令的業(yè)務(wù)邏輯將在指令聲明中處理。為了在 DOM 上呈現(xiàn)數(shù)據(jù),我們將創(chuàng)建一個(gè)用于列出帖子的自定義模板。讓我們從指令聲明開始。

指令聲明

AngularJS 中的指令可以使用以下語法為模塊聲明:

/**  * Creating a custom directive for posts listing  */ quiescentApp.directive( 'postListing', [function() {     return {      }; }] ); 

在這里,我們使用模塊中可用的 .directive() 方法在模塊上聲明指令。該方法將指令的名稱作為第一個(gè)參數(shù),并且該名稱與元素標(biāo)簽的名稱密切相關(guān)。由于我們希望 HTML 元素為 <post-listing></post-listing>,因此我們提供了標(biāo)簽名稱的駝峰式表示形式。您可以在官方文檔中了解有關(guān) AngularJS 執(zhí)行的規(guī)范化過程以匹配指令名稱的更多信息。

我們?cè)谏厦娴拇a中使用的用于聲明指令的符號(hào)稱為安全樣式的依賴注入。在這種表示法中,我們提供了一個(gè)依賴項(xiàng)數(shù)組作為指令所需的第二個(gè)參數(shù)。目前,我們尚未為自定義指令定義任何依賴項(xiàng)。但由于我們需要 Posts 服務(wù)來檢索帖子(我們?cè)诒鞠盗械纳弦徊糠种袆?chuàng)建的)以及本機(jī) AngularJS 的 $routeParams 和 $location服務(wù)用于訪問URL參數(shù)和當(dāng)前路徑,我們定義如下:

/**  * Creating a custom directive for posts listing  */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) {     return {         restrict: 'E',         scope: {             postArgs: '='         },         link: function( $scope, $elem, $attr ) {                  }     }; }] ); 

然后,這些依賴項(xiàng)可供定義為數(shù)組最后一個(gè)元素的函數(shù)使用。該函數(shù)返回一個(gè)包含指令定義的對(duì)象。目前,我們?cè)谥噶疃x對(duì)象中有兩個(gè)屬性,即 restrict 和 link。

restrict 選項(xiàng)定義了我們?cè)诖a中使用指令的方式,該選項(xiàng)可以有四個(gè)可能的值:

  1. A:用于將指令用作現(xiàn)有 HTML 元素的屬性。
  2. E:用于使用指令作為元素名稱。

  3. C:用于使用指令作為類名。

  4. M:用于將該指令用作 HTML 注釋。

restrict 選項(xiàng)也可以接受上述四個(gè)值的任意組合。

由于我們希望指令成為新元素 <post-listing></post-listing>,因此我們將限制選項(xiàng)設(shè)置為 E。如果我們要使用預(yù)先存在的 HTML 元素上的屬性來定義指令,那么我們可以將此選項(xiàng)設(shè)置為 A。在這種情況下,我們可以使用 在 HTML 代碼中定義該指令。

第二個(gè) scope 屬性用于修改指令的范圍。默認(rèn)情況下, scope 屬性的值為 false,這意味著指令的范圍與其父級(jí)的范圍相同。當(dāng)我們向它傳遞一個(gè)對(duì)象時(shí),會(huì)為該指令創(chuàng)建一個(gè)隔離的范圍,并且需要由其父級(jí)傳遞給該指令的任何數(shù)據(jù)都通過 HTML 屬性傳遞。這就是我們?cè)诖a中所做的,我們使用的屬性是 post-args,它被標(biāo)準(zhǔn)化為 postArgs。

p>

scope 對(duì)象中的 postArgs 屬性可以接受以下三個(gè)值中的任意一個(gè):

  1. =:表示傳遞給屬性的值將被視為對(duì)象。
  2. @:這意味著傳遞到屬性的值將被視為純字符串。

  3. &:表示傳遞給屬性的值將被視為函數(shù)。

由于我們選擇使用 = 值,因此傳遞到 post-args 屬性的任何值都將被視為 JSON 對(duì)象,我們可以使用該對(duì)象作為檢索帖子的參數(shù)。

第三個(gè)屬性 link 用于定義一個(gè)函數(shù),該函數(shù)用于操作 DOM 并定義該指令所需的 API 和函數(shù)。該函數(shù)是處理指令所有邏輯的地方。

link 函數(shù)接受作用域?qū)ο蟆⒅噶畹?HTML 元素以及指令的 HTML 元素上定義的屬性的對(duì)象的參數(shù)。目前,我們分別為范圍對(duì)象和 HTML 元素傳遞兩個(gè)參數(shù) $scope 和 $elem 。

讓我們?cè)?$scope 屬性上定義一些變量,我們將使用該變量在 DOM 上呈現(xiàn)帖子列表功能。

/**  * Creating a custom directive for posts listing  */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) {     return {         restrict: 'E',         scope: {             postArgs: '='         },         link: function( $scope, $elem, $attr ) {             // defining variables on the $scope object             $scope.posts = [];             $scope.postHeaders = {};             $scope.currentPage = $routeParams.page ? Math.abs( $routeParams.page ) : 1;             $scope.nextPage = null;             $scope.previousPage = null;             $scope.routeContext = $location.path();         }     }; }] ); 

因此,我們?cè)?$scope 對(duì)象上定義了六個(gè)屬性,我們可以在 DOM 中訪問它們。這些屬性是:

  1. $posts:保存服務(wù)器返回的 post 對(duì)象的數(shù)組。
  2. $postHeaders:用于保存服務(wù)器將與響應(yīng)正文一起返回的標(biāo)頭的對(duì)象。我們將使用它們來處理導(dǎo)航。

  3. $currentPage:保存當(dāng)前頁碼的整型變量。

  4. $previousPage:保存上一頁頁碼的變量。

  5. $nextPage:保存下一頁編號(hào)的變量。

  6. $routeContext:用于使用 $location 服務(wù)訪問當(dāng)前路徑。

我們之前為 HTML 屬性定義的 postArgs 屬性已在指令內(nèi)的 $scope 對(duì)象上可用。

現(xiàn)在我們準(zhǔn)備使用 Posts 服務(wù)向服務(wù)器發(fā)出請(qǐng)求以檢索帖子。但在此之前,我們必須考慮用戶作為 URL 參數(shù)提供的參數(shù)以及 post-args 屬性中提供的參數(shù)。為此,我們將創(chuàng)建一個(gè)函數(shù),使用 $routeParams 服務(wù)來提取 URL 參數(shù),并將它們與通過 post-args 屬性提供的參數(shù)合并: p>

/**  * Creating a custom directive for posts listing  */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) {     return {         restrict: 'E',         scope: {             postArgs: '='         },         link: function( $scope, $elem, $attr ) {             // defining variables on the $scope object             $scope.posts = [];             $scope.postHeaders = {};             $scope.currentPage = $routeParams.page ? Math.abs( $routeParams.page ) : 1;             $scope.nextPage = null;             $scope.previousPage = null;             $scope.routeContext = $location.path();                          // preparing query arguments             var prepareQueryArgs = function() {                 var tempParams = $routeParams;                 delete tempParams.id;                 return angular.merge( {}, $scope.postArgs, tempParams );             };         }     }; }] ); 

上述代碼中的 prepareQueryArgs() 方法使用 angular.merge() 方法,該方法擴(kuò)展了 $scope。 postArgs 對(duì)象與 $routeParams 對(duì)象。但在合并這兩個(gè)對(duì)象之前,它首先使用 delete 運(yùn)算符從 $routeParams 對(duì)象中刪除 id 屬性。這是必要的,因?yàn)槲覀儗⒃陬悇e和用戶視圖上使用此指令,并且我們不希望類別和用戶 ID 被錯(cuò)誤地解釋為帖子 ID。

準(zhǔn)備好查詢參數(shù)后,我們終于準(zhǔn)備好調(diào)用服務(wù)器并檢索帖子,我們使用 Posts.query() 方法來執(zhí)行此操作,該方法采用兩個(gè)參數(shù):

  1. 包含用于進(jìn)行查詢的參數(shù)的對(duì)象。
  2. 查詢完成后執(zhí)行的回調(diào)函數(shù)

因此,我們將使用 prepareQueryArgs() 函數(shù)為查詢參數(shù)準(zhǔn)備一個(gè)對(duì)象,并在回調(diào)函數(shù)中設(shè)置 上某些變量的值$scope 屬性:

// make the request and query posts Posts.query( prepareQueryArgs(), function( data, headers ) {     $scope.posts = data;     $scope.postHeaders = headers();     $scope.previousPage = ( ( $scope.currentPage + 1 ) &gt; $scope.postHeaders['x-wp-totalpages'] ) ? null : ( $scope.currentPage + 1 );     $scope.nextPage = ( ( $scope.currentPage - 1 ) &gt; 0 ) ? ( $scope.currentPage - 1 ) : null; }); 

回調(diào)函數(shù)獲取響應(yīng)正文和響應(yīng)標(biāo)頭的兩個(gè)參數(shù)。這些分別由 data 和 headers 參數(shù)表示。

headers 參數(shù)是一個(gè)函數(shù),它返回一個(gè)包含服務(wù)器響應(yīng)標(biāo)頭的對(duì)象。

剩下的代碼非常不言自明,因?yàn)槲覀冋谠O(shè)置 $scope.posts 數(shù)組的值。為了設(shè)置 $scope.previousPage 和 $scope.nextPage 變量的值,我們使用 x-wp-totalpages 屬性postHeaders 對(duì)象。

現(xiàn)在我們準(zhǔn)備使用指令的自定義模板在前端渲染這些數(shù)據(jù)。

為指令創(chuàng)建自定義模板

為了使我們的指令發(fā)揮作用,我們需要做的最后一件事是為帖子列表制作一個(gè)單獨(dú)的模板并將其鏈接到指令。為此,我們需要修改指令聲明并包含 templateUrl 屬性,如下所示:

/**  * Creating a custom directive for posts listing  */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) {     return {         restrict: 'E',         scope: {             postArgs: '='         },         templateUrl: 'views/directive-post-listing.html',         link: function( $scope, $elem, $attr ) {                  }     }; }] ); 

上面代碼中的 templateUrl 屬性引用了 views 目錄中名為 directive-post-listing.html 的文件。因此,在 views 文件夾中創(chuàng)建此文件并粘貼以下 HTML 代碼:

<!-- post listing starts --> <article class="post-entry"><h2 class="post-title"><a href="post-single.html">Good design is a lot like clear thinking made visual.</a></h2>     <figure class="post-thumbnail">         @@##@@     </figure><p class="post-meta">         By <a href="author.html">Bilal Shahid</a> in <a href="category.html">Quotes</a>     </p>     <div class="post-content">         <p>Created days forth. Dominion. Subdue very hath spirit us sixth fish creepeth also. First meat one forth above. You'll Fill for. Can't evening one lights won't. Great of make firmament image. Life his beginning blessed lesser meat spirit blessed seas created green great beginning can't doesn't void moving. Subdue evening make spirit lesser greater all living green firmament winged saw tree one divide wherein divided shall dry very lesser saw, earth the. Light their the.</p>     </div> </article><!-- post listing ends --><!-- pagination links start --><div class="post-pagination">     <a href="#" class="button">Older Posts</a>     <a href="#" class="button">Newer Posts</a> </div>		 <!-- pagination links end --> 

這是非常基本的 HTML 代碼,表示單個(gè)帖子條目和帖子分頁。我已從 views/listing.html 文件中復(fù)制了它。我們將使用一些 AngularJS 指令,包括 ng-repeat、ng-href、ng-src 和 ng -bind-html,顯示當(dāng)前駐留在指令的 $scope 屬性中的數(shù)據(jù)。

將 HTML 代碼修改為以下內(nèi)容:

<!-- post listing starts --> <article class="post-entry" ng-repeat="post in posts"><h2 class="post-title"><a ng-href="#/posts/{{post.slug}}">{{post.title.rendered}}</a></h2>     <figure class="post-thumbnail" ng-show="post.quiescent_featured_image">         @@##@@     </figure><p class="post-meta">         By <a ng-href="#/users/{{post.author}}">{{post.quiescent_author_name}}</a>          in <a ng-href="#/categories/{{category.term_id}}" ng-repeat="category in post.quiescent_categories">{{category.name}}{{$last ? '' : ',?'}}</a>     </p>     <div class="post-content" ng-bind-html="post.excerpt.rendered"></div>     </article><!-- post listing ends -->

上面的代碼使用 ng-repeat 指令來迭代 $scope.posts 數(shù)組。指令聲明中 $scope 對(duì)象上定義的任何屬性都可以直接在模板中使用。因此,我們?cè)谀0逯袑?$scope.posts 數(shù)組直接引用為 posts 。

通過使用 ng-repeat 指令,我們確保 article.post-entry 容器將在 中的每個(gè)帖子中重復(fù)posts 數(shù)組,每個(gè)帖子在內(nèi)循環(huán)中被稱為 post 。這個(gè) post 對(duì)象包含服務(wù)器返回的 JSON 格式的數(shù)據(jù),包含帖子標(biāo)題、帖子 ID、帖子內(nèi)容和特色圖像鏈接等屬性,這是同伴添加的附加字段插件。

在下一步中,我們將帖子標(biāo)題、帖子鏈接和特色圖像鏈接等值替換為 post 對(duì)象中的屬性。

對(duì)于分頁,將之前的代碼替換為以下代碼:

<!-- pagination links start --> <div class="post-pagination">     <a ng-href="#{{routeContext}}?page={{nextPage}}" class="button" ng-class="{'disabled': !nextPage}">Newer Posts</a>     <a ng-href="#{{routeContext}}?page={{previousPage}}" class="button" ng-class="{'disabled': !previousPage}">Older Posts</a> </div>		 <!-- pagination links end --> 

我們首先訪問我們?cè)谥噶盥暶髦卸x的 routeContext 屬性,并使用 ?page= 參數(shù)作為后綴,并使用 nextPage 和 previousPage 變量用于在帖子之間來回導(dǎo)航。我們還檢查下一頁或上一頁鏈接是否不是 null,否則我們將 .disabled 類添加到 Zurb Foundation 提供的按鈕。

現(xiàn)在我們已經(jīng)完成了該指令,是時(shí)候?qū)ζ溥M(jìn)行測(cè)試了。我們通過在 HTML 中放置一個(gè) <post-listing></post-listing> 標(biāo)簽來實(shí)現(xiàn)這一點(diǎn),最好位于

的上方標(biāo)簽。這樣做意味著帖子列表將出現(xiàn)在頁腳上方。不要擔(dān)心格式和樣式,我們將在本系列的下一部分中處理它們。

這就是為帖子列表功能創(chuàng)建自定義 AngularJS 指令的過程。

接下來會(huì)發(fā)生什么?

在有關(guān)使用 WP REST API 和 AngularJS 創(chuàng)建前端的系列的當(dāng)前部分中,我們?yōu)樘恿斜砉δ軜?gòu)建了一個(gè)自定義 AngularJS 指令。該指令使用我們?cè)诒鞠盗星懊娌糠謩?chuàng)建的 Posts 服務(wù)。該指令還以 HTML 屬性和 URL 參數(shù)的形式獲取用戶輸入。

在本系列的最后部分,我們將開始研究項(xiàng)目的最后一部分,即帖子、用戶和類別的控制器及其各自的模板。

Creating a Custom Directive for WordPress Post Listing on the Front EndCreating a Custom Directive for WordPress Post Listing on the Front End

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊9 分享