Vue中用props给data赋初始值遇到的问题解决
前言
前段时间做一个运营活动的项目,上线后产品反馈页面埋点不对,在排查过程中发现,问题竟然是由于Vue中的data初始值导致,而data的初始值来自于props。为方便描述,现将问题抽象如下
一、现象
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用props初始化data中变量</title> <script src="https://cdn.bootcss./vue/2.5.16/vue.min.js"></script> </head> <body> <div id="app"> <user-info :user-data="user"></user-info> </div> <script> //全局组件 let userInfo = Vue.ponent('userInfo' ,{ name: 'user-info', props: { userData: Object }, data() { return { userName: this.userData.name } }, template: ` <div> <div>姓名{{userName}}</div> <div>性别{{userData.gender}}</div> <div>生日{{userData.birthday}}</div> </div> ` }); //Vue实例 new Vue({ el: '#app', data: { user: { name: '', gender: '', birthday: '' } }, created(){ this.getUserData(); }, methods:{ getUserData(){ setTimeout(()=>{ this.user = { name: '于永雨', gender: '男', birthday: '1991-7' } }, 500) } }, ponents: { userInfo } }); </script> </body> </html>
代码解读
- 根组件data中有一个对象user,包含三个属性name、gender、birthday,初始值都为空字符串
- 模拟api异步请求,500毫秒后对user的重新赋值,三个属性都不再为空
- 声明一个子组件userInfo,props中有一个对象userData,用于接收父组件的user;data中有一个变量userName,初始值来自于userData.name
结果
页面初始化后,姓名、性别、生日都显示为空,500毫秒后性别和生日显示正常结果,仅姓名没有变化。
为什么会这样呢?
我最初的想法user.name是String,属于基本数据类型,用它给子组件data中userName赋值,属于基本数据类型赋值,所以当父组件中user.name变化时,子组件中userName并不会随之变化。
是这样的吗?于是我决定将user.name改为对象,通过引用数据类型赋值,然后观察是否符合预期。代码如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用props初始化data中变量-对象形式</title> <script src="https://cdn.bootcss./vue/2.5.16/vue.min.js"></script> </head> <body> <div id="app"> <user-info :user-data="user"></user-info> </div> <script> //全局组件 let userInfo = Vue.ponent('userInfo' ,{ name: 'user-info', props: { userData: Object }, data() { return { userName: this.userData.name } }, template: ` <div> <div>姓名{{userName.text}}</div> <div>性别{{userData.gender}}</div> <div>生日{{userData.birthday}}</div> </div> ` }); //Vue实例 new Vue({ el: '#app', data: { user: { name: {text: ''}, gender: '', birthday: '' } }, created(){ this.getUserData(); }, methods:{ getUserData(){ setTimeout(()=>{ this.user = { name: {text: '于永雨'}, gender: '男', birthday: '1991-7' } }, 500) } }, ponents: { userInfo } }); </script> </body> </html>
运行结果姓名仍然没有值,和第一次结果一样!!!
二、原因
那么,原因到底是什么呢?百思不得解,后来和小伙伴们讨论时,有人提出会不会因为data在初始化时深拷贝?
我觉得这种解释比较靠谱,于是去收集证据,去Vue官网翻了一下关于data的文档,其中
当看到"递归地"那个词,基本上就能断定上面的推论是正确的,因为深拷贝的核心原理就是递归。
原来,Vue初始化时会递归地遍历data所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter,用于实现双向绑定。官方文档在一章明确有说
还顺便解释了一下为什么Vue不支持IE8的原因IE8不支持Object.defineProperty。
三、解决办法
既然因为data深拷贝的原因,data无法随着props的变化而更新,我们很自然的就想到Vue中有监听作用的两个功能watch、puted。
修改代码如下,观察结果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>解决方案watch、puted</title> <script src="https://cdn.bootcss./vue/2.5.16/vue.min.js"></script> </head> <body> <div id="app"> <user-info :user-data="user"></user-info> </div> <script> //全局组件 let userInfo = Vue.ponent('userInfo' ,{ name: 'user-info', props: { userData: Object }, data() { return { userName: this.userData.name } }, puted: { putedUserName(){ return this.userData.name } }, watch: { 'userData.name': function (val) {//监听props中的属性 this.userName = val; } }, template: ` <div> <div>姓名(watch){{ userName }}</div> <div>姓名(puted){{ putedUserName }}</div> <div>性别{{ userData.gender }}</div> <div>生日{{ userData.birthday }}</div> </div> ` }); //Vue实例 new Vue({ el: '#app', data: { user: { name: '', gender: '', birthday: '' } }, created(){ this.getUserData(); }, methods:{ getUserData(){ setTimeout(()=>{ this.user = { name: '于永雨', gender: '男', birthday: '1991-7' } }, 500) } }, ponents: { userInfo } }); </script> </body> </html>
运行结果
完美!!!
四、关于Vue中props的要点
事后又仔细翻了一下关于props的文档
大概梳理一下
1.props是单向数据流父组件的数据变化,通过props实时反应在子组件中,反之不然
2.不允许在子组件中直接操作props
3.可以变相操作props
(1)在data中声明局部变量,并用props初始化,弊端局部变量不随着props更新而更新
(2)在puted中对props值转换后输出
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持狼蚁SEO。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程