详解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 相关文章推荐
document.all还是document.getElementsByName?
Jul 21 Javascript
jQuery 名称冲突的解决方法
Apr 08 Javascript
iframe里面的元素触发父窗口元素事件的jquery代码
Oct 19 Javascript
javascript使用prototype完成单继承
Dec 24 Javascript
jQuery简单实现日历的方法
May 04 Javascript
jQuery实现指定区域外单击关闭指定层的方法【经典】
Jun 22 Javascript
JS 动态判断PC和手机浏览器实现代码
Sep 21 Javascript
快速解决js开发下拉框中blur与click冲突
Oct 10 Javascript
详解Javascript百度地图接口开发文档中的类和方法
Feb 07 Javascript
js链表操作(实例讲解)
Aug 29 Javascript
ES6中新增的Object.assign()方法详解
Sep 22 Javascript
微信小程序使用slider设置数据值及switch开关组件功能【附源码下载】
Dec 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
zf框架db类的分页示例分享
2014/03/14 PHP
mac下Apache + MySql + PHP搭建网站开发环境
2014/06/02 PHP
php获取网页里所有图片并存入数组的方法
2015/04/06 PHP
php根据年月获取当月天数及日期数组的方法
2016/11/30 PHP
php实现文件上传基本验证
2020/03/04 PHP
ext form 表单提交数据的方法小结
2008/08/08 Javascript
javascript 模拟JQuery的Ready方法实现并出现的问题
2009/12/06 Javascript
用JSON做数据传输格式中的一些问题总结
2011/12/21 Javascript
jQuery学习笔记(2)--用jquery实现各种模态提示框代码及项目构架
2013/04/08 Javascript
js和php如何获取当前url的内容
2013/09/22 Javascript
JavaScript验证Email(3种方法)
2015/09/21 Javascript
jQuery动态添加
2016/04/07 Javascript
微信小程序倒计时功能实例代码
2018/07/17 Javascript
vue-cli中安装方法(图文详细步骤)
2018/12/12 Javascript
Vue 组件修改根实例的数据的方法
2019/04/02 Javascript
vue实现登录拦截
2020/06/29 Javascript
[48:37]EG vs OG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
python统计文本字符串里单词出现频率的方法
2015/05/26 Python
Python使用wxPython实现计算器
2018/01/30 Python
用python 批量更改图像尺寸到统一大小的方法
2018/03/31 Python
浅述python中深浅拷贝原理
2018/09/18 Python
pandas.DataFrame的pivot()和unstack()实现行转列
2019/07/06 Python
python matplotlib.pyplot.plot()参数用法
2020/04/14 Python
理解Django 中Call Stack机制的小Demo
2020/09/01 Python
python 密码学示例——凯撒密码的实现
2020/09/21 Python
Python 多进程、多线程效率对比
2020/11/19 Python
css3动画 小球滚动 js控制动画暂停
2019/11/29 HTML / CSS
商务考察邀请函范文
2014/01/21 职场文书
2014年医学生毕业自我鉴定
2014/03/26 职场文书
企业演讲稿范文大全
2014/05/20 职场文书
安全保卫工作竞聘材料
2014/08/25 职场文书
酒店服务员岗位职责
2015/02/09 职场文书
证券公司客户经理岗位职责
2015/04/09 职场文书
Java实现带图形界面的聊天程序
2022/06/10 Java/Android
MySQL串行化隔离级别(间隙锁实现)
2022/06/16 MySQL
Python安装及建立虚拟环境的完整步骤
2022/06/25 Servers