怎么將圖片上傳封裝成指令?

一、背景介紹

如果我們想實現圖片上傳功能,其中需要包含以下功能
*點擊按鈕上傳圖片
*圖片能在本地預覽
*顯示圖片信息,顯示上傳進度
*點擊上傳按鈕上傳到服務器
*點擊刪除按鈕,刪除。
*上傳按鈕只能按一次
現在我們需要把它用directive自定義指令封裝起來。
為什么要封裝呢?這個圖片上傳插件如果需要多次運用的話,用自定義指令封裝后能減少大量代碼。

二、知識剖析

關于指令,網上有很多資料,這里就簡單說一下。
angular指令本質上就是AngularJs擴展具有自定義功能的html元素的途徑。
angular指令本質上就是AngularJs擴展具有自定義功能的html元素的途徑。
內置指令,打包在AngularJs內部的指令,所有內部指令的命名空間 都使用ng作為前綴,所以在寫自定義指令的時候,避免用ng作為指令命名的前綴。
創建指令的方式有四種,在指令里用 restrict屬性控制:
*E:元素
*A:屬性
*C:css類
*M:注釋
向指令中傳遞數據,用template屬性
directive 在使用隔離 scope 的時候,提供了三種方法同隔離之外的地方交互:
*@ 綁定一個局部 scope 屬性到當前 dom 節點的屬性值。結果總是一個字符串,因為 dom 屬性是字符串。
*= 通過 directive 的 attr 屬性的值在局部 scope 的屬性和父 scope 屬性名之間建立雙向綁定。
*& 提供一種方式執行一個表達式在父 scope 的上下文中。如果沒有指定 attr 名稱,則屬性名稱為相同的本地名稱。(其實說白了,就是可以使用在父scope中定義的函數。)
replace:是否用模板替換當前元素。
true : 將指令標簽替換成temple中定義的內容,頁面上不會再有標簽;
false :則append(追加)在當前元素上,即模板的內容包在標簽內部。默認false。

三、常見問題

如何實現封裝?

四、解決方案

見代碼

五、編碼實戰

//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">
                    <!--圖片預覽-->
                    <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>狀態</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的區別?當我們每次想要擴展個自定義指令時,應該用哪個?
簡單來說,優先使用link。事實上,這兩個都可以獲取到作用域,元素,屬性等引用,也都會執行一次。
控制器可以暴露一個API,而link可以通過require與其他的指令控制器交互。
所以如果要開放出一個API給其他指令用就寫在controller中,否則寫在link中。

七、更多討論

討論點一、去掉template頁中第7行的「ng-if="uploader"」,使用link就會報錯,使用controller則正常,這是為什么?
討論點二、如何上傳多張圖片?
討論點三、&方法該如何應用?

八、參考文獻

參考一:angular自定義指令詳解

參考二:Angular File Upload

參考三:angular-file-upload 中文API

參考四:ng指令中controller與link的區別

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。