详解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 相关文章推荐
让iframe自适应高度(支持XHTML,支持FF)
Jul 24 Javascript
国外Lightbox v2.03.3 最新版 下载
Oct 17 Javascript
javascript图像处理—仿射变换深度理解
Jan 16 Javascript
详解AngularJS中的作用域
Jun 17 Javascript
JS实现DIV容器赋值的方法
Dec 14 Javascript
Javascript复制实例详解
Jan 28 Javascript
简单实现的JQuery文本框水印插件
Jun 14 Javascript
jQuery获取radio选中项的值实例
Jun 18 Javascript
Angular的模块化(代码分享)
Dec 26 Javascript
微信小程序 wx.login解密出现乱码的问题解决办法
Mar 10 Javascript
详解AngularJs HTTP响应拦截器实现登陆、权限校验
Apr 11 Javascript
微信小程序实现订单倒计时
Nov 01 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
php全局变量和类配合使用深刻理解
2013/06/05 PHP
使用配置类定义Codeigniter全局变量
2014/06/12 PHP
thinkphp在模型中自动完成session赋值示例代码
2014/09/09 PHP
Yii清理缓存的方法
2016/01/06 PHP
PHP中常用的数组操作方法笔记整理
2016/05/16 PHP
php+Memcached实现简单留言板功能示例
2017/02/15 PHP
php设计模式之迭代器模式实例分析【星际争霸游戏案例】
2020/04/07 PHP
一段利用WSH修改和查看IP配置的代码
2008/05/11 Javascript
js Date自定义函数 延迟脚本执行
2010/03/10 Javascript
基于JQuery的cookie插件
2010/04/07 Javascript
jQuery学习总结之jQuery事件
2014/06/30 Javascript
node.js中的fs.link方法使用说明
2014/12/15 Javascript
jQuery使用之处理页面元素用法实例
2015/01/19 Javascript
javascript操作符&quot;!~&quot;详解
2015/02/10 Javascript
AngularJS整合Springmvc、Spring、Mybatis搭建开发环境
2016/02/25 Javascript
jQuery实现的购物车物品数量加减功能代码
2016/11/16 Javascript
Vue服务端渲染和Vue浏览器端渲染的性能对比(实例PK )
2017/03/31 Javascript
jQuery获取table表中的td标签(实例讲解)
2017/07/28 jQuery
基于vue 实现token验证的实例代码
2017/12/14 Javascript
关于express与koa的使用对比详解
2018/01/25 Javascript
如何让node运行es6模块文件及其原理详解
2018/12/11 Javascript
vue+Element实现搜索关键字高亮功能
2019/05/28 Javascript
微信小程序开发搜索功能实现(前端+后端+数据库)
2020/03/04 Javascript
[00:30]明星选手化身超级英雄!2018DOTA2亚洲邀请赛全明星赛来临!
2018/04/06 DOTA
[01:07:17]EG vs Optic Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
django query模块
2019/04/20 Python
Python configparser模块配置文件过程解析
2020/03/03 Python
Python基于当前时间批量创建文件
2020/05/07 Python
HTC VIVE美国官网:VR虚拟现实眼镜
2018/02/13 全球购物
乌克兰电子产品和家用电器购物网站:TOUCH
2019/08/09 全球购物
科颜氏香港官方网店:Kiehl’s香港
2021/03/07 全球购物
金鑫耀Java笔试题
2014/09/06 面试题
个人公司授权委托书范本
2014/10/12 职场文书
2015年暑期社会实践报告
2015/07/13 职场文书
遇事可以测出您的见识与格局
2019/09/16 职场文书
Python函数中apply、map、applymap的区别
2021/11/27 Python