詳解Vue 普通對象數(shù)據(jù)更新與 file 對象數(shù)據(jù)更新
最近在做一個多圖片上傳的組件,需求是做到多文件依次上傳,并顯示上傳進度條。
邏輯部分實現(xiàn)了以后,在更新進度條視圖的時候出現(xiàn)一點問題:動態(tài)計算生產的進度 progress 屬性不會自動更新。
原來的代碼是這樣寫的:
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中辦法,百思不得其解。
后來一怒之下做了一個小 demo,看看問題到底出現(xiàn)在哪里,把不想關的代碼都剔除,只保留核心代碼,并用最簡單的數(shù)據(jù)來模擬一下。代碼如下:
// 用數(shù)組模擬 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 對象換成了數(shù)組來模擬,把 file 對象換成了普通對象模擬。
神奇的是,這樣居然就自動更新了。
由于文件 file 后來都保存在數(shù)組里,這說明唯一的區(qū)別就在 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 對象和普通對象的區(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ù)來實現(xiàn)的,而 Vue 默認沒有對 File 對象設置 getter setter, 因此用 File 對象不會自動更新。
解決辦法,就是用普通對象保存 file 對象里需要的信息,然后用來構造視圖數(shù)據(jù)?;蛘咦约菏謩釉O置 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>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- vue數(shù)據(jù)更新UI不刷新顯示的解決辦法
- 解決echarts vue數(shù)據(jù)更新,視圖不更新問題(echarts嵌在vue彈框中)
- 詳解Vue 數(shù)據(jù)更新了但頁面沒有更新的 7 種情況匯總及延伸總結
- vue 解決異步數(shù)據(jù)更新問題
- Vue.js中provide/inject實現(xiàn)響應式數(shù)據(jù)更新的方法示例
- 詳解vue中的父子傳值雙向綁定及數(shù)據(jù)更新問題
- 解決IE11 vue +webpack 項目中數(shù)據(jù)更新后頁面沒有刷新的問題
- 解決vue keep-alive 數(shù)據(jù)更新的問題
- 談談對vue響應式數(shù)據(jù)更新的誤解
- vue+echarts實現(xiàn)數(shù)據(jù)實時更新
相關文章
vue3使用Pinia修改state的三種方法(直接修改,$patch,actions)
Vue3?Pinia是一個狀態(tài)管理庫,專門為Vue3設計優(yōu)化,它提供了一種簡單而強大的方式來管理應用程序的狀態(tài),并且與Vue3的響應式系統(tǒng)緊密集成,本文給大家介紹了vue3使用Pinia修改state的三種方法,需要的朋友可以參考下2024-03-03Vue+Element ui 根據(jù)后臺返回數(shù)據(jù)設置動態(tài)表頭操作
這篇文章主要介紹了Vue+Element ui 根據(jù)后臺返回數(shù)據(jù)設置動態(tài)表頭操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09