Vue Component 之 Prop
栏目: JavaScript · 发布时间: 6年前
内容简介: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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。