Vue Component 之 Prop
栏目: JavaScript · 发布时间: 7年前
内容简介:Component 若只有一層,那問題不大,若牽涉到 component 包含 component,就會牽涉到一個基本問題:該如何將 data 由外層 component 傳給內層 component ?這時候就要使用 Vue Component 的 Prop,這也是 Vue 從 React 學來的部分。Vue 2.5.17
Component 若只有一層,那問題不大,若牽涉到 component 包含 component,就會牽涉到一個基本問題:該如何將 data 由外層 component 傳給內層 component ?
這時候就要使用 Vue Component 的 Prop,這也是 Vue 從 React 學來的部分。
Version
Vue 2.5.17
Static Prop
一樣是老梗 Hello World,但這次 data 並不是在 Vue Instance 內定義,而是由外層傳進來。
Static Prop
將 靜態資料 由 prop 傳進 component
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Static Prop</title>
</head>
<body>
<div id="app">
<hello-world greeting="Hello" user-name="World"></hello-world>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="HelloWorld.js"></script>
<script src="index.js"></script>
</html>
第 9 行
<hello-world greeting="Hello" user-name="World"></hello-world>
一樣使用 <hello-world></hello-world> Component,但這次透過自訂的 greeting 與 user-name 將 data 由 component 的外層傳進來。
index.js
new Vue({
el: '#app'
});
建立 Vue Instance。
HelloWorld.js
Vue.component('HelloWorld', {
props: [
'greeting',
'userName'
],
template: `
<span>{{ greeting }} {{ userName }}</span>
`,
});
第 2 行
props: [ 'greeting', 'userName', ],
若要由 Component 的外層傳 data 進來,則要在 Vue Instance 使用 props property。
props 為 array,每個 prop 使用 string 定義。
第 6 行
template: `
<span>{{ greeting }} {{ userName }}</span>
`,
在 props 宣告過 greeting 與 userName prop 之後,就可在 template 如同使用 data 的 model 了。
在 prop 使用上,有一點要注意:
- Props 若在 JavaScript 使用了 CamelCase,在 Vue Template 會自動改成 kebab-case 才能用 (W3C 建議)
Vue Template 能綁定的資料,除了能使用 data 、 computed 外,目前還多了 props
Dynamic Prop
剛剛傳進 prop 的值是寫死的,能夠動態以 MVVM 的 model 結合 prop 嗎 ?
Dynamic Prop
將 動態資料 (MVVM 的 model ) 傳進 prop
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dynamic Prop</title>
</head>
<body>
<div id="app">
<ul>
<hello-world v-for="userName in userNames" greeting="Hello" :user-name="userName"></hello-world>
</ul>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="HelloWorld.js"></script>
<script src="index.js"></script>
</html>
第 9 行
<ul> <hello-world v-for="userName in userNames" greeting="Hello" :user-name="userName"></hello-world> </ul>
想將 userName 綁定到 user-name prop,必須使用 : Attribute Binding。
而 userName 則由 v-for 來自於 userNames 。
index.js
new Vue({
el: '#app',
data: {
userNames: [
'Sam',
'Kevin',
'John'
]
}
});
userNames 是 Vue Instance 的 data 所定義的 model。
HelloWorld.js
Vue.component('HelloWorld', {
props: [
'greeting',
'userName'
],
template: `
<li>{{ greeting }} {{ userName }}</li>
`
});
與 Static Prop 的 HelloWorld.js 完全一樣。
透過 Dynamic Prop,我們就能將 component 外層的 model 透過 prop 傳進 component
Unidirectional Dataflow
Vue Prop 是 單向數據流 ,也就是 data 只能從 component 外層傳進 component,而無法由內層 component 傳到外層 component。
若要將 data 從內層 component 傳到外層 component,則要使用 event
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Unidirectional Dataflow (Warning)</title>
</head>
<body>
<div id="app">
{{ counter }}
<button @click="add">+</button>
<my-counter :inner-counter="counter"></my-counter>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="Counter.js"></script>
<script src="index.js"></script>
</html>
第 9 行
{{ counter }}
<button @click="add">+</button>
外層有自己 counter 計算。
11 行
<my-counter :inner-counter="counter"></my-counter>
想要將 counter model 透過 inner-counter prop 傳進 MyCounter component。
index.js
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
add() {
this.counter++;
}
}
});
第 3 行
data: {
counter: 0
},
methods: {
add() {
this.counter++;
}
}
上層有自己的 counter 計算。
Counter.js
Vue.component('MyCounter', {
template: `
<div>
<h2>{{ innerCounter }}</h2>
<button @click="add">+</button>
</div>
`,
props: [
'innerCounter'
],
methods: {
add() {
this.innerCounter++;
}
}
});
第 8 行
props: [ 'innerCounter' ],
定義 innerCounter prop。
11 行
methods: {
add() {
this.innerCounter++;
}
}
直接 innterCounter prop 做累加。
這種寫法雖然可以執行,但有個淺在問題:由於 Vue 的 Unidirectional Dataflow,每次 component 外層的 model 改變,都會傳入內層 component,因而會覆蓋掉原本 component 的資料。
Vue 也在 run-time 提出警告,建議不要對 prop 直接修改,因為 data 隨時會被外層 component 蓋掉。
由於不建議直接改 prop,Vue 官網建議兩種 Pattern 使用 prop:
- 改用 Data
- 改用 Computed
改用 Data
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Unidirectional Dataflow (Data)</title>
</head>
<body>
<div id="app">
{{ counter }}
<button @click="add">+</button>
<p></p>
<my-counter :start-counter="counter"></my-counter>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="Counter.js"></script>
<script src="index.js"></script>
</html>
12 行
<my-counter :start-counter="counter"></my-counter>
由 inner-counter 改成 start-counter prop。
index.js
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
add() {
this.counter++;
}
}
});
與之前的 index.js 完全一樣。
Counter.js
Vue.component('MyCounter', {
template: `
<div>
<h2>{{ innerCounter }}</h2>
<button @click="add">+</button>
</div>
`,
props: [
'startCounter'
],
data() {
return {
innerCounter: this.startCounter
}
},
methods: {
add() {
this.innerCounter++;
}
}
});
第 8 行
props: [ 'startCounter' ],
改成 startCounter prop。
11 行
data() {
return {
innerCounter: this.startCounter
}
},
由於 prop 不適合直接修改,因此我們另外宣告了 innerCounter model。
startCounter 的用途只在於初始化 innerCounter model。
由原本直接修改 prop,改成修改 Data,prop 只退化用來初始化 model
改用 Computed
使用 Data 的優點內層 component 的資料不會受外層影響,但缺點是內層 component 的資料不會與外層連動。
若有內外層 data 連動的需求,Vue 則建議改用 computed。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Unidirectional Dataflow (Computed)</title>
</head>
<body>
<div id="app">
{{ counter }}
<button @click="add">+</button>
<my-counter :start-counter="counter"></my-counter>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="Counter.js"></script>
<script src="index.js"></script>
</html>
11 行
<my-counter :start-counter="counter"></my-counter>
一樣使用 start-counter prop 傳入資料。
index.js
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
add() {
this.counter++;
}
}
});
index.js 一樣也沒變。
Counter.js
Vue.component('MyCounter', {
template: `
<div>
<h2>{{ countDoubled }}</h2>
</div>
`,
props: [
'startCounter'
],
computed: {
countDoubled() {
return this.startCounter * 2;
}
}
});
10 行
computed: {
countDoubled() {
return this.startCounter * 2;
}
}
由原本的 innerCounter 改成 countDoubled() 。
第 2 行
template: `
<div>
<h2>{{ countDoubled }}</h2>
</div>
`,
Data Binding 改成 countDoubled() 。
如此內層 component 的 data 就與外層同步
2 種寫法都各有適用場景,視需求決定要使用
Conclusion
- 透過 prop,data 能由外層傳進 Component
- Dynamic Prop 能將 MVVM 的 model 也綁定 prop,不再只是寫死的資料
- Prop 只支援 Unidirectional Dataflow,也就是外層的 data 改變,會影響到內層 component,但內層 component 的 data 改變,不會影響到外層 component
- 若要內層 component 的 data 改變,會影響到外層 component,就必須使用 event
Sample Code
完整的範例可以在我的 GitHub 上找到
Reference
以上所述就是小编给大家介绍的《Vue Component 之 Prop》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
尽在双11:阿里巴巴技术演进与超越
阿里巴巴集团双11技术团队 / 电子工业出版社 / 2017-4 / 79
“双 11”,诞生于杭州,成长于阿里,风行于互联网,成就于新经济,贡献于全世界。 从 2009 年淘宝商城起,双 11 已历经八年。每年的双 11 既是当年的结束,又是走向未来的起点。技术的突破创新,商业模式的更替交互,推动着双 11 迈步向前。 《尽在双11——阿里巴巴技术演进与超越》是迄今唯一由阿里巴巴集团官方出品、全面阐述双 11 八年以来在技术和商业上演进和创新历程的书籍。内容......一起来看看 《尽在双11:阿里巴巴技术演进与超越》 这本书的介绍吧!