详解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 相关文章推荐
jQuery生成asp.net服务器控件的代码
Feb 04 Javascript
使用Javascript写的2048小游戏
Nov 25 Javascript
JavaScript原生xmlHttp与jquery的ajax方法json数据格式实例
Dec 04 Javascript
AngularJS  自定义指令详解及实例代码
Sep 14 Javascript
vue.js表格分页示例
Oct 18 Javascript
javascript实现无法关闭的弹框
Nov 27 Javascript
利用jquery实现下拉框的禁用与启用
Dec 07 Javascript
JS百度地图搜索悬浮窗功能
Jan 12 Javascript
Node.js如何响应Ajax的POST请求并且保存为JSON文件详解
Mar 10 Javascript
详解vue-cli项目中怎么使用mock数据
May 29 Javascript
jQuery实现上下滚动公告栏详细代码
Nov 21 jQuery
详解vue3.0 diff算法的使用(超详细)
Jul 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简单实现文件或图片强制下载的方法
2016/12/06 PHP
PHP+redis实现的限制抢购防止商品超发功能详解
2019/09/19 PHP
在TP5数据库中四个字段实现无限分类的示例
2019/10/18 PHP
PHP cookie与session会话基本用法实例分析
2019/11/18 PHP
广告切换效果(缓动切换)
2009/05/27 Javascript
javascript 必知必会之closure
2009/09/21 Javascript
JSON 教程 json入门学习笔记
2020/09/22 Javascript
jQuery调用AJAX时Get和post公用的乱码解决方法实例说明
2013/06/04 Javascript
js 将json字符串转换为json对象的方法解析
2013/11/13 Javascript
Angular.js回顾ng-app和ng-model使用技巧
2016/04/26 Javascript
BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面
2016/08/01 Javascript
基于JavaScript实现自动更新倒计时效果
2016/12/19 Javascript
微信小程序 sha1 实现密码加密实例详解
2017/07/06 Javascript
vue脚手架中配置Sass的方法
2018/01/04 Javascript
React和Vue中监听变量变化的方法
2018/11/14 Javascript
微信小程序页面间跳转传参方式总结
2019/06/13 Javascript
JavaScript实现身份证验证代码实例
2019/08/26 Javascript
JS实现电脑虚拟键盘的操作
2020/06/24 Javascript
python 七种邮件内容发送方法实例
2014/04/22 Python
在Python中操作文件之seek()方法的使用教程
2015/05/24 Python
Python实现定时精度可调节的定时器
2018/04/15 Python
Python列表list排列组合操作示例
2018/12/18 Python
python适合人工智能的理由和优势
2019/06/28 Python
浅谈Python小波分析库Pywavelets的一点使用心得
2019/07/09 Python
python Django里CSRF 对应策略详解
2019/08/05 Python
python实现代码统计器
2019/09/19 Python
python生成大写32位uuid代码
2020/03/03 Python
python对一个数向上取整的实例方法
2020/06/18 Python
python脚本定时发送邮件
2020/12/22 Python
css3翻牌翻数字的示例代码
2020/02/07 HTML / CSS
印度尼西亚综合购物网站:Lazada印尼
2016/09/07 全球购物
PHP面试题及答案二
2015/05/23 面试题
如何通过jdbc调用存储过程
2012/04/19 面试题
2014年妇幼卫生工作总结
2014/12/09 职场文书
2015公务员年度考核评语
2015/03/25 职场文书
python pygame 开发五子棋双人对弈
2022/05/02 Python