詳解Vue 普通對(duì)象數(shù)據(jù)更新與 file 對(duì)象數(shù)據(jù)更新
最近在做一個(gè)多圖片上傳的組件,需求是做到多文件依次上傳,并顯示上傳進(jìn)度條。
邏輯部分實(shí)現(xiàn)了以后,在更新進(jìn)度條視圖的時(shí)候出現(xiàn)一點(diǎn)問題:動(dòng)態(tài)計(jì)算生產(chǎn)的進(jìn)度 progress 屬性不會(huì)自動(dòng)更新。
原來的代碼是這樣寫的:
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];
// 每個(gè)文件初始進(jìn)度為0
item.progress = '0';
arr.push(obj);
}
this.fileArr = arr;
這里直接將 file 對(duì)象添加一個(gè) progress 屬性記錄上傳進(jìn)度,并初始化為0,然后上傳時(shí)候?qū)崟r(shí)計(jì)算更新 progress。但奇怪的是這個(gè) progress 在視圖里并不會(huì)自動(dòng)更新,巋然不動(dòng),一直都是0。還了N中辦法,百思不得其解。
后來一怒之下做了一個(gè)小 demo,看看問題到底出現(xiàn)在哪里,把不想關(guān)的代碼都剔除,只保留核心代碼,并用最簡單的數(shù)據(jù)來模擬一下。代碼如下:
// 用數(shù)組模擬 files, 用對(duì)象模擬 file 對(duì)象
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 對(duì)象換成了數(shù)組來模擬,把 file 對(duì)象換成了普通對(duì)象模擬。
神奇的是,這樣居然就自動(dòng)更新了。
由于文件 file 后來都保存在數(shù)組里,這說明唯一的區(qū)別就在 file 對(duì)象上面!于是打算用普通對(duì)象保存 file 對(duì)象的屬性再試試。
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);
}
這樣視圖也是可以自動(dòng)更新的,果然是 file 對(duì)象和普通對(duì)象的區(qū)別。
它們究竟是什么區(qū)別呢?看一下他們的類型先。
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 的數(shù)據(jù)更新利用的是 Object.defineProperty 的 getter setter 函數(shù)來實(shí)現(xiàn)的,而 Vue 默認(rèn)沒有對(duì) File 對(duì)象設(shè)置 getter setter, 因此用 File 對(duì)象不會(huì)自動(dòng)更新。
解決辦法,就是用普通對(duì)象保存 file 對(duì)象里需要的信息,然后用來構(gòu)造視圖數(shù)據(jù)?;蛘咦约菏謩?dòng)設(shè)置 File 對(duì)象的 setter,也可以自動(dòng)更新。代碼如下:
<div id="app">
<input type="text" id='a'>
<span id='b'></span>
<input type="file" id='file'>
<button type="button" id='button'>點(diǎn)擊更改file屬性</button>
</div>
<script>
// 普通對(duì)象設(shè)置 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 對(duì)象設(shè)置 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>
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- vue數(shù)據(jù)更新UI不刷新顯示的解決辦法
- 解決echarts vue數(shù)據(jù)更新,視圖不更新問題(echarts嵌在vue彈框中)
- 詳解Vue 數(shù)據(jù)更新了但頁面沒有更新的 7 種情況匯總及延伸總結(jié)
- vue 解決異步數(shù)據(jù)更新問題
- Vue.js中provide/inject實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)更新的方法示例
- 詳解vue中的父子傳值雙向綁定及數(shù)據(jù)更新問題
- 解決IE11 vue +webpack 項(xiàng)目中數(shù)據(jù)更新后頁面沒有刷新的問題
- 解決vue keep-alive 數(shù)據(jù)更新的問題
- 談?wù)剬?duì)vue響應(yīng)式數(shù)據(jù)更新的誤解
- vue+echarts實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)更新
相關(guān)文章
Vue中對(duì)watch的理解(關(guān)鍵是immediate和deep屬性)
watch偵聽器,是Vue實(shí)例的一個(gè)屬性,是用來響應(yīng)數(shù)據(jù)的變化,需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開銷較大的操作時(shí),這個(gè)方式是最有用的,這篇文章主要介紹了Vue中對(duì)watch的理解,需要的朋友可以參考下2022-11-11
vue element-ui里的table中表頭與表格出現(xiàn)錯(cuò)位的解決
這篇文章主要介紹了vue element-ui里的table中表頭與表格出現(xiàn)錯(cuò)位的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
詳解探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 構(gòu)建記事本應(yīng)用
本篇文章主要介紹了詳解探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 構(gòu)建記事本應(yīng)用 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
vue項(xiàng)目實(shí)現(xiàn)img的src動(dòng)態(tài)賦值
這篇文章主要介紹了vue項(xiàng)目實(shí)現(xiàn)img的src動(dòng)態(tài)賦值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
vue mint-ui 實(shí)現(xiàn)省市區(qū)街道4級(jí)聯(lián)動(dòng)示例(仿淘寶京東收貨地址4級(jí)聯(lián)動(dòng))
本篇文章主要介紹了vue mint-ui 實(shí)現(xiàn)省市區(qū)街道4級(jí)聯(lián)動(dòng)(仿淘寶京東收貨地址4級(jí)聯(lián)動(dòng)),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10
解決axios:"timeout of 5000ms exceeded"
這篇文章主要介紹了解決axios:"timeout of 5000ms exceeded"超時(shí)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08

