详解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 相关文章推荐
(function(){})()的用法与优点
Mar 11 Javascript
jquery的ajax()函数传值中文乱码解决方法介绍
Nov 08 Javascript
AngularJS HTML编译器介绍
Dec 06 Javascript
js实现鼠标触发图片抖动效果的方法
Feb 27 Javascript
JavaScript通过Date-Mask将日期转换成字符串的方法
Jun 04 Javascript
Vue引入sass并配置全局变量的方法
Jun 27 Javascript
解决layui-table单元格设置为百分比在ie8下不能自适应的问题
Sep 28 Javascript
浅谈vue中组件绑定事件时是否加.native
Nov 09 Javascript
微信小程序音乐播放器开发
Nov 20 Javascript
JavaScript中的相等操作符使用详解
Dec 21 Javascript
基于原生JS封装的Modal对话框插件的示例代码
Sep 09 Javascript
通过JS判断网页是否为手机打开
Oct 28 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获取搜索引擎关键字来源的函数(支持百度和谷歌等搜索引擎)
2012/10/03 PHP
Laravel5.1 框架Request请求操作常见用法实例分析
2020/01/04 PHP
jquery.fileEveryWhere.js 一个跨浏览器的file显示插件
2011/10/24 Javascript
深入理解JavaScript系列(13) This? Yes,this!
2012/01/18 Javascript
javascript教程之不完整的继承(js原型链)
2014/01/13 Javascript
js自动生成的元素与页面原有元素发生堆叠的解决方法
2014/09/04 Javascript
JavaScript中计算网页中某个元素的位置
2015/06/10 Javascript
dedecms页面如何获取会员状态的实例代码
2016/03/15 Javascript
jQuery的内容过滤选择器学习教程
2016/04/18 Javascript
js阻止浏览器默认行为触发的通用方法(推荐)
2016/05/15 Javascript
JQuery Mobile 弹出式登录框的实现方法
2016/05/28 Javascript
浅谈jQuery为哪般去掉了浏览器检测
2016/08/29 Javascript
jquery datatable服务端分页
2016/08/31 Javascript
Javascript获取background属性中url的值
2016/10/17 Javascript
js实现模糊匹配功能
2017/02/15 Javascript
Vue添加请求拦截器及vue-resource 拦截器使用
2017/11/23 Javascript
详解微信小程序审核不通过的解决方法
2018/01/17 Javascript
Vue Promise的axios请求封装详解
2018/08/13 Javascript
详解vue项目中使用token的身份验证的简单实践
2019/03/08 Javascript
js 获取扫码枪输入数据的方法
2020/06/10 Javascript
使用Vant完成通知栏Notify的提示操作
2020/11/11 Javascript
[42:11]TNC vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
Python修改Excel数据的实例代码
2013/11/01 Python
pygame学习笔记(4):声音控制
2015/04/15 Python
Python备份目录及目录下的全部内容的实现方法
2016/06/12 Python
python实现分页效果
2017/10/25 Python
python3.6使用pickle序列化class的方法
2018/10/22 Python
Python实现将多个空格换为一个空格.md的方法
2018/12/20 Python
html5 Canvas画图教程(7)—canvas里画曲线之quadraticCurveTo方法
2013/01/09 HTML / CSS
竞选团支书演讲稿
2014/04/28 职场文书
实习介绍信模板
2015/01/30 职场文书
大学生党员个人总结
2015/02/13 职场文书
入党转正介绍人意见
2015/06/03 职场文书
react中props 的使用及进行限制的方法
2021/04/28 Javascript
Python 机器学习工具包SKlearn的安装与使用
2021/05/14 Python
Python源码解析之List
2021/05/21 Python