详解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 相关文章推荐
静态页面下用javascript操作ACCESS数据库(读增改删)的代码
May 14 Javascript
javascript各种复制代码收集
Sep 20 Javascript
Jquery的hide及toggle方法让超链接慢慢消失
Sep 06 Javascript
对于Form表单reset方法的新认识
Mar 05 Javascript
使用JS或jQuery模拟鼠标点击a标签事件代码
Mar 10 Javascript
JQuery操作textarea,input,select,checkbox方法
Sep 02 Javascript
易操作的jQuery表单提示插件
Dec 01 Javascript
jQuery查找节点方法完整实例
Sep 13 Javascript
Vue页面骨架屏的实现方法
May 22 Javascript
vue-cli 3.x 配置Axios(proxyTable)跨域代理方法
Sep 19 Javascript
JavaScript实现的滚动公告特效【基于jQuery】
Jul 10 jQuery
vuex根据不同的用户权限展示不同的路由列表功能
Sep 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
PHP获取QQ达人QQ信息的方法
2015/03/05 PHP
php基于curl实现的股票信息查询类实例
2016/11/11 PHP
Yii框架分页技术实例分析
2019/08/30 PHP
Event altKey,ctrlKey,shiftKey属性解析
2013/12/18 Javascript
JavaScript遍历table表格中的某行某列并打印其值
2014/07/08 Javascript
javascript中call,apply,bind的用法对比分析
2015/02/12 Javascript
jQuery使用fadein方法实现渐出效果实例
2015/03/27 Javascript
javascript编程异常处理实例小结
2015/11/30 Javascript
JavaScript实现打开链接页面的方式汇总
2016/06/02 Javascript
JavaScript面向对象分层思维全面解析
2016/11/22 Javascript
详解如何提高 webpack 构建 Vue 项目的速度
2017/07/03 Javascript
深入解析koa之中间件流程控制
2019/06/17 Javascript
详解element-ui设置下拉选择切换必填和非必填
2019/06/17 Javascript
vue项目从node8.x升级到12.x后的问题解决
2019/10/25 Javascript
JS实现字体背景跑马灯
2020/01/06 Javascript
Webpack中SplitChunksPlugin 配置参数详解
2020/03/24 Javascript
python错误处理详解
2014/09/28 Python
Python计算回文数的方法
2015/03/11 Python
对Python正则匹配IP、Url、Mail的方法详解
2018/12/25 Python
对PyQt5基本窗口控件 QMainWindow的使用详解
2019/06/19 Python
python爬虫刷访问量 2019 7月
2019/08/01 Python
Python lambda表达式filter、map、reduce函数用法解析
2019/09/11 Python
python全局变量引用与修改过程解析
2020/01/07 Python
TensorFlow 读取CSV数据的实例
2020/02/05 Python
Python字典深浅拷贝与循环方式方法详解
2020/02/09 Python
解决Keras的自定义lambda层去reshape张量时model保存出错问题
2020/07/01 Python
python pandas dataframe 去重函数的具体使用
2020/07/20 Python
Python3爬虫中pyspider的安装步骤
2020/07/29 Python
泰国综合购物网站:Lazada泰国
2018/04/09 全球购物
Jar包的作用是什么
2014/03/30 面试题
Linux的文件类型
2012/03/07 面试题
值传递还是引用传递
2015/02/08 面试题
销售部主管岗位职责
2013/12/18 职场文书
计算机求职信
2014/07/02 职场文书
Pytest中conftest.py的用法
2021/06/27 Python
python 实现图片特效处理
2022/04/03 Python