详解Vue 普通对象数据更新与 file 对象数据更新

发布时间 - 2026-01-11 00:51:19    点击率:

最近在做一个多图片上传的组件,需求是做到多文件依次上传,并显示上传进度条。

逻辑部分实现了以后,在更新进度条视图的时候出现一点问题:动态计算生产的进度 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,看看问题到底出现在哪里,把不想关的代码都剔除,只保留核心代码,并用最简单的数据来模拟一下。代码如下:

// 用数组模拟 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 对象换成了普通对象模拟。

神奇的是,这样居然就自动更新了。

由于文件 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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# vue  # 数据更新  # vue.js  # 更新对象  # vue数据更新UI不刷新显示的解决办法  # 解决echarts vue数据更新  # 视图不更新问题(echarts嵌在vue弹框中)  # 详解Vue 数据更新了但页面没有更新的 7 种情况汇总及延伸总结  # vue 解决异步数据更新问题  # Vue.js中provide/inject实现响应式数据更新的方法示例  # 详解vue中的父子传值双向绑定及数据更新问题  # 解决IE11 vue +webpack 项目中数据更新后页面没有刷新的问题  # 解决vue keep-alive 数据更新的问题  # 谈谈对vue响应式数据更新的误解  # vue+echarts实现数据实时更新  # 的是  # 上传  # 自动更新  # 可以自动  # 换成了  # 都是  # 进度条  # 他们的  # 岿然不动  # 就在  # 是这样  # 出现在  # 百思不得其解  # 仅仅是  # 做一个  # 看一下  # 多图  # 最简单  # 来实现  # 解决办法 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】  教学论文网站制作软件有哪些,写论文用什么软件 ?  如何撰写建站申请书?关键要点有哪些?  Java类加载基本过程详细介绍  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  Laravel集合Collection怎么用_Laravel集合常用函数详解  JavaScript如何实现继承_有哪些常用方法  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  Python函数文档自动校验_规范解析【教程】  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  Laravel如何处理文件下载请求?(Response示例)  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  java获取注册ip实例  如何为不同团队 ID 动态生成多个独立按钮  在Oracle关闭情况下如何修改spfile的参数  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  JavaScript如何实现音频处理_Web Audio API如何工作?  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  Laravel如何记录自定义日志?(Log频道配置)  在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  如何在IIS7上新建站点并设置安全权限?  微信小程序 scroll-view组件实现列表页实例代码  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  Laravel storage目录权限问题_Laravel文件写入权限设置  Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门  ,在苏州找工作,上哪个网站比较好?  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  Laravel怎么调用外部API_Laravel Http Client客户端使用  Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives  Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  JavaScript如何操作视频_媒体API怎么控制播放  深入理解Android中的xmlns:tools属性  Laravel的.env文件有什么用_Laravel环境变量配置与管理详解  网站制作软件有哪些,制图软件有哪些?  jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】  如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?  C语言设计一个闪闪的圣诞树  Python结构化数据采集_字段抽取解析【教程】  大连网站制作公司哪家好一点,大连买房网站哪个好?  如何在云虚拟主机上快速搭建个人网站?  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  怎么用AI帮你设计一套个性化的手机App图标?  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧  Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程  Laravel如何配置Horizon来管理队列?(安装和使用)  如何在云主机上快速搭建网站?  英语简历制作免费网站推荐,如何将简历翻译成英文?