在AngularJS中,操做DOM通常在指令中完成,那麼指令是如何實現的呢?
指令的做用是把咱們自定義的語義化標籤替換成瀏覽器可以認識的HTML標籤html
通常的事件監聽是在對靜態的dom綁定事件,而若是在指令中動態生成了DOM節點,動態生成的節點不會被JS事件監聽。這也是使用directive指令來處理的緣由。jquery
解決問題的開始先介紹下directive的幾個屬性瀏覽器
1.restrict
主要是定義directive自定義指令的方式,通常有如下幾種
E: 表示該directive僅能以element方式使用,即:<my-dialog></my-dialog>
A: 表示該directive僅能以attribute方式使用
EA: 表示該directiveapp
2.scope
寫上該屬性時,就表示這個directive不會從它的controller裏繼承$scope對象,而是會從新建立一個dom
3.link
link包含了三個屬性分別是scope,element,attrs
scope就至關於上文提到scope,實際上是同樣的
element就至關於jquery的獲取對象如$('my-dialog')
attra則是個類型map的數據類型,包括你加入指令那句html代碼的全部屬性。函數
<input type="file" id="photo_back" name="id_photo_back" ng-model="kycpeople.id_photo_back" custom-on-change="uploadFile"/> .directive('customOnChange',function(){ return { restrict:'A', link:function(scope,element,attrs){ var onChangeHandler = scope.$eval(attrs.customOnChange); element.bind('change',onChangeHandler); } }; });
如上所示,自定義一個custom-on-change的指令,restrict:'A'代表該指令是一個attribute,給指令添加一個名字做爲以後事件綁定觸發的函數,當directive被渲染後,input就被綁定了一個change事件,當元素的值被修改時,標籤input的customOnChange指令值uploadFile觸發事件
以下this
$scope.uploadFile = function (event) { var file = event.target.files[0]; $scope.file = file; };
以上代碼解決了angular圖片上傳過程圖片獲取的問題。url
那麼假設此時要實現多個圖片上傳且實時預覽,這時候要怎麼實現呢?雙向綁定
首先,先把業務處理封裝成service,以下rest
angular.module('app').service('foo', function ($translate) { this.getPrivate = function (tmp) { . // 獲取文件對象 var file = event.target.files[0]; return file; }; this.getimgname = function (tmp) { // 獲取圖片名稱 var filename = event.target.files[0].name; return filename; }; this.getimgurl = function (filename,callback) { // 獲取圖片並預覽 if(filename==null) { return; } var tmp = new FileReader(); tmp.onload = function (ev) { //調用回調函數 callback(ev.target.result); }; tmp.readAsDataURL(filename); }; });
接下來是在建立的控制器裏面加入service的依賴,並使用這個service中的函數
angular.module('app').controller('kycForPersoncontroller', function (foo,$scope,$http) { $scope.uploadFile = function (event) { $scope.file = foo.getPrivate(event); $scope.uploadimg=foo.getimgname(event); foo.getimgurl($scope.file,function (result) { $scope.img = result; console.log($scope.img); }); };
到這裏我遇到一個問題阻塞個人思路,就是進入service的getimgurl函數時裏面有一個我本身的定義的回調函數callback(ev.target.result),添加圖片後這個回調函數返回的result值便是上傳圖片成功後的base64值,用控制檯可以打印出來,可是視圖卻沒顯示出來,這是爲何?
<img src={{imgback}}></img>
數據綁定好了,圖片怎麼顯示不出來,angular所謂的雙向綁定不是有任何數據發生了變化,view會跟着改變,scope模型會自動地更新嗎?
這是由於回調函數中,angular並不知道你修改了什麼。就像你使用setTimeout()來更新一個scope model,它並不知道你更新什麼。這種狀況下,調用$apply()就是你的責任了(如上),它會自動觸發$rootScope.$digest(),從而讓watchers被觸發用以更新view,才能作到手動更新model,view視圖也會隨之顯示。
正確的寫法
$scope.uploadFile = function (event) { $scope.file = foo.getPrivate(event); $scope.uploadimg=foo.getimgname(event); foo.getimgurl($scope.file,function (result) { $scope.$apply(function () { $scope.img = result; }); }); };
最後作下總結,AngularJS是否能檢測到你對於model的修改。若是它不能檢測到,那麼你就須要手動地調用$apply()。
文章記錄自:
http://www.jianshu.com/p/0d3652a5db21