Vue中用props给data赋初始值时会遇到什么问题

这篇文章给大家分享的是有关Vue中用props给data赋初始值时会遇到什么问题的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。

网站建设哪家好,找成都创新互联!专注于网页设计、网站建设、微信开发、小程序设计、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了临夏免费建站欢迎大家使用!

前段时间做一个运营活动的项目,上线后产品反馈页面埋点不对,在排查过程中发现,问题竟然是由于Vue中的data初始值导致,而data的初始值来自于props。为方便描述,现将问题抽象如下:

一、现象

代码:

<!DOCTYPE html>
<html>
<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>

代码解读:

  1. 根组件data中有一个对象:user,包含三个属性:name、gender、birthday,初始值都为空字符串

  2. 模拟api异步请求,500毫秒后对user的重新赋值,三个属性都不再为空

  3. 声明一个子组件userInfo,props中有一个对象userData,用于接收父组件的user;data中有一个变量userName,初始值来自于userData.name

结果:

Vue中用props给data赋初始值时会遇到什么问题

页面初始化后,姓名、性别、生日都显示为空,500毫秒后性别和生日显示正常结果,仅姓名没有变化。

为什么会这样呢?

我最初的想法:user.name是String,属于基本数据类型,用它给子组件data中userName赋值,属于基本数据类型赋值,所以当父组件中user.name变化时,子组件中userName并不会随之变化。

是这样的吗?于是我决定将user.name改为对象,通过引用数据类型赋值,然后观察是否符合预期。代码如下:

<!DOCTYPE html>
<html>
<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中用props给data赋初始值时会遇到什么问题

当看到"递归地"那个词,基本上就能断定上面的推论是正确的,因为深拷贝的核心原理就是递归

原来,Vue初始化时会递归地遍历data所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter,用于实现双向绑定。官方文档在Reactivity in Depth一章明确有说:

Vue中用props给data赋初始值时会遇到什么问题

还顺便解释了一下为什么Vue不支持IE8的原因:IE8不支持Object.defineProperty。

三、解决办法

既然因为data深拷贝的原因,data无法随着props的变化而更新,我们很自然的就想到Vue中有监听作用的两个功能:watch、computed
修改代码如下,观察结果:

<!DOCTYPE html>
<html>
<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>

四、总结:关于Vue中props的要点

事后又仔细翻了一下关于props的文档:

Vue中用props给data赋初始值时会遇到什么问题

大概梳理一下:

1.props是单向数据流:父组件的数据变化,通过props实时反应在子组件中,反之不然
2.不允许在子组件中直接操作props
3.可以变相操作props
(1)在data中声明局部变量,并用props初始化,弊端:局部变量不随着props更新而更新
(2)在computed中对props值转换后输出

感谢各位的阅读!关于Vue中用props给data赋初始值时会遇到什么问题就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到吧!

本文标题:Vue中用props给data赋初始值时会遇到什么问题
浏览路径:https://www.cdcxhl.com/article44/jgohee.html

成都网站建设公司_创新互联,为您提供网站排名自适应网站网站营销营销型网站建设网站设计公司网页设计公司

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

成都网站建设