使用props
在Vue中父組件向子組件中傳送數據是通過props實現的,一個簡單的使用props的例子:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component :foo-message="fooMessage"></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: ['fooMessage'], 18 template: '<div> {{ fooMessage }} </div>' 19 }; 20 21 var vm = new Vue({ 22 components: { 23 'foo-component': fooComponent 24 }, 25 el: '#app', 26 data: { 27 fooMessage: 123 28 } 29 }); 30 31 </script> 32 </body> 33 </html>
為什么要有props驗證
但是上面這種方式是建立在大家都很遵守約定的情況下的,想象一下當有一個人要使用foo-component組件的時候,他可能對於其要接受的參數有什么要求並不是很清楚,因此傳入的參數可能會在開發子組件的人的意料之外,程序就會發生錯誤,就像我們在函數調用之前先檢查一下函數一樣,props也可以進行一個預先檢查。
平時調用函數的時候在函數開頭的地方都是一坨糊糊的參數檢查,這種寫法很不好了,所有后來就有了校驗器模式(別去百度了,我隨口取的名字),校驗器模式就是指把在函數開頭的對參數校驗的部分提取出來作為一個公共的部分來管理,讓一個什么東西來專門負責校驗,當類型不正確的時候就拋個異常根本不去調用這個函數,很多框架設計時都是這么設計的(Spring MVC、Struts2等等),props也提供了這個功能,想一下如果沒有這個功能的話,為了保證正確性我們可能需要在每次使用props屬性之前都寫一坨代碼來檢查。校驗器最大的好處就是大多數情況下我們只需要聲明我需要什么樣的數據,讓校驗器檢查好了再塞給我。
type
可以使用type來聲明這個參數可以接受的數據的類型,當檢查規則只有一個的時候type可以略寫:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component :foo-message="fooMessage"></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: Number 19 }, 20 template: '<div> {{ fooMessage }} </div>' 21 }; 22 23 var vm = new Vue({ 24 components: { 25 'foo-component': fooComponent 26 }, 27 el: '#app', 28 data: { 29 fooMessage: 123 30 } 31 }); 32 33 </script> 34 </body> 35 </html>
當傳入的參數類型不正確的時候Vue會發出提示:
type接受多個類型
當參數可以是多種類型的其中一個的時候,使用數組來表示。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component :foo-message="fooMessage"></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: [Number, String] 19 }, 20 template: '<div> {{ fooMessage }} </div>' 21 }; 22 23 var vm = new Vue({ 24 components: { 25 'foo-component': fooComponent 26 }, 27 el: '#app', 28 data: { 29 fooMessage: 123 30 } 31 }); 32 33 </script> 34 </body> 35 </html> 36
type能夠指定的類型
type可以是以下原生類型:
String
Number
Boolean
Function
Object
Array
Symbol
required
可以使用required選項來聲明這個參數是否必須傳入。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component :foo-message="fooMessage"></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: { 19 type: Number, 20 required: true 21 } 22 }, 23 template: '<div> {{ fooMessage }} </div>' 24 }; 25 26 var vm = new Vue({ 27 components: { 28 'foo-component': fooComponent 29 }, 30 el: '#app', 31 data: { 32 fooMessage: 256 33 } 34 }); 35 36 </script> 37 </body> 38 </html>
當未傳入參數時:
default
使用default選項來指定當父組件未傳入參數時props變量的默認值:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: { 19 type: Number, 20 default: 128 21 } 22 }, 23 template: '<div> {{ fooMessage }} </div>' 24 }; 25 26 var vm = new Vue({ 27 components: { 28 'foo-component': fooComponent 29 }, 30 el: '#app', 31 data: { 32 fooMessage: 256 33 } 34 }); 35 36 </script> 37 </body> 38 </html>
當父組件未傳入參數時子組件的值是128,當父組件傳入參數時是其指定的參數,比如這里可以是256。
當type的類型為Array或者Object的時候default必須是一個函數:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: { 19 type: Array, 20 default: function(){ 21 return ['foo', 'bar']; 22 } 23 } 24 }, 25 template: '<div> {{ fooMessage }} </div>' 26 }; 27 28 var vm = new Vue({ 29 components: { 30 'foo-component': fooComponent 31 }, 32 el: '#app', 33 data: { 34 fooMessage: ['f', 'o', 'o'] 35 } 36 }); 37 38 </script> 39 </body> 40 </html>
required && default ???
那么required和default是否能同時出現在一個props變量中呢?
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: { 19 type: Number, 20 required: true, 21 default: 128 22 } 23 }, 24 template: '<div> {{ fooMessage }} </div>' 25 }; 26 27 var vm = new Vue({ 28 components: { 29 'foo-component': fooComponent 30 }, 31 el: '#app', 32 data: { 33 fooMessage: 256 34 } 35 }); 36 37 </script> 38 </body> 39 </html>
渲染結果:
盡管控制台上Vue報了錯誤,但是props變量fooMessage還是使用了設置的default值。
事情不會這么簡單,再測試一下其它的情況,比如當傳入的參數驗證不通過的時候:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component :foo-message="fooMessage"></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: { 19 type: Number 20 } 21 }, 22 template: '<div> {{ fooMessage }} </div>' 23 }; 24 25 var vm = new Vue({ 26 components: { 27 'foo-component': fooComponent 28 }, 29 el: '#app', 30 data: { 31 fooMessage: 'foobar' 32 } 33 }); 34 35 </script> 36 </body> 37 </html>
渲染結果:
fooMessage要求的類型是Number,傳入了一個String類型的,盡管在控制台提示報了錯,但是仍然將其渲染了出來。
由此可以得出一個結論:Vue的props校驗只是提供一個參考,並不是強制性的。
validator
當校驗規則很復雜,默認提供的校驗規則無法滿足的時候可以使用自定義函數來校驗。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue Study</title> 6 </head> 7 <body> 8 9 <div id="app"> 10 <foo-component :foo-message="fooMessage"></foo-component> 11 </div> 12 13 <script type="text/javascript" src="lib/vue.js"></script> 14 <script type="text/javascript"> 15 16 var fooComponent = { 17 props: { 18 fooMessage: { 19 validator: function(value){ 20 return value>=0 && value<=128; 21 } 22 } 23 }, 24 template: '<div> {{ fooMessage }} </div>' 25 }; 26 27 var vm = new Vue({ 28 components: { 29 'foo-component': fooComponent 30 }, 31 el: '#app', 32 data: { 33 fooMessage: 100 34 } 35 }); 36 37 </script> 38 </body> 39 </html>
一個綜合的例子
1 props: { 2 // fooA只接受數值類型的參數 3 fooA: Number, 4 // fooB可以接受字符串和數值類型的參數 5 fooB: [String, Number], 6 // fooC可以接受字符串類型的參數,並且這個參數必須傳入 7 fooC: { 8 type: String, 9 required: true 10 }, 11 // fooD接受數值類型的參數,如果不傳入的話默認就是100 12 fooD: { 13 type: Number, 14 default: 100 15 }, 16 // fooE接受對象類型的參數 17 fooE: { 18 type: Object, 19 // 當為對象類型設置默認值時必須使用函數返回 20 default: function(){ 21 return { message: 'Hello, world' } 22 } 23 }, 24 // fooF使用一個自定義的驗證器 25 fooF: { 26 validator: function(value){ 27 return value>=0 && value<=100; 28 } 29 } 30 }