详解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中的16进制字符(改进)
Nov 21 Javascript
JS 模态对话框和非模态对话框操作技巧汇总
Apr 15 Javascript
jquery.form.js用法之清空form的方法
Mar 07 Javascript
jQuery中extend函数详解
Jul 13 Javascript
在Html中使用Requirejs进行模块化开发实例详解
Apr 15 Javascript
jQuery mobile的header和footer在点击屏幕的时候消失的解决办法
Jul 01 Javascript
JS实现隔行换色的表格排序
Mar 27 Javascript
vue cli 3.0 使用全过程解析
Jun 14 Javascript
用POSTMAN发送JSON格式的POST请求示例
Sep 04 Javascript
详解Bootstrap 学习(一)入门
Apr 12 Javascript
微信小程序文章详情页跳转案例详解
Jul 09 Javascript
Vue.Draggable实现交换位置
Apr 07 Vue.js
微信小程序实现给循环列表添加点击样式实例
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
PHP新手上路(十三)
2006/10/09 PHP
php URL验证正则表达式
2011/07/19 PHP
有关PHP中MVC的开发经验分享
2012/05/17 PHP
深入Memcache的Session数据的多服务器共享详解
2013/06/13 PHP
php可应用于面包屑导航的迭代寻找家谱树实现方法
2015/02/02 PHP
php实现的农历算法实例
2015/08/11 PHP
Laravel + Elasticsearch 实现中文搜索的方法
2020/02/02 PHP
查询绑定数据岛的表格中的文本并修改显示方式的js代码
2009/12/15 Javascript
判断iframe是否加载完成的完美方法
2010/01/07 Javascript
读jQuery之八 包装事件对象
2011/06/21 Javascript
js简单实现让文本框内容逐个字的显示出来
2013/10/22 Javascript
JavaScript?Apple设备检测示例代码
2013/11/15 Javascript
Script标签与访问HTML页面详解
2014/01/10 Javascript
开源的javascript项目Kissy介绍
2014/11/28 Javascript
jQuery基础知识小结
2014/12/22 Javascript
js获取当前日期时间及其它操作汇总
2015/04/17 Javascript
ionic js 模型 $ionicModal 可以遮住用户主界面的内容框
2016/06/06 Javascript
解决vue数据不实时更新的问题(数据更改了,但数据不实时更新)
2020/10/27 Javascript
vue3.0+vue-router+element-plus初实践
2020/12/02 Vue.js
[01:10:02]IG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python登录QQ邮箱发信的实现代码
2013/02/10 Python
对python中Json与object转化的方法详解
2018/12/31 Python
Python分割训练集和测试集的方法示例
2019/09/19 Python
python中安装django模块的方法
2020/03/12 Python
Shoes For Crews法国官网:美国领先的防滑鞋设计和制造商
2018/01/01 全球购物
个人生活学习自我评价范文
2013/11/26 职场文书
元旦晚会上单位领导演讲稿
2014/01/05 职场文书
家长给孩子的评语
2014/01/30 职场文书
组织鉴定材料
2014/06/02 职场文书
纪检干部现实表现材料
2014/08/21 职场文书
连锁超市项目计划书
2014/09/15 职场文书
就业证明函
2015/06/17 职场文书
2016春季运动会前导词
2015/11/25 职场文书
python 实现的截屏工具
2021/05/08 Python
Python实现制作销售数据可视化看板详解
2021/11/27 Python