AngularJS接收PHP變量數據
理想情況下,AngularJS處理的數據都是通過異步請求獲取的,但有些情況下,由于開發環境的限制,只允許頁面部分使用AngularJS。這類頁面中的數據分為兩種,一種是用于初始化頁面的數據,一種是用于更新頁面的數據。其中用于初始化的數據會決定頁面初始化時的內容,如果這類數據也用異步請求獲取,那么頁面在呈現出來的時候可能是空白或錯亂的。
注:理想狀態指全站使用AngularJS,就算這種情況下,通過異步請求初始化數據也會造成頁面在一開始空白或錯亂,但我們監測$rootScope上的加載完成事件或監測$routeProvider的promise狀態來判斷是否初始化完成,在未完成前可以通過不顯示頁面或者給出一個loading的畫面,來掩蓋錯亂的頁面。但這些措施在局部使用AngularJS時是不太可能有效的,所以下面要講訴的是妥協于非理想情況的解決方法。
</blockquote>通常這類頁面在生成之前,后臺就會初始化主要的數據,我們完全可以把這些后臺數據利用起來,而不必再去發起異步請求。
以常見的PHP后臺為應用場景,PHP生成頁面前便會處理用戶數據,用戶數據中包含了用戶權限,用戶名,用戶關注等等數據,這些數據在頁面中也會被用到,比如用來決定用戶面板的顯隱:
// 假設%%為PHP模板輸出語法 // 假設PHP的$member變量存儲用戶數據% if !empty($member) % <ul class="user-panel"> <li>% $member.username %</li>
% if $member[authority] > 1000 % <li>后臺管理</li> % /if % <li>退出</li>
</ul> % /if %</pre>
假設AngularJS中也用到用戶數據,用于處理回復框的可輸入狀態,如果用戶沒有權限則不允許輸入:// $scope.memberData此時為undefined <div class="reply-box"> <textarea ng-disabled="memberData.authority > 1000"></textarea> </div>
輸入框是否可輸入由memberData.authority決定,但memberData還沒有初始化,所以我們先用后臺數據初始化memberData。
ng-init初始化后臺數據
通過ng-init指令在行內初始化AngularJS作用域:
<div class="reply-box" ng-init="memberData = % json_encode($member) %"> <textarea ng-disabled="memberData.authority > 1000"></textarea> </div>
上述調用PHP的json_encode函數將$member轉換為JSON格式并輸出到頁面中,頁面渲染結束后,AngularJS對該頁面進行二次解析,在這過程中將這段JSON數據解析并賦值到$scope.memberData中。
但實際開發中,上面的寫法會導致HTML的解析錯誤,因為JSON數據的格式是:
{"username": "lxjwlt", "authority": 9999}JSON中帶有雙引號,也可能包含HTML語句,所以直接在HTML中打印出這類JSON要注意將引號和HTML特殊符號都進行HEX編碼,PHP中的json_encode可以傳入第二個參數,用于設置特殊字符的編碼方式:
// JSON_HEX_TAG: 將 < 和 > 等符號編碼為 \u003C 和 \u003E // JSON_HEX_APOS: 將單引號轉換為 \u0027 // JSON_HEX_QUOT: 將雙引號轉換為 \u0022<div class="reply-box" ng-init="memberData = % json_encode($member, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT) %"> // ... </div></pre>
這種寫法有兩點不足: * 寫在行內,要考慮引號等特殊符號的編碼 * 公共數據不通用,如果頁面中多處用到用戶數據,那么就要多次初始化用戶數據 * 數據初始化遍布頁面各個地方,不利于管理
module.value全局數據存儲
在AngularJS中,我們可以通過module.value來定義全局公用數據:
// 初始化angular應用 var app = angular.module('myApp', []);// 全局數據 app.value('myData', { key_1: 'value_1', key_2: 'value_2' });</pre>
利用AngularJS這一特性,我們可以將后臺數據存儲到AngularJS中的全局變量中:<body ng-app="myData"> <script> angular.module('myData') .value('memberData', % json_encode($member) %); </script>// ...
</body></pre>
PHP模板會執行json_encode將$member數據打印到script標簽中,而這段JSON數據在script標簽中被當作是JS對象來對待,于是在AngularJS對頁面的第二次解析時,直接將這段JS對象存入到全局變量memberData中。
于是,在我們在編寫myApp模塊時,可以在任意的控制器中獲取這段全局數據 -- memberData:
angular.module('myApp')// 依賴注入memberData .controller('MyCtrl', function(memberData) { // 要在作用域中使用memberData,先賦值給$scope $scope.memberData = memberData; });</pre><br />
這樣我們就能夠使用用戶數據:
<div class="reply-box"> <textarea ng-disabled="memberData.authority > 1000"></textarea> </div>
通過全局數據的方式,我們不再需要ng-init指令來初始化數據,也不用再考慮特殊符號的編碼轉換問題,而且這段數據可以全局復用。
總結
采用以上的方法,在AngularJS內部,我們能夠獲取任意后臺數據,而我們只需花費數據解析的時間,從而節省下異步請求和第二次后臺運行邏輯代碼的時間。
參考