详解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 相关文章推荐
js中将HTMLCollection/NodeList/伪数组转换成数组的代码
Jul 31 Javascript
Underscore.js 的模板功能介绍与应用
Dec 24 Javascript
js判断当页面无法回退时关闭网页否则就history.go(-1)
Aug 07 Javascript
jquery实现两个图片渐变切换效果的方法
Jun 25 Javascript
vue项目中做编辑功能传递数据时遇到问题的解决方法
Dec 19 Javascript
从零开始学习Node.js系列教程之基于connect和express框架的多页面实现数学运算示例
Apr 13 Javascript
使用jquery的jsonp如何发起跨域请求及其原理详解
Aug 17 jQuery
JS浅拷贝和深拷贝原理与实现方法分析
Feb 28 Javascript
ajax跨域访问遇到的问题及解决方案
May 23 Javascript
微信小程序登陆注册功能的实现代码
Dec 10 Javascript
JS实现百度搜索框关键字推荐
Feb 17 Javascript
JavaScript中的this妙用实例分析
May 09 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新手上路(四)
2006/10/09 PHP
mayfish 数据入库验证代码
2010/04/30 PHP
php数组去重实例及分析
2013/11/26 PHP
判断浏览器的javascript版本的代码
2010/09/03 Javascript
几种设置表单元素中文本输入框不可编辑的方法总结
2013/11/25 Javascript
Iframe实现跨浏览器自适应高度解决方法
2014/09/02 Javascript
jQuery子属性过滤选择器用法分析
2015/02/10 Javascript
JavaScript获得url查询参数的方法
2015/07/02 Javascript
轻松实现Bootstrap图片轮播
2020/04/20 Javascript
JS实时弹出新消息提示框并有提示音响起的实现代码
2016/04/20 Javascript
jQuery 判断是否包含在数组中Array[]的方法
2016/08/03 Javascript
js实现的xml对象转json功能示例
2016/12/24 Javascript
jQuery发请求传输中文参数乱码问题的解决方案
2018/05/22 jQuery
node中使用es6/7/8(支持性与性能)
2019/03/28 Javascript
浅析vue插槽和作用域插槽的理解
2019/04/22 Javascript
微信小程序学习总结(二)样式、属性、模板操作分析
2020/06/04 Javascript
[29:59]完美世界DOTA2联赛PWL S3 Forest vs access 第二场 12.11
2020/12/13 DOTA
python中使用urllib2获取http请求状态码的代码例子
2014/07/07 Python
Python使用MONGODB入门实例
2015/05/11 Python
使用Python操作MySQL的一些基本方法
2015/08/16 Python
python通过opencv实现批量剪切图片
2017/11/13 Python
详解如何利用Cython为Python代码加速
2018/01/27 Python
Python弹出输入框并获取输入值的实例
2019/06/18 Python
python实现自动化上线脚本的示例
2019/07/01 Python
python各类经纬度转换的实例代码
2019/08/08 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
Python Tkinter图形工具使用方法及实例解析
2020/06/15 Python
解决virtualenv -p python3 venv报错的问题
2021/02/05 Python
HTML5实现视频直播功能思路详解
2017/11/16 HTML / CSS
Homestay中文官网:全球寄宿家庭
2018/10/18 全球购物
Radley英国官网:英国莱德利小狗包
2019/03/21 全球购物
新闻工作者先进事迹
2014/05/26 职场文书
树转促学习心得体会
2014/09/10 职场文书
群众路线教师自我剖析材料
2014/09/29 职场文书
关于感谢信的范文
2015/01/23 职场文书
《成长的天空》读后感3篇
2019/12/06 职场文书