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


Posted in Javascript onApril 26, 2017

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

逻辑部分实现了以后,在更新进度条视图的时候出现一点问题:动态计算生产的进度 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>

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

Javascript 相关文章推荐
ASP.NET jQuery 实例5 (显示CheckBoxList成员选中的内容)
Jan 13 Javascript
javaScript使用EL表达式的几种方式
May 27 Javascript
node.js中的url.format方法使用说明
Dec 10 Javascript
jQuery中dom元素上绑定的事件详解
Apr 24 Javascript
jQuery通过deferred对象管理ajax异步
May 20 Javascript
浅谈js原生拖放
Nov 21 Javascript
学习vue.js中class与style绑定
Dec 03 Javascript
详解Angualr 组件间通信
Jan 21 Javascript
完美实现js选项卡切换效果(一)
Mar 08 Javascript
JavaScript类的继承方法小结【组合继承分析】
Jul 11 Javascript
js实现图片上传并预览功能
Aug 06 Javascript
fetch 如何实现请求数据
Dec 20 Javascript
微信小程序实现给循环列表添加点击样式实例
Apr 26 #Javascript
微信小程序 request接口的封装实例代码
Apr 26 #Javascript
微信小程序中hidden不生效原因的解决办法
Apr 26 #Javascript
微信小程序 flex实现导航实例详解
Apr 26 #Javascript
微信扫码支付零云插件版实例详解
Apr 26 #Javascript
JavaScript实现的冒泡排序法及统计相邻数交换次数示例
Apr 26 #Javascript
微信小程序 实例开发总结
Apr 26 #Javascript
You might like
让ThinkPHP支持大小写url地址访问的方法
2014/10/31 PHP
PHP中使用register_shutdown_function函数截获fatal error示例
2015/04/21 PHP
实例简介PHP的一些高级面向对象编程的特性
2015/11/27 PHP
WordPress中用于检索模版的相关PHP函数使用解析
2015/12/15 PHP
利用phpexcel对数据库数据的导入excel(excel筛选)、导出excel
2017/04/27 PHP
建议大家看下JavaScript重要知识更新
2007/07/08 Javascript
JavaScript将Table导出到Excel实现思路及代码
2013/03/13 Javascript
js获取当前页面的url网址信息
2014/06/12 Javascript
JavaScript使用concat连接数组的方法
2015/04/06 Javascript
js实现带缓冲效果的仿QQ面板折叠菜单代码
2015/09/06 Javascript
js中unicode转码方法详解
2015/10/09 Javascript
javascript事件冒泡简单示例
2016/06/20 Javascript
AngularJS基础 ng-class-odd 指令示例
2016/08/01 Javascript
js判断数组key是否存在(不用循环)的简单实例
2016/08/03 Javascript
vue2.0 axios前后端数据处理实例代码
2017/06/30 Javascript
Vue之Watcher源码解析(1)
2017/07/19 Javascript
layui实现文件或图片上传记录
2018/08/28 Javascript
webpack4+react多页面架构的实现
2018/10/25 Javascript
微信小程序局部刷新触发整页刷新效果的实现代码
2018/11/21 Javascript
从Node.js事件触发器到Vue自定义事件的深入讲解
2020/06/26 Javascript
Python温度转换实例分析
2018/01/17 Python
python微信跳一跳系列之棋子定位像素遍历
2018/02/26 Python
python XlsxWriter模块创建aexcel表格的实例讲解
2018/05/03 Python
python验证码识别教程之利用滴水算法分割图片
2018/06/05 Python
Flask之flask-session的具体使用
2018/07/26 Python
Python3解释器知识点总结
2019/02/19 Python
详解Python 定时框架 Apscheduler原理及安装过程
2019/06/14 Python
Django 对象关系映射(ORM)源码详解
2019/08/06 Python
python 定时器每天就执行一次的实现代码
2019/08/14 Python
win10下opencv-python特定版本手动安装与pip自动安装教程
2020/03/05 Python
jupyter修改文件名方式(TensorFlow)
2020/04/21 Python
世界最大的海报和艺术印刷商店:AllPosters.com
2017/02/01 全球购物
秋季运动会广播稿大全
2014/02/17 职场文书
幼儿教师寄语集锦
2014/04/03 职场文书
运动会通讯稿300字
2015/07/20 职场文书
服务器nginx权限被拒绝解决案例
2022/09/23 Servers