手机版

解决Vue中用道具给数据赋值时遇到的问题

时间:2021-08-28 来源:互联网 编辑:宝哥软件园 浏览:

前言

前段时间做了一个运营项目,上线后产品反馈页面被错误掩埋。调查过程中发现,问题是由Vue中的数据初值引起的,数据初值来源于道具。为了描述方便,问题抽象如下:

一.现象

代码:

!doctype html lang=' en ' head metacarset=' utf-8 ' title Script src=' http:https://cdn.bootcss.com/vue/2.5.16/vue.min.js'/Script/head dydiv id=' app ' user-info : user-data=' user '/user-info/div Script//全局组件let user info=vue.component(' user info ',{ name: 'user-info ',prop s : { userdata : Object },data(){ return { userName 3: this . userdata . name },Template//Vue实例newvue ({el:' # app ',data: {user3360 {name3360 ' ',gender3360 ' ',birthday:''}),创建了(){this。getuser data();},方法: { getuser data(){ settimeout(()={ this。用户={name:' Yu Yongyu ',gender: '男',生日:' 1991-7'}},500)},组件333/脚本/正文/html代码解释:

根组件数据中有一个对象:用户,它包含三个属性:姓名、性别和生日。初始值都是空字符串,用来模拟api异步请求。500毫秒后,当用户被重新分配时,所有三个属性不再为空,以声明子组件userInfo。道具中有一个对象userData,用于接收父组件的用户。数据中有一个变量userName,初始值来自userData.name结果:

页面初始化后,姓名、性别和生日都是空白的。500毫秒后,性别和生日显示正常结果,但只有名字没有变化。

为什么会这样?

我最初的想法是:用户名是一个字符串,属于基本数据类型。用于分配子组件数据中的userName,属于基础数据类型分配。因此,当父组件中的用户名改变时,子组件中的用户名不会随之改变。

是这样吗?所以我决定把user.name改成一个对象,通过引用数据类型赋值,然后观察它是否符合预期。代码如下:

!doctype HTML lang=' en ' head meta charset=' utf-8 ' title用props初始化数据中的变量-对象表单/title Script src=' http:https://cdn.bootcss.com/vue/2.5.16/vue.min.js'/脚本/head dydiv id=' app ' user-info : user-data=' user '/user-info/div Script//全局组件让user info=vue.component(' user info ',{ name: 'user-info ',props: { userData: Object },data(){ return { username 33366//Vue实例newvue ({el:' # app ',data : { user 3360 { name 3360 { text : ' ' },gender: ' ',birthday:''}),创建了(){this。getuserdata () },方法: { getuser data(){ settimeout(()={ this。用户={ name : { text : ' Yu Yong Yu ' },gender:' male ',生日3360' 1991-7'},500) /script/body/html运行结果:名字还是没有值,跟第一个结果一样!

二、原因

那么,是什么原因呢?我无法理解。后来和朋友讨论的时候,有人问:会不会是初始化的时候数据被深度复制了?

我觉得这个解释比较靠谱,于是就去搜集证据。首先,我去Vue官网查看了数据文档,包括:

当你看到‘递归’这个词的时候,基本可以断定上面的推断是正确的,因为深度复制的核心原理就是递归。

原来Vue在初始化的时候会递归遍历数据的所有属性,用Object.defineProperty把这些属性全部转换成getter/setter,用来实现双向绑定。在《深度反应》一章中,官方文件明确指出:

这也解释了为什么Vue不支持IE8: IE8不支持Object.defineProperty

第三,解决方案

由于数据的深度复制,数据不能随着道具的变化而更新,我们自然会想到Vue中的两个监控功能:watch和computed。

按照以下步骤修改代码,并观察结果:

!doctype html lang=' en ' head meta charset=' utf-8 ' title solution:watch,computed/title Script src=' http:https://cdn.bootcss.com/vue/2.5.16/vue.min.js'/Script/head dydiv id=' app ' user-info : user-data=' user '/user-info/div Script//global component let user info=vue.component(' user info ',{ name: 'user-info ',prop s : { userdata : Object },data(){ Return { username : this。userdata.name}},watch 3360 { ' user data . name ' : function(val){//听属性this.userName=val in props} },template : ` div div name(watch):{ { username } }/div name(计算得出):{{computed username}}/div div性别:{{ userData.gender }}/div生日:{{ userData .生日}}/div/div`}) //Vue实例newvue ({el:' # app ',data: { user3360 { name3360 ' ',gender3360 ' ',生日3: ' ' }),创建了(){thisgetuser data();},方法: { getuser data(){ settimeout(()={ this。用户={name:' Yu Yongyu ',gender: '男',生日:' 1991-7'}},500)},组件333/脚本/正文/htmlrunning结果

完美!

第四,总结:Vue中道具的要点

事后,我仔细翻了翻关于道具的文件:

粗略梳理一下:

1.props是单向数据流:父组件的数据变化通过props实时反映在子组件中,反之亦然

2.不允许在子组件中直接操作道具

3.你可以伪装操作道具

(1)在数据中声明局部变量,并用道具初始化。缺点:局部变量没有用道具更新

(2)转换计算出的道具值并输出

以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

版权声明:解决Vue中用道具给数据赋值时遇到的问题是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。