详解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 相关文章推荐
JQuery实现自定义对话框的代码
Jun 15 Javascript
js 模拟实现类似c#下的hashtable的简单功能代码
Jan 24 Javascript
aspx中利用js实现确认删除代码
Jul 22 Javascript
简体中文转换繁体中文(实现代码)
Dec 25 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
Jan 08 Javascript
jquery点击缩略图切换视频播放特效代码分享
Sep 15 Javascript
angular-ui-sortable实现可拖拽排序列表
Dec 28 Javascript
React-Native做一个文本输入框组件的实现代码
Aug 10 Javascript
vue数组对象排序的实现代码
Jun 20 Javascript
详解基于Vue2.0实现的移动端弹窗(Alert, Confirm, Toast)组件
Aug 02 Javascript
jquery实现动态创建form并提交的方法示例
May 27 jQuery
layui 选择列表,打勾,点击确定返回数据的例子
Sep 02 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 用sock技术发送邮件的函数
2007/07/21 PHP
smarty简单入门实例
2014/11/28 PHP
PHP与Ajax相结合实现登录验证小Demo
2016/03/16 PHP
PHP命名空间namespace用法实例分析
2016/09/27 PHP
jquery 事件执行检测代码
2009/12/09 Javascript
仿百度的关键词匹配搜索示例
2013/09/25 Javascript
jquery ready函数、css函数及text()使用示例
2013/09/27 Javascript
JS 仿腾讯发表微博的效果代码
2013/12/25 Javascript
Node.js返回JSONP详解
2016/05/18 Javascript
如何用JavaScript实现动态修改CSS样式表
2016/05/20 Javascript
微信小程序 wx:key详细介绍
2016/10/28 Javascript
jQuery实现的简单拖动层示例
2017/02/22 Javascript
javascript实现下雨效果
2017/03/27 Javascript
利用npm 安装删除模块的方法
2018/05/15 Javascript
JavaScript设计模式之模板方法模式原理与用法示例
2018/08/07 Javascript
node中的session的具体使用
2018/09/14 Javascript
详解react阻止无效重渲染的多种方式
2018/12/11 Javascript
vue 实现setInterval 创建和销毁实例
2020/07/21 Javascript
es5 类与es6中class的区别小结
2020/11/09 Javascript
[42:36]DOTA2上海特级锦标赛B组败者赛 VG VS Spirit第二局
2016/02/26 DOTA
[51:32]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
Python复制Word内容并使用格式设字体与大小实例代码
2018/01/22 Python
Python模块搜索路径代码详解
2018/01/29 Python
Python中遍历列表的方法总结
2019/06/27 Python
python模拟点击网页按钮实现方法
2020/02/25 Python
Python闭包与装饰器原理及实例解析
2020/04/30 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
2020/11/05 Python
Kneipp克奈圃美国官网:德国百年精油配方的传承
2018/02/07 全球购物
维多利亚的秘密官方旗舰店:VICTORIA’S SECRET
2018/04/02 全球购物
小区门卫岗位职责
2013/12/31 职场文书
《猴子种树》教学反思
2014/02/14 职场文书
安全标准化实施方案
2014/02/20 职场文书
运动会加油稿100字
2014/09/19 职场文书
导游词范文
2015/02/13 职场文书
python异常中else的实例用法
2021/06/15 Python
MySQL数据库配置信息查看与修改方法详解
2022/06/25 MySQL