首頁 > web前端 > js教程 > 主體

Vue中用props為data賦初始值時遇到的問題及解決方法

不言
發布: 2018-11-27 14:54:24
轉載
4561 人瀏覽過

這篇文章帶給大家的內容是關於Vue中用props給data賦初始值時遇到的問題及解決方法,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

前段時間做一個營運活動的項目,上線後產品回饋頁面埋點不對,在排查過程中發現,問題竟然是由於Vue中的data初始值導致,而data的初始值來自於props。為方便描述,現將問題抽像如下:

一、現象

#程式碼:

nbsp;html>


    <meta>
    <title>用props初始化data中变量</title>
    <script></script>


<div>
    <user-info></user-info>
</div>
<script>
    //全局组件
    let userInfo = Vue.component(&#39;userInfo&#39; ,{
        name: &#39;user-info&#39;,
        props: {
            userData: Object
        },
        data() {
          return {
              userName: this.userData.name
          }
        },
        template: `
            <div>
                <div>姓名:{{userName}}
                <div>性别:{{userData.gender}}
                <div>生日:{{userData.birthday}}
            
        `
    });

    //Vue实例
    new Vue({
        el: &#39;#app&#39;,
        data: {
            user: {
                name: &#39;&#39;,
                gender: &#39;&#39;,
                birthday: &#39;&#39;
            }
        },
        created(){
           this.getUserData();
        },
        methods:{
            getUserData(){
                setTimeout(()=>{
                    this.user = {
                        name: &#39;于永雨&#39;,
                        gender: &#39;男&#39;,
                        birthday: &#39;1991-7&#39;
                    }
                }, 500)
            }
        },
        components: {
            userInfo
        }
    });
</script>

登入後複製

程式碼解讀:

Vue中用props為data賦初始值時遇到的問題及解決方法

#根元件data中有一個物件:user,包含三個屬性:name、gender、birthday,初始值都為空字串

模擬api非同步請求, 500毫秒後對user的重新賦值,三個屬性都不再為空

#聲明一個子元件userInfo,props中有一個物件userData,用於接收父元件的user; data中有一個變數userName,初始值來自於userData.name

結果:

Vue中用props為data賦初始值時遇到的問題及解決方法##頁面初始化後,姓名、性別、生日都顯示為空,500毫秒後性別和生日顯示正常結果,僅姓名沒有變化。

為什麼會這樣呢?

我最初的想法:user.name是String,屬於基本資料類型,用它給子元件data中userName賦值,屬於基本資料類型賦值,所以當父元件中user.name變化時,子元件中userName並不會隨之變化。

是這樣的嗎?於是我決定將user.name改為對象,透過引用資料類型賦值,然後觀察是否符合預期。程式碼如下:

nbsp;html>


    <meta>
    <title>用props初始化data中变量-对象形式</title>
    <script></script>


<div>
    <user-info></user-info>
</div>
<script>
    //全局组件
    let userInfo = Vue.component(&#39;userInfo&#39; ,{
        name: &#39;user-info&#39;,
        props: {
            userData: Object
        },
        data() {
          return {
              userName: this.userData.name
          }
        },
        template: `
            <div>
                <div>姓名:{{userName.text}}
                <div>性别:{{userData.gender}}
                <div>生日:{{userData.birthday}}
            
        `
    });


    //Vue实例
    new Vue({
        el: &#39;#app&#39;,
        data: {
            user: {
                name: {text: &#39;&#39;},
                gender: &#39;&#39;,
                birthday: &#39;&#39;
            }
        },
        created(){
           this.getUserData();
        },
        methods:{
            getUserData(){
                setTimeout(()=>{
                    this.user = {
                        name: {text: &#39;于永雨&#39;},
                        gender: &#39;男&#39;,
                        birthday: &#39;1991-7&#39;
                    }
                }, 500)
            }
        },
        components: {
            userInfo
        }
    });
</script>

登入後複製

運行結果:姓名仍然沒有值,和第一次結果一樣! ! ! Vue中用props為data賦初始值時遇到的問題及解決方法

二、原因

那麼,原因到底是什麼呢?百思不得解,後來和朋友討論時,有人提出:會不會因為data在初始化時深拷貝?

我覺得這種解釋比較可靠,於是去收集證據,首先去Vue官網翻了一下關於data的文檔,其中:


當看到"遞歸地"那個詞,基本上就能斷定上面的推論是正確的,因為深拷貝的核心原理就是遞歸

原來,Vue中用props為data賦初始值時遇到的問題及解決方法Vue初始化時會遞歸地遍歷data所有的​​屬性,並使用Object.defineProperty把這些屬性全部轉為getter/setter,用來實現雙向綁定。 官方文件在Reactivity in Depth一章中明確有說:

#還順便解釋了為什麼Vue不支持IE8的原因:IE8不支援Object.defineProperty。

三、解決方法

既然因為data深拷貝的原因,data無法隨著props的變化而更新,我們很自然的就想到Vue中用props為data賦初始值時遇到的問題及解決方法Vue中有監聽作用的兩個功能:watch、computed

修改程式碼如下,觀察結果:

nbsp;html>


    <meta>
    <title>解决方案:watch、computed</title>
    <script></script>


<div>
    <user-info></user-info>
</div>
<script>
    //全局组件
    let userInfo = Vue.component(&#39;userInfo&#39; ,{
        name: &#39;user-info&#39;,
        props: {
            userData: Object
        },
        data() {
          return {
            userName: this.userData.name
          }
        },
        computed: {
            computedUserName(){
                return this.userData.name
            }
        },
        watch: {
            &#39;userData.name&#39;: function (val) {//监听props中的属性
                this.userName = val;
            }
        },
        template: `
            <div>
                <div>姓名(watch):{{ userName }}
                <div>姓名(computed):{{ computedUserName }}
                <div>性别:{{ userData.gender }}
                <div>生日:{{ userData.birthday }}
            
        `
    });


    //Vue实例
    new Vue({
        el: &#39;#app&#39;,
        data: {
            user: {
                name: &#39;&#39;,
                gender: &#39;&#39;,
                birthday: &#39;&#39;
            }
        },
        created(){
           this.getUserData();
        },
        methods:{
            getUserData(){
                setTimeout(()=>{
                    this.user = {
                        name: &#39;于永雨&#39;,
                        gender: &#39;男&#39;,
                        birthday: &#39;1991-7&#39;
                    }
                }, 500)
            }
        },
        components: {
            userInfo
        }
    });
</script>

登入後複製

運行結果

完美! ! !

四、總結:關於Vue中props的要點

###事後又仔細翻了一下關於props的文檔:############## #######大概梳理一下:######1.props是單向資料流:父元件的資料變化,透過props即時反應在子元件中,反之不然######2 .不允許在子元件中直接操作props######3.可以變相操作props######(1)在data中宣告局部變量,並用props初始化,###弊端:局部變數不隨著props更新而更新#########(2)在computed中對props值轉換後輸出#########

以上是Vue中用props為data賦初始值時遇到的問題及解決方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板