在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