vue多文件上傳進度條 進度不更新問題

轉自 hhttp://www.cnblogs.com/muge10/p/6767493.htmlhtml

感謝這位兄弟的文章,以前由於這個問題 ,我連續在sgmentflow上提問過屢次,徹底沒人能回答。謝謝這篇文章數組

 

最近在作一個多圖片上傳的組件,需求是作到多文件依次上傳,並顯示上傳進度條。app

邏輯部分實現了之後,在更新進度條視圖的時候出現一點問題:動態計算生產的進度 progress 屬性不會自動更新。函數

原來的代碼是這樣寫的:this

複製代碼
let files = this.filePicker.files;
if(!files.length) {
    return;
}

let arr = [];
for(let i = 0, len = files.length; i < len; i++) {
    let item = files[i];
    // 每一個文件初始進度爲0
    item.progress = '0';

    arr.push(obj);
}

this.fileArr = arr;
複製代碼

這裏直接將 file 對象添加一個 progress 屬性記錄上傳進度,並初始化爲0,而後上傳時候實時計算更新 progress。但奇怪的是這個 progress 在視圖裏並不會自動更新,巋然不動,一直都是0。還了N中辦法,百思不得其解。spa

 

後來一怒之下作了一個小 demo,看看問題到底出如今哪裏,把不想關的代碼都剔除,只保留核心代碼,並用最簡單的數據來模擬一下。代碼以下:prototype

複製代碼
// 用數組模擬 files, 用對象模擬 file 對象
let files = [];
for(let i = 0, len = 5; i < len; i++) {
    let obj = {name: 'name_' + 1};

    files.push(obj);
}

let arr = [];
for(let i = 0, len = files.length; i < len; i++) {
    files[i].progress = '0';
    arr.push(files[i]);
}
複製代碼

這裏僅僅是把 files 對象換成了數組來模擬,把 file 對象換成了普通對象模擬。code

神奇的是,這樣竟然就自動更新了。htm

因爲文件 file 後來都保存在數組裏,這說明惟一的區別就在 file 對象上面!因而打算用普通對象保存 file 對象的屬性再試試。對象

複製代碼
let files = this.filePicker.files;
if(!files.length) {
    return;
}


let arr = [];
for(let i = 0, len = files.length; i < len; i++) {
    let item = files[i];
    let obj = {};

    obj.name = item.name;
    obj.size = item.size;

    obj.progress = '0';

    arr.push(obj);
}
複製代碼

這樣視圖也是能夠自動更新的,果真是 file 對象和普通對象的區別。

 

它們到底是什麼區別呢?看一下他們的類型先。

複製代碼
console.log('files type', Object.prototype.toString.call(files));
// files type [object FileList]
console.log('arr   type', Object.prototype.toString.call(arr));
// arr   type [object Array]

console.log('item type', Object.prototype.toString.call (files[0]));
// item type [object File]
console.log('obj  type', Object.prototype.toString.call (obj));
// obj  type [object Object]
複製代碼

原來 files 是 FileList 類型,file 是 File 類型。而普通的 obj 是 Object 類型。

Vue 的數據更新利用的是 Object.defineProperty 的 getter setter 函數來實現的,而 Vue 默認沒有對 File 對象設置 getter setter, 所以用 File 對象不會自動更新。

解決辦法,就是用普通對象保存 file 對象裏須要的信息,而後用來構造視圖數據。或者本身手動設置 File 對象的 setter,也能夠自動更新。代碼以下:

複製代碼
<div id="app">
    <input type="text" id='a'>
    <span id='b'></span>

    <input type="file" id='file'>
    <button type="button" id='button'>點擊更改file屬性</button>
</div>

<script>
    // 普通對象設置 setter
    var obj = {};
    Object.defineProperty(obj, 'hello', {
        set: function(newVal) {
            document.getElementById('a').value = newVal;
            document.getElementById('b').innerHTML = newVal;
        }
    });

    document.addEventListener('keyup', function(e){
        obj.hello = e.target.value;
    });

    // File 對象設置 setter
    var fileInput = document.getElementById('file');
    var file;
    fileInput.addEventListener('change', function(e){
        file = fileInput.files[0];

        Object.defineProperty(file, 'progress', {
            set: function(newVal) {
                // document.getElementById('a').value = newVal;
                document.getElementById('b').innerHTML = newVal;
            }
        });
    });

    document.getElementById('button').addEventListener('click', function(){
        file.progress = 'hello file';
    });

</script>
相關文章
相關標籤/搜索