|
導讀網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立... 網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立在超文本基礎之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。 本篇文章給大家帶來的內容是關于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>代碼解讀:
結果:
頁面初始化后,姓名、性別、生日都顯示為空,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初始化時會遞歸地遍歷data所有的屬性,并使用Object.defineProperty把這些屬性全部轉為getter/setter,用于實現雙向綁定。官方文檔在Reactivity in Depth一章明確有說:
還順便解釋了一下為什么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的文檔:
大概梳理一下: 1.props是單向數據流:父組件的數據變化,通過props實時反應在子組件中,反之不然2.不允許在子組件中直接操作props3.可以變相操作props(1)在data中聲明局部變量,并用props初始化,弊端:局部變量不隨著props更新而更新(2)在computed中對props值轉換后輸出以上就是Vue中用props給data賦初始值時遇到的問題及解決方法的詳細內容,更多請關注php中文網其它相關文章! 網站建設是一個廣義的術語,涵蓋了許多不同的技能和學科中所使用的生產和維護的網站。 |
溫馨提示:喜歡本站的話,請收藏一下本站!