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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Domain-Driven Design Distilled
Vaughn Vernon / Addison-Wesley Professional / 2016-6-2 / USD 36.99
Domain-Driven Design (DDD) software modeling delivers powerful results in practice, not just in theory, which is why developers worldwide are rapidly moving to adopt it. Now, for the first time, there......一起来看看 《Domain-Driven Design Distilled》 这本书的介绍吧!