詳解angularJs中自定義directive的數(shù)據(jù)交互
就我對directive的粗淺理解,它一般用于獨立Dom元素的封裝,應用場合為控件重用和邏輯模塊分離。后者我暫時沒接觸,但數(shù)據(jù)交互部分卻是一樣的。所以舉幾個前者的例子,以備以后忘記。
directive本身的作用域$scope可以選擇是否封閉,不封閉則和其controller共用一個作用域$scope。例子如下:
<body ng-app="myApp" ng-controller="myCtrl"> <test-directive></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ $scope.data = { name:"白衣如花" }; }) .directive("testDirective",function(){ return { restrict:"E", template:"<h1>{{data.name||'未定義'}}</h1>" } }); </script> </body>
顯示結(jié)果為:白衣如花,可以知道directive中的data.name就是myCtrl控制器中的$scope.data.name。
那么封閉的directive呢?怎么封閉,封閉效果是什么樣的,封閉后怎么數(shù)據(jù)交互?這些都是我這幾天摸索的東西。
<body ng-app="myApp" ng-controller="myCtrl"> <test-directive></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ $scope.data = { name:"白衣如花" }; }) .directive("testDirective",function(){ return { restrict:"E", scope: {}, template:"<h1>{{data.name||'未定義'}}</h1>" } }); </script> </body>
結(jié)果顯示為:未定義。所以在directive定義時,添加屬性scope就可以把directive的作用域和父控制器的作用域分離開來。
好,了解了開放和封閉之后,進入主題,如何進行數(shù)據(jù)交互。個人覺得數(shù)據(jù)交互分為:父控制器獲取directive的變量;directive獲取父控制器的變量;父控制器調(diào)用directive的函數(shù);directive調(diào)用父控制器的函數(shù)。
1.父控制器獲取directive的變量。比如封裝了一個輸入框接受用戶輸入,父控制器點擊搜索按鈕要獲取用戶輸入:
<body ng-app="myApp" ng-controller="myCtrl"> <p>名字:{{outerName}}</p> <test-directive inner-name="outerName"></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ }) .directive("testDirective",function(){ return { restrict:"E", scope: { innerName: "=" }, template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>" } }); </script> </body>
顯示結(jié)果如下:
分析:從數(shù)據(jù)流向說起,testDirective中的一個input輸入綁定在innerName中,innerName是directive私有作用域擁有的變量,外部控制器不能直接用。通過innerName: "="傳遞給html中的inner-name屬性,
而inner-name屬性則綁定在外部控制器的outerName變量中,所以最后顯示在最上面的<p>標簽內(nèi)。上述代碼等價于如下代碼:
<test-directive name="outerName"></test-directive> scope: { innerName: "=name" },
由inerName: "="變成了innerName: "=name",而html屬性綁定也由inner-name變成了name。
2.directive獲取父控制器的變量。這個應用場合應該挺多的,比如公共的頁眉頁腳,公共的展示面板等。
這個用上面例子的"="一樣可以實現(xiàn),于是我們知道了"="是雙向綁定。但是我們要防止directive內(nèi)部意外修改數(shù)據(jù)該怎么辦呢?于是單向綁定"@"就出場了。
<body ng-app="myApp" ng-controller="myCtrl"> <input type='text' ng-model='outerName' placeholder='白衣如花'> <test-directive inner-name="{{outerName}}"></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ }) .directive("testDirective",function(){ return { restrict:"E", scope: { innerName: "@" }, template:"<p>名字:{{innerName}}</p>" + "<button ng-click='innerName=innerName+1'>點擊</button>" } }); </script> </body>
值得注意的是:@在html的屬性綁定時需要{{}}開標識,而=則不用。我的理解是,對于父控制器而言,@是數(shù)據(jù)傳遞,而=是數(shù)據(jù)綁定,所以有這些區(qū)別。directive中加入了一個按鈕用于驗證修改數(shù)據(jù)后
父控制器是否發(fā)生改變,結(jié)果是=有變化,@無變化,很容易得出結(jié)論:=是雙向綁定,@是雙向綁定。
3.directive調(diào)用父控制器的函數(shù)。應用場合,暫時想不到(汗)。
變量用=和@來傳遞,函數(shù)則用&。例子如下:
<body ng-app="myApp" ng-controller="myCtrl"> <p>名字:{{outerName}}</p> <test-directive on-click="click(name)"></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ $scope.click = function (name) { $scope.outerName = name || "白衣如花"; } }) .directive("testDirective",function(){ return { restrict:"E", scope: { onClick: "&" }, template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>" + "<button ng-click='onClick({name: innerName})'>點擊</button>" } }); </script> </body>
數(shù)據(jù)傳遞流程和之上的例子差不多,唯一要注意的是參數(shù)傳遞時,{name: innerName}前者是形參,后者是實參。多個參數(shù)時,參數(shù)順序不重要,形參一一對應。
4.父控制器調(diào)用directive的函數(shù)。這個是前段時間遇到的難點,情況較其他復雜一些。應用場合也很普遍,比如初始化,重置等。
<body ng-app="myApp" ng-controller="myCtrl"> <button ng-click="click()">重置</button> <test-directive action="action"></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ $scope.action = {}; $scope.click = function () { $scope.action.reset(); } }) .directive("testDirective",function(){ return { restrict:"E", scope: { action: "=" }, template:"<input type='text' ng-model='name' placeholder='白衣如花'>", controller: function ($scope) { $scope.action.reset = function () { $scope.name = "白衣如花" } } } }); </script> </body>
又一次用到了=,利用了js中函數(shù)也是屬性的原理。似乎,理解了=的雙向綁定,就很容易調(diào)用directive內(nèi)部函數(shù)了。但是初始化呢?
首先想到的是類似的=來引用傳遞:
<body ng-app="myApp" ng-controller="myCtrl"> <test-directive action="action"></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ $scope.action = {}; $scope.action.init(); }) .directive("testDirective",function(){ return { restrict:"E", scope: { action: "=" }, template:"<input type='text' ng-model='name' placeholder='白衣如花'>", controller: function ($scope) { $scope.action.init = function () { $scope.name = "白衣如花" } } } }); </script> </body>
但是運行卻發(fā)現(xiàn),錯誤顯示$scope.action.init is not a function,看提示應該是運行到第7行的時候,$scope.action.init函數(shù)還未定義。怎么辦呢?把directive提到controller之前試試?一樣是錯誤。
嗯,可以不用函數(shù),直接在directive的controller中執(zhí)行$scope.name = "白衣如花",似乎很完美,但如果是有參數(shù)的初始化呢?事實上js分離后,我遇到的問題是根據(jù)http請求的返回結(jié)果來初始化directive,由于
網(wǎng)絡(luò)快慢不一定,導致控件初始化時不一定有http請求的返回(沒有有效的初始化參數(shù)),也不能保證http請求返回后directive已經(jīng)初始化(不能用=來進行函數(shù)調(diào)用)。
需求很明了了,如果能監(jiān)控參數(shù)變化,再執(zhí)行初始化,此時能保證directive已經(jīng)加載,而且有有效的參數(shù)。正好angularjs提供了$watch。代碼如下:
<body ng-app="myApp" ng-controller="myCtrl"> <test-directive action="action"></test-directive> <script> angular.module("myApp",[]) .controller("myCtrl",function($scope){ $scope.action = {name: "白衣如花"}; }) .directive("testDirective",function(){ return { restrict:"E", scope: { action: "=" }, template:"<input type='text' ng-model='name' placeholder='白衣如花'>", link: function (scope, elem, attrs) { scope.$watch(attrs.action, function (value) { scope.action.init(); }) }, controller: function ($scope) { $scope.action.init = function () { $scope.name = $scope.action.name } } } }); </script> </body>
這是我對于directive數(shù)據(jù)交互的粗淺理解。想要更詳細了解,請參看官方文檔:https://docs.angularjs.org/guide/directive
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- AngularJS實現(xiàn)分頁顯示數(shù)據(jù)庫信息
- Angular.JS內(nèi)置服務$http對數(shù)據(jù)庫的增刪改使用教程
- 三種AngularJS中獲取數(shù)據(jù)源的方式
- AngularJS實現(xiàn)數(shù)據(jù)列表的增加、刪除和上移下移等功能實例
- 基于AngularJS實現(xiàn)頁面滾動到底自動加載數(shù)據(jù)的功能
- Angularjs實現(xiàn)多個頁面共享數(shù)據(jù)的方式
- Angular.js如何從PHP讀取后臺數(shù)據(jù)
- Angularjs 滾動加載更多數(shù)據(jù)
- 深入學習AngularJS中數(shù)據(jù)的雙向綁定機制
- 在 Angular6 中使用 HTTP 請求服務端數(shù)據(jù)的步驟詳解
- Angular.JS讀取數(shù)據(jù)庫數(shù)據(jù)調(diào)用完整實例
相關(guān)文章
AngularJS入門教程之與服務器(Ajax)交互操作示例【附完整demo源碼下載】
這篇文章主要介紹了AngularJS與服務器Ajax交互操作的方法,可實現(xiàn)post傳輸數(shù)據(jù)的功能,并附帶完整的demo源碼供讀者下載參考,源碼中還包含了前面章節(jié)的示例文件,需要的朋友可以參考下2016-11-11AngularJS 路由和模板實例及路由地址簡化方法(必看)
下面小編就為大家?guī)硪黄狝ngularJS 路由和模板實例及路由地址簡化方法(必看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06詳解為生產(chǎn)環(huán)境編譯Angular2應用的方法
這篇文章主要介紹了詳解為生產(chǎn)環(huán)境編譯Angular2應用的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12詳解Angular Forms中自定義ngModel綁定值的方式
在Angular應用中有兩種方式來實現(xiàn)表單綁定,但是對于一些特殊的表單控件沒法實現(xiàn),這篇文章主要介紹了詳解Angular Forms中自定義ngModel綁定值的方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12