在一個web項目中,不能保證只使用一種JavaScript框架,一種常見的情況是同時使用了jQuery和AngularJS框架進行開發;另一種常見的情況是,現需要對之前完全以jQuery為框架開發的項目擴展功能,為了方便需要使用AngularJS。這兩種情況都存在一個不同框架間互相通信的問題。使用以下三種AngularJS方法,如表-1所示,可以較好的解決這一問題:

表-1 AngularJS方法
有兩點需要特別說明一下:
這里的handler是一個接收兩個參數的函數,兩個參數分別為被監聽數據改變前的值和被監聽數據改變后的值,形式如下:
var handler = function(newVal, oldVal) {
//some action
};這里的expression有兩種情況,一種情況是字符串,此時被監聽的數據為$scope[expression];另一種情況是一個帶有返回值的函數,此時被監聽的數據為函數的返回值。一般來說,如果要監聽AngularJS自定義service上用于在不同controller間共享的數據時(關于在不同controller間共享數據這部分內容,請參考這里),必須使用上述提到的第二種情況,即expression為一個帶有返回值的函數,如:
$scope.$watchCollection(function() {
return DatashareService.detailInfo;
}, function(newObj, oldObj) {
//some action
});下面提供一個多JavaScript框架協同使用的例子,在該例中,同時使用了jQuery UI和AngularJS。通過AngularJS控制jQuery UI的button是否可以被點擊,通過點擊jQuery UI的button,在AngularJS中動態顯示button點擊量,頁面效果如圖1 ~ 圖3所示:

圖-1 按鈕處于可點擊狀態

圖-2 按鈕處于不可點狀態

圖-3 點擊按鈕后,點擊量增加
下面分別貼出HTML和JavaScript代碼,重要部分以注釋形式進行解釋:
index.html文件:
<!DOCTYPE html>
<html ng-app="exampleApp" ng-cloak>
<head>
<meta charset="utf-8">
<title>jQuery UI & AngularJS</title>
<link rel="stylesheet" href="css/bootstrap.min.css" />
<link rel="stylesheet" href="css/bootstrap-responsive.min.css" />
<link rel="stylesheet" href="lib/jquery-ui-1.11.4/jquery-ui.min.css" />
</head>
<body>
<!-- 此div的id后面需要用到 -->
<div id="angularRegion" class="well" ng-controller="simpleCtrl">
<h5>AngularJS</h5>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="buttonEnabled"> Enable Button
</label>
</div>
Click counter: {{ clickCounter }}
</div>
<div id="jqui" class="well">
<h5>jQuery UI</h5>
<button>Click Me!</button>
</div>
<script src="lib/jquery-ui-1.11.4/external/jquery/jquery.js"></script>
<script src="lib/jquery-ui-1.11.4/jquery-ui.min.js"></script>
<script src="lib/angular.js"></script>
<!-- 該js文件為本例主要js代碼,該文件中的代碼在下方提供 -->
<script src="main.js"></script>
</body>
</html>main.js文件:
/**
* jQuery UI代碼
*/
$(function() {
// .button()為jQuery UI裝飾button元素的代碼,無需深究
$('#jqui button').button().click(function(e) {
// 使用AngularJS自帶元素選擇器,angularRegion為HTML元素的id屬性,注意這里不能用引號將其引起來
// .scope()可以選擇當前元素所在的controller中的$scope對象
// 即 angular.element(angularRegion).scope() === AngularJS代碼中的$scope
// 能取到$scope對象是其他框架與AngularJS交互***最重要***的一點
// 如果直接 ....scope().handleClick(),則$scope.handlerClick函數也會執行,但view不會刷新
angular.element(angularRegion).scope().$apply('handleClick()');
// 使用jQuery元素選擇器
// $('#angularRegion').scope().$apply('handleClick()');
// $apply()中直接使用表達式,可以這么做,但并不建議
// angular.element(angularRegion).scope().$apply('clickCounter = clickCount + 1');
});
});
/**
* AngularJS代碼
*/
var app = angular.module("exampleApp", []);
app.controller("simpleCtrl", function($scope, $log) {
$scope.buttonEnabled = true; // 標識按鈕是否可以點擊
$scope.clickCounter = 0; // 點擊量計數器
$scope.handleClick = function() { // 遞增按鈕點擊量
$scope.clickCounter++;
$log.info("Click Counter Increase, Now clickCounter = ", $scope.clickCounter);
}
// 監聽$scope.buttonEnabled變量,不可使用$scope.buttonEnabled
$scope.$watch('buttonEnabled', function(newVal) {
$('#jqui button').button({
disabled: !newVal
});
});
// 監控對象,可以使用這種方法代替直接監聽$scope.buttonEnabled變量
// $scope.settings = {
// buttonEnabled: true
// };
// $scope.$watchCollection('settings', function(newObj, oldObj) {
// $('#jqui button').button({
// disabled: !newObj.buttonEnabled
// });
// });
});在main.js中我們注釋掉了很多代碼,這些代碼可以實現與其上方代碼相同的功能,有興趣的讀者可以自己試一下。如果需要監控對象,則index.html中也需修改,將
<input type="checkbox" ng-model="buttonEnabled"> Enable Button
修改為
<input type="checkbox" ng-model="settings.buttonEnabled"> Enable Button
相信對AngularJS雙向綁定有了解的讀者對此一定不陌生。
只要會用這三個方法,在jQuery UI等框架中與AngularJS進行通信問題也就迎刃而解了。
完。
參考資料:
《Pro AngularJS》 作者:Adam Freeman
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。