这篇文章主要为大家详细介绍了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.com/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.component('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)
}
},
components: {
userInfo
}
});
</script>
</body>
</html>
代码解读:
结果:
【图片暂缺】
页面初始化后,姓名、性别、生日都显示为空,500毫秒后性别和生日显示正常结果,仅姓名没有变化。
为什么会这样呢?
是这样的吗?于是我决定将user.name改为对象,通过引用数据类型赋值,然后观察是否符合预期。代码如下:
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用props初始化data中变量-对象形式</title>
<script src="https://cdn.bootcss.com/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.component('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)
}
},
components: {
userInfo
}
});
</script>
</body>
</html>
运行结果:姓名仍然没有值,和第一次结果一样!!!
那么,原因到底是什么呢?百思不得解,后来和小伙伴们讨论时,有人提出:会不会因为data在初始化时深拷贝?
我觉得这种解释比较靠谱,于是去收集证据,首先去Vue官网翻了一下关于data的文档,其中:
【图片暂缺】
当看到"递归地"那个词,基本上就能断定上面的推论是正确的,因为深拷贝的核心原理就是递归。
原来,Vue初始化时会递归地遍历data所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter,用于实现双向绑定。官方文档在Reactivity in Depth一章明确有说:
【图片暂缺】
还顺便解释了一下为什么Vue不支持IE8的原因:IE8不支持Object.defineProperty。
既然因为data深拷贝的原因,data无法随着props的变化而更新,我们很自然的就想到Vue中有监听作用的两个功能:watch、computed。
修改代码如下,观察结果:
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>解决方案:watch、computed</title>
<script src="https://cdn.bootcss.com/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.component('userInfo' ,{
name: 'user-info',
props: {
userData: Object
},
data() {
return {
userName: this.userData.name
}
},
computed: {
computedUserName(){
return this.userData.name
}
},
watch: {
'userData.name': function (val) {//监听props中的属性
this.userName = val;
}
},
template: `
<div>
<div>姓名(watch):{{ userName }}</div>
<div>姓名(computed):{{ computedUserName }}</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)
}
},
components: {
userInfo
}
});
</script>
</body>
</html>
运行结果
【图片暂缺】
完美!!!
事后又仔细翻了一下关于props的文档:
【图片暂缺】
大概梳理一下:
1.props是单向数据流:父组件的数据变化,通过props实时反应在子组件中,反之不然
2.不允许在子组件中直接操作props
3.可以变相操作props
(1)在data中声明局部变量,并用props初始化,弊端:局部变量不随着props更新而更新
(2)在computed中对props值转换后输出
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持四海网。
本文来自:http://www.q1010.com/184/6498-0.html
注:关于Vue中用props给data赋初始值遇到的问题解决的内容就先介绍到这里,更多相关文章的可以留意四海网的其他信息。
关键词:vue.js
四海网收集整理一些常用的php代码,JS代码,数据库mysql等技术文章。