详解Vue 普通对象数据更新与 file 对象数据更新

 更新时间:2017年04月26日 17:12:16   作者:muge10  
本篇文章主要介绍了详解Vue 普通对象数据更新与 file 对象数据更新 ,具有一定的参考价值,有兴趣的可以了解一下。

最近在做一个多图片上传的组件,需求是做到多文件依次上传,并显示上传进度条。

逻辑部分实现了以后,在更新进度条视图的时候出现一点问题:动态计算生产的进度 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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • vue3使用Pinia修改state的三种方法(直接修改,$patch,actions)

    vue3使用Pinia修改state的三种方法(直接修改,$patch,actions)

    Vue3 Pinia是一个状态管理库,专门为Vue3设计优化,它提供了一种简单而强大的方式来管理应用程序的状态,并且与Vue3的响应式系统紧密集成,本文给大家介绍了vue3使用Pinia修改state的三种方法,需要的朋友可以参考下
    2024-03-03
  • vue3引入Element-plus的详细步骤记录

    vue3引入Element-plus的详细步骤记录

    Element Plus是为适配Vue3而对Element UI进行重构后产生的前端组件库,包含丰富的基础组件,下面这篇文章主要给大家介绍了关于vue3引入Element-plus的相关资料,需要的朋友可以参考下
    2022-04-04
  • Vue+Element ui 根据后台返回数据设置动态表头操作

    Vue+Element ui 根据后台返回数据设置动态表头操作

    这篇文章主要介绍了Vue+Element ui 根据后台返回数据设置动态表头操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • vue单选按钮,选中如何改变其当前按钮颜色

    vue单选按钮,选中如何改变其当前按钮颜色

    这篇文章主要介绍了vue单选按钮,选中如何改变其当前按钮颜色。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • vue如何定义全局变量和全局方法实例代码

    vue如何定义全局变量和全局方法实例代码

    在项目中经常会复用一些变量和函数,比如用户的登录token,用户信息等,这时将它们设为全局的就显得很重要了,下面这篇文章主要给大家介绍了关于vue如何定义全局变量和全局方法的相关资料,需要的朋友可以参考下
    2023-04-04
  • vue使用i18n实现国际化的方法详解

    vue使用i18n实现国际化的方法详解

    这篇文章主要给大家介绍了关于vue使用i18n如何实现国际化的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • vue实现移动端多格输入框

    vue实现移动端多格输入框

    这篇文章主要为大家详细介绍了vue实现移动端多格输入框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • VUE使用axios调用后台API接口的方法

    VUE使用axios调用后台API接口的方法

    这篇文章主要介绍了VUE使用axios调用后台API接口的方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-08-08
  • vue第三方库中存在扩展运算符报错问题的解决方案

    vue第三方库中存在扩展运算符报错问题的解决方案

    这篇文章主要介绍了vue第三方库中存在扩展运算符报错问题,本文给大家分享解决方案,通过结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Vue分页组件实例代码

    Vue分页组件实例代码

    这篇文章主要为大家详细介绍了Vue分页组件的实例代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04

最新评论