vue.js之props传递参数浅析

news/2024/5/18 7:38:32

vue.js之props传递参数浅析

前段时间用vue做一个后台管理系统,其中每一页都需要一个表格来展示信息。自然就想到了将表格提取出来做成公共组件,将不同页面的数据传入进行渲染,达到复用的目的。

demo地址

1. 问题发现

在父组件中,需要向表格组件传递的数据有表格的内容数据tableData,表格的页面数据page。

<div class="content"><my-table :table-data="tableData" :page-info="pageInfo" id="myTable"></my-table>
</div>

其中tableData是个Array对象,是所有需要在表格中展示的数据对象组成的一个数组。而pageInfo是个Object对象,包含了表格页面信息。在父组件对两个数据对如下初始化,形式如下

tableData:[],
pageInfo: {current: 1, // 当前是第几页total: 100, // 数据对象的总数size: 20 // 每页显示的数量
}

按照官方文档上的说明,prop是单向绑定的,不应该在子组件内部改变prop。之所以有想修改prop中数据的冲动,主要是prop作为初始值传入后,子组件想把它当作局部数据来用。对于这种情况,官方的说法是定义一个局部变量,并用 prop 的值初始化它:

props: ['tableData', 'pageInfo'],
data() {return {tData: this.tableData,page: this.pageInfo}
}

然后根据官方文档的说法,当每次父组件更新时,子组件的所有prop都会更新为最新值。而tableData和pageInfo的信息是异步通过api从server端获取的:

{error: 0,msg: "调用成功.",data: {restrictioninfo: [...],total: 42}
}

因此当获取到数据时父组件需要改变传入子组件中的值:

me.tableData = Json.data.restrictioninfo;
me.pageInfo.total = Json.data.total;

按理说这时候子组件中的值应该更新成server返回的值,但是子组件页面的总数更新了,但table数据依然是初始化时的空数组。(黑人问号???)
image

2.赋值与绑定

首先需要定位数据是在哪个地方出了问题,于是我做了一个demo来定位问题。
首先看父组件与子组件中各元素的初始值:
image
然后当只改变父组件中数组的引用时可以看到子组件的props数组随之改变,而子组件中绑定的数组确并没有随之改变image
因此,可以发现,问题是出在了这一步

props: ['tableData', 'pageInfo'],
data() {return {tData: this.tableData,page: this.pageInfo}
}

而要弄清楚问题的根源,就得弄清楚vue文档中深入响应式原理。
image
"在Vue实例的data选项中,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为 getter/setter","每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。"文档中说了这么一大堆,简单理解就是Vue将data选项中的vm.$data.a与DOM中的vm.a进行了双向绑定,即其中一个变化,另一个也会跟着变化。在Vue源码中是由defineReactive$$1函数实现的:
image

但在子其中主要是利用了Object.defineProperty的get和set方法实现了双向绑定。而在子组件中,pros数据和子组件的$data是通过如下方式联系在一起的:

    tData: this.tableData

查询Vue源码可知this.tableData与tData之间仅仅是赋值,即"="关系
image

而上述的initData函数是在组件构建时候执行的,因此只会在create时执行一次。这也是为什么官方文档中"作为初始值传入"这一说法,因为他本就只会执行一次。当组件构建完成后,this.tableData与tData就没有半毛钱关系了,其中一个的变化并不会引起另一个变化。当然,这种说法并不准确,因为在上文中,我们动态改变父组件传入的total,子组件也"随之"改变,感觉就像是绑定在一起了啊,这又是怎么回事呢?

3.引用类型带来的假象

当然,我们还是要从官方文档出发来解决这个问题。文档中有这样一个提示:
image
这里就需要理解引用类型的概念,引用数据类型值指保存在堆内存中的对象。也就是,变量中保存的实际上的只是一个指针,这个指针指向内存中的另一个位置,该位置保存着对象。访问方式是按引用访问。例如一个js对象a,他在内存中的存储形式如下图所示:

    var a = new Object();

image

当操作时,需要先从栈中读取内存地址,然后再延指针找到保存在堆内存中的值再操作。

    a.name = 'xz';

image

引用类型变量赋值,本质上赋值的是存储在栈中的指针,将指针复制到栈中未新变量分配的空间中,而这个指针副本和原指针指向存储在堆中的同一个对象;赋值操作结束后,两个变量实际上将引用同一个对象。因此,在使用时,改变其中的一个变量的值,将影响另一个变量。

    var b = a;

image

在了解了引用类型之后,我们在来看看上文提到的动态改变传入子组件前后内存中的情况:

me.tableData = Json.data.restrictioninfo;
me.pageInfo.total = Json.data.total;
========================================
props: ['tableData', 'pageInfo'],
data() {return {tData: this.tableData,page: this.pageInfo}
}

首先对tableData的改变是改变了其引用的指针,而对pageInfo则改变了其中一个属性的值,因此动态改变前:
image
动态改变后:
image
这样就解释了为什么子组件页面的总数更新了,但table数据依然是初始化时的空数组。因为引用类型的存在,我们动态改变父组件传入的total,子组件也"随之"改变了。


https://dhexx.cn/news/show-2145457.html

相关文章

Python 黑帽编程 4.2 Sniffer之数据本地存储和加载

在上一节&#xff0c;我们完成了编写一个简易的Sniffer的第一步——数据捕获。 很多时候&#xff0c;我们需要将捕获的数据先保存到磁盘上&#xff0c;之后再使用工具或者自己编写代码来进行详细分析。 本节我们在上一节的基础上来讲解保存捕获数据的方式&#xff0c;当然使用t…

【Oracle】迁移含有BLOG类型的字段的表

日常数据库迁移过程中&#xff0c;发现dmp文件中的表&#xff0c;如果表含有blog类型的字段&#xff0c;无法进行迁移。以下是我迁移含有blog类型字段表的经验分享‘使用PLSQL Developer进行导出接着选择需要导出的表点击【Export】即可导出到a.sql文件中。导出后&#xff0c;再…

IDEA修改pom.xml文件不自动下载

1.手动让IDEA下载jar或者从本地查找jar包 2.设置自动下载jar包或者从本地查找 转载于:https://www.cnblogs.com/htzsyy/p/11187238.html

AgileEAS.NET平台开发实例-药店系统-BLL层分析

介绍 上篇我们分析了AgileEAS.NET平台的DAL层的设计与相关的使用说明分析&#xff0c;本篇我们来分析下业务逻辑层/服务层的设计与分析&#xff0c;并且分析下如何抽离单独的业务逻辑 层&#xff0c;分离出单独的分布式访问服务支持。我们主要是分析如何设计出严格的基于现有DA…

java IO(四):FileReader和InputStreamReader和StreamDecoder

之所以把这三个放在一起说&#xff0c;是因为他们密切相关。 首先要说明为何在有FileInputStream的情况下&#xff0c;jdk还要设置这几个流。 实际测试中发现&#xff0c;除了ascii码编码的字符(如英文字符、数字字符)外&#xff0c;对于其他字符(如汉字字符、阿拉伯语字符)&am…

进程管理常用命令(2)

转载于:https://www.cnblogs.com/jacky1982/p/9080315.html

带你开发一个日历控件

首发我的博客 - https://blog.cdswyda.com/post/2017121010 日历控件多的不胜枚举&#xff0c;为什么我们还要再造一个轮子呢&#xff1f; 因为大多数日历控件都是用于选择日期的&#xff0c;有种需求是要在日历上展示各种各样的内容&#xff0c;这样的日历控件较少&#xff0c…

1、iptables-netfilter基础

1、iptables: 包过滤型防火墙功能、四表五链 2、iptables规则、规则管理工具、iptables命令 3、iptables链管理、规则管理、查看等 4、iptables匹配条件、目标、显式扩展、保存及重载规则参考&#xff1a;马哥教育和朱双印个人日志http://www.zsythink.net/archives/tag/iptabl…

走进Android Binder机制(驱动篇上)

2019独角兽企业重金招聘Python工程师标准>>> Binder的实现是比较复杂的&#xff0c;想要完全弄明白是怎么一回事&#xff0c;并不是一件容易的事情。 这里面牵涉到好几个层次&#xff0c;每一层都有一些模块和机制需要理解。这部分内容预计会分为三篇文章来讲解。本…

可视化展示js插件

2019独角兽企业重金招聘Python工程师标准>>> 1.Echarts.js http://echarts.baidu.com/ 版本3的 http://echarts.baidu.com/echarts2/doc/example.html 版本2的 目前业内使用最多的可视化插件&#xff0c;文档看起来有点费劲&#xff0c;好在案例比较多 <!DOCTYPE…