一吮成、背景介紹
如果我們想實現(xiàn)圖片上傳功能,其中需要包含以下功能
*點擊按鈕上傳圖片
*圖片能在本地預(yù)覽
*顯示圖片信息辜梳,顯示上傳進度
*點擊上傳按鈕上傳到服務(wù)器
*點擊刪除按鈕粱甫,刪除。
*上傳按鈕只能按一次
現(xiàn)在我們需要把它用directive自定義指令封裝起來作瞄。
為什么要封裝呢茶宵?這個圖片上傳插件如果需要多次運用的話,用自定義指令封裝后能減少大量代碼宗挥。
二节预、知識剖析
關(guān)于指令,網(wǎng)上有很多資料属韧,這里就簡單說一下安拟。
angular指令本質(zhì)上就是AngularJs擴展具有自定義功能的html元素的途徑。
angular指令本質(zhì)上就是AngularJs擴展具有自定義功能的html元素的途徑宵喂。
內(nèi)置指令糠赦,打包在AngularJs內(nèi)部的指令,所有內(nèi)部指令的命名空間 都使用ng作為前綴锅棕,所以在寫自定義指令的時候拙泽,避免用ng作為指令命名的前綴。
創(chuàng)建指令的方式有四種裸燎,在指令里用 restrict屬性控制:
*E:元素
*A:屬性
*C:css類
*M:注釋
向指令中傳遞數(shù)據(jù)顾瞻,用template屬性
directive 在使用隔離 scope 的時候,提供了三種方法同隔離之外的地方交互:
*@ 綁定一個局部 scope 屬性到當前 dom 節(jié)點的屬性值德绿。結(jié)果總是一個字符串荷荤,因為 dom 屬性是字符串退渗。
*= 通過 directive 的 attr 屬性的值在局部 scope 的屬性和父 scope 屬性名之間建立雙向綁定。
*& 提供一種方式執(zhí)行一個表達式在父 scope 的上下文中蕴纳。如果沒有指定 attr 名稱会油,則屬性名稱為相同的本地名稱。(其實說白了古毛,就是可以使用在父scope中定義的函數(shù)翻翩。)
replace:是否用模板替換當前元素。
true : 將指令標簽替換成temple中定義的內(nèi)容,頁面上不會再有標簽稻薇;
false :則append(追加)在當前元素上嫂冻,即模板的內(nèi)容包在標簽內(nèi)部。默認false塞椎。
三絮吵、常見問題
如何實現(xiàn)封裝?
四忱屑、解決方案
見代碼
五蹬敲、編碼實戰(zhàn)
//template
<form name="myForm" class="col-lg-10">
<div class="row">
<div class="col-lg-10 col-sm-12">
<div class="row">
<label class="col-md-2 col-sm-12 titles">{{labelName}}</label>
<div class="col-lg-12" ng-if="uploader">
<label class="btn-pic" for="{{imgId}}" style="float:left;">
選擇文件
</label>
<input type="file" accept="image/*"
name="file" id="{{imgId}}"
style="display: none;"
nv-file-select=""
uploader="uploader"
multiple="">
<label style="line-height:.3rem;">(圖片最大為1m)</label>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<!--圖片預(yù)覽-->
<img style="max-width: 100%;" ng-src="{{imageUrl}}">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-10">
<!-----上傳圖片插件----->
<table class="table">
<thead>
<tr>
<th>圖片名</th>
<th>文件大小</th>
<th>進度</th>
<th>狀態(tài)</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in uploader.queue">
<td style="word-break:break-all">
<strong>{{ item.file.name }}</strong>
</td>
<td nowrap>{{ item.file.size/1024/1024|number:2 }} MB</td>
<td>
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar"
ng-style="{ 'width': item.progress + '%' }"></div>
</div>
</td>
<td class="text-center">
<span ng-show="item.isSuccess"><i class="glyphicon glyphicon-ok"></i></span>
<span ng-show="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span>
<span ng-show="item.isError"><i class="glyphicon glyphicon-remove"></i></span>
</td>
<td>
<button type="button" class="btn btn-success btn-xs" ng-click="item.upload()"
ng-disabled="item.isReady || item.isUploading || item.isSuccess">
<span class="glyphicon glyphicon-upload"></span> Upload
</button>
<button type="button" class="btn btn-warning btn-xs" ng-click="item.cancel()"
ng-disabled="!item.isUploading">
<span class="glyphicon glyphicon-ban-circle"></span> Cancel
</button>
<button type="button" class="btn btn-danger btn-xs" ng-click="item.remove()">
<span class="glyphicon glyphicon-trash"></span> Remove
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
//directive
angular.module("myApp")
.directive("uploadFile", function (FileUploader) {
return {
restrict: "EA",
templateUrl: "html/fileUpload.html",
scope: {
labelName:"@",
imageUrl:"=ngModel",
imgId:"@"
},
replace: true,
link: function (scope,ele,attrs) {
// 上傳圖片插件
scope.uploader = new FileUploader({
url: "/carrots-admin-ajax/a/u/img/task",
queueLimit: 1
});
scope.uploader.onSuccessItem = function (fileItem, response,status,headers) {
scope.imageUrl = response.data.url;
};
}
//link或者controller都可以達到效果
// controller:function ($scope) {
// // 上傳圖片插件
// $scope.uploader = new FileUploader({
// url: "/carrots-admin-ajax/a/u/img/task",
// queueLimit: 1
// });
// $scope.uploader.onSuccessItem = function (fileItem, response,status,headers) {
// $scope.imageUrl = response.data.url;
// };
// }
}
});
//html
<upload-file ng-model="params.img" img-id="img" label-name="article圖片"></upload-file>
六、擴展思考
指令中controller跟link的區(qū)別?當我們每次想要擴展個自定義指令時莺戒,應(yīng)該用哪個伴嗡?
簡單來說,優(yōu)先使用link从铲。事實上瘪校,這兩個都可以獲取到作用域,元素名段,屬性等引用阱扬,也都會執(zhí)行一次。
控制器可以暴露一個API伸辟,而link可以通過require與其他的指令控制器交互麻惶。
所以如果要開放出一個API給其他指令用就寫在controller中,否則寫在link中信夫。
七窃蹋、更多討論
討論點一、去掉template頁中第7行的「ng-if="uploader"」静稻,使用link就會報錯警没,使用controller則正常,這是為什么振湾?
討論點二杀迹、如何上傳多張圖片?
討論點三押搪、&方法該如何應(yīng)用树酪?
八浅碾、參考文獻
參考一:angular自定義指令詳解