详解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获取父节点方法
Aug 20 Javascript
基于jquery库的tab新形式使用
Nov 16 Javascript
js调用图片隐藏&amp;显示实现代码
Sep 13 Javascript
Javascript浅谈之引用类型
Dec 18 Javascript
两个select多选模式的选项相互移动(示例代码)
Jan 11 Javascript
jQuery侧边栏实现代码
May 06 Javascript
jQuery的extend方法【三种】
Dec 14 Javascript
微信小程序 PHP后端form表单提交实例详解
Jan 12 Javascript
JavaScript 函数的定义-调用、注意事项
Apr 16 Javascript
利用node.js+mongodb如何搭建一个简单登录注册的功能详解
Jul 30 Javascript
php中and 和 &amp;&amp;出坑指南
Jul 13 Javascript
详解Bootstrap 学习(一)入门
Apr 12 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 存取 MySQL 数据库的一个例子
2006/10/09 PHP
用PHP实现的四则运算表达式计算实现代码
2011/08/02 PHP
详解php的魔术方法__get()和__set()使用介绍
2012/09/19 PHP
PHP session文件独占锁引起阻塞问题解决方法
2015/05/12 PHP
PHP合并数组+号和array_merge的区别
2015/06/25 PHP
php实现smarty模板无限极分类的方法
2015/12/07 PHP
laravel框架与其他框架的详细对比
2019/10/23 PHP
PHP设计模式(一)工厂模式Factory实例详解【创建型】
2020/05/02 PHP
Fixie.js 自动填充内容的插件
2012/06/28 Javascript
TextArea设置MaxLength属性最大输入值的js代码
2012/12/21 Javascript
JavaScript自动设置IFrame高度的小例子
2013/06/08 Javascript
基于AngularJS实现页面滚动到底自动加载数据的功能
2015/10/16 Javascript
在JavaScript中如何解决用execCommand(
2015/10/19 Javascript
js精准的倒计时函数分享
2016/06/29 Javascript
springMVC结合AjaxForm上传文件
2016/07/12 Javascript
深入nodejs中流(stream)的理解
2017/03/27 NodeJs
在Vant的基础上封装下拉日期控件的代码示例
2018/12/05 Javascript
详解微信小程序-canvas绘制文字实现自动换行
2019/04/26 Javascript
浅谈redux, koa, express 中间件实现对比解析
2019/05/23 Javascript
nodejs nedb 封装库与使用方法示例
2020/02/06 NodeJs
vue-router重写push方法,解决相同路径跳转报错问题
2020/08/07 Javascript
pandas对指定列进行填充的方法
2018/04/11 Python
Python+selenium实现自动循环扔QQ邮箱漂流瓶
2018/05/29 Python
浅谈flask源码之请求过程
2018/07/26 Python
Python列表生成式与生成器操作示例
2018/08/01 Python
用Python将mysql数据导出成json的方法
2018/08/21 Python
Python通用循环的构造方法实例分析
2018/12/19 Python
TensorFlow——Checkpoint为模型添加检查点的实例
2020/01/21 Python
recorder.js 基于Html5录音功能的实现
2020/05/26 HTML / CSS
梵蒂冈和罗马卡:Omnia Card Pass
2018/02/10 全球购物
DeinDesign德国:设计自己的手机壳
2019/12/14 全球购物
英语专业学生个人求职信范文
2014/01/06 职场文书
加班费申请报告
2015/05/15 职场文书
入党积极分子考察意见
2015/06/02 职场文书
Linux安装Nginx步骤详解
2021/03/31 Servers
MySQL批量更新不同表中的数据
2022/05/11 MySQL