1. 程式人生 > >vue 元件開發 props 驗證

vue 元件開發 props 驗證

使用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 }