|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: / l# \+ F. M" @; d# F
- <div id="app">2 b# s' A7 J8 p3 x7 v4 q
- <runoob></runoob>
8 q" z9 d N. Q. } - </div>
; `. a3 H# _5 v; Y; u3 t -
: Y: P- l8 c2 R6 k7 ` - <script>1 T$ g7 ^: X3 f; g
- // 注册. q) p' X' Y! T7 @% h
- Vue.component('runoob', {
' U) P: |0 v: t d5 m# c - template: '<h1>自定义组件!</h1>'; v# n7 M, J( q) g0 j' H
- })' b" e4 R8 g) a( R* S0 j
- // 创建根实例
( ]0 a1 _! Z% L - new Vue({
$ [& e. }3 d$ N9 `* E1 C6 E - el: '#app', I2 w. ?% a8 T8 a8 w1 }" H1 v
- })
( x# X0 ]) Q2 Q, `: C - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
, N% H) x* W8 Z" b4 ~3 L+ k, {% v/ Y9 v- <div id="app">* n, Q3 u0 |' G
- <runoob></runoob> c& U9 w: K. {+ S) `; K
- </div>
$ G Q d& v$ s! C - 3 A) T$ c8 R7 s7 ^* B$ }/ {# q0 v# ]/ l
- <script>4 l" }: I( O0 ?6 P P: S. Y8 [
- var Child = {
* X1 n- N. ]& F, Q' q - template: '<h1>自定义组件!</h1>'
( T# D' Z/ W. i - }/ c- J& ]/ [7 g; G+ E) d
-
' q. [1 O' k+ g ? - // 创建根实例
$ A" [, K$ F( q/ u - new Vue({1 E* R9 }7 h- R% l
- el: '#app',. @# H0 X, N- {- c% E
- components: {
4 t, ~% r$ ^' c! H' u1 G7 h; } - // <runoob> 将只在父模板可用: }9 m! D1 {9 q! \! k
- 'runoob': Child
* S! G0 o O; G' @ - }
% U. p* c% w. ^( d( j" m: I - })8 ?1 s! t8 _! s7 S/ U, N+ N+ D
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
$ W% y3 k% r' D+ Y+ _5 |( @- <div id="app">/ n# N$ b7 \5 U6 r8 G
- <child message="hello!"></child>
; E9 E. O1 l# L) d$ E q$ j5 t9 U - </div>; I1 o+ Y4 V( D$ Q
- : `3 @% U+ C/ ~$ o% d# I
- <script>4 B* q) u1 v& r) ^) n5 G( ^% I/ C
- // 注册9 Z, k) L5 c% P2 g( e6 R
- Vue.component('child', {/ L/ I; H, D+ n5 F5 X
- // 声明 props
* B( }* d7 q: H0 H1 W) q3 F& w - props: ['message'],
* K f0 }7 y; k7 g7 x1 M% y - // 同样也可以在 vm 实例中像 "this.message" 这样使用
. t, N# @" w! B0 ?. c- d1 u - template: '<span>{{ message }}</span>': l0 _8 c, l1 c$ N: K9 E$ k
- })
+ d* `" e" Y, B0 b6 w) r - // 创建根实例 f7 g8 \" L0 A3 t
- new Vue({' G4 T4 M' w# C' I3 W
- el: '#app'! [; J% p, P5 Z z6 K5 E
- })
$ k% W% {. {! \1 J - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
2 Q8 ~; G; G( Y1 V0 t! v& e/ b3 f- <div id="app"> ?) h$ ^( |6 U" A7 I) g
- <div>
& @4 k f4 q- u/ t3 c; v - <input v-model="parentMsg">
. E! E$ ~7 O3 h8 _1 D) u5 Y - <br>$ F4 m* X" ~1 i
- <child v-bind:message="parentMsg"></child>
1 i Q8 s: r4 _5 l. r Z7 h - </div>
$ D7 m* h% J+ }1 } - </div>
( \. F! T1 b' l- Q5 z - 5 l! ]1 U6 n% R* r* R' @" \
- <script>
: \% v7 [/ `, h- E9 q( | - // 注册
. k6 |% y! M7 v" }4 a& n" f - Vue.component('child', {* ]& E' u* b- w, a2 {
- // 声明 props4 e& E" M7 a/ ]/ |# |6 z
- props: ['message'],& m( p4 {, d$ L* ]2 m! q& ?) L
- // 同样也可以在 vm 实例中像 "this.message" 这样使用' n! C6 X' T* W' S! k- N" A! S3 |
- template: '<span>{{ message }}</span>'
2 h9 e) e+ m; E" A/ V - })
& `' h" Z3 N% C' ^ - // 创建根实例4 U f: y- }, y
- new Vue({$ w" d2 M% _5 y" o5 r
- el: '#app',
* `& y2 @) \: ~ Q1 ? - data: {0 [5 R6 ?! k( O1 a. G
- parentMsg: '父组件内容'3 {. a' A# q# L! _; O! U
- }6 a) |% I# c; ]( Q, [8 f
- }). F+ `! x$ N6 J$ n. x
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
& y% }" i4 ]- [- <div id="app">9 I% I9 r6 O* p; d0 m
- <ol>
+ ~# g) ]* k4 Z - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
8 s: T6 E/ Z: i+ X( { - </ol>
1 M/ T! _3 ?1 W& d1 }. Y - </div>/ @7 o$ ?+ h2 w# X2 m# o
- 0 a5 ?% Z, ~9 P
- <script> J$ ^5 G* J8 ?
- Vue.component('todo-item', {
" W$ Z; Q I! J - props: ['todo'],
7 H8 V' O. {5 y' j( h - template: '<li>{{ todo.text }}</li>'
+ T: F# j3 h. U2 t) Y - })! p. p' e8 H( E1 ]
- new Vue({
$ r2 @, ^$ N3 U- U. w( F+ L$ I - el: '#app',
4 L+ Q( F1 Q$ ` - data: {% s/ Y! O2 z' c& q6 `
- sites: [
$ d9 M2 p% G! s1 g - { text: 'Runoob' },
! ^, x) Q/ A- H& N - { text: 'Google' },
6 @8 S9 U% I: \0 e# M9 T - { text: 'Taobao' }
0 l% W7 J. V0 N" B1 @4 @# E6 z2 _ - ]
& E! N3 B4 S/ s - }: z9 ?3 Q+ R; N3 l3 j) R
- })
! a* i/ D9 ^) c* o( d% { - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {$ F8 T& k) X, k7 U+ ^
- props: {1 T Y1 s+ v1 H* N+ n" j
- // 基础类型检测 (`null` 意思是任何类型都可以)- h) O; g# T( Y v2 Q
- propA: Number,
/ e8 q! \1 C/ h - // 多种类型2 V, o. C' o/ `0 U T! G; ]
- propB: [String, Number],2 g' v q9 f3 u7 I* a6 e( u% @" _9 M" C
- // 必传且是字符串
4 @0 w2 ^) C" F+ _ - propC: {
5 T9 q3 S ?8 Z6 B - type: String, R3 a! O; s1 B8 T
- required: true" v2 w) t* g. ?- i$ H
- },
3 H& r% m% w* s0 A# Q: [7 h" H% Y - // 数字,有默认值* q5 [: Q9 I; q$ c6 S
- propD: {$ I* R* e1 U* l8 u8 `
- type: Number,
0 U! S' u* F* b5 l - default: 100
9 y# l8 E+ W6 m/ ~5 Y1 |) A# p, }+ s - },
7 n, M) O/ g- ?. X - // 数组/对象的默认值应当由一个工厂函数返回$ V0 }6 K" h+ |( g9 X1 R R) J
- propE: {! ^' _, U1 N# U
- type: Object,7 O4 u! P2 w5 {* r# c7 T
- default: function () {2 t- g s! f* J5 S* g# r7 o- d# q
- return { message: 'hello' }/ ]! S3 T% S- ]8 T- B
- } l' v# D! G9 G( q
- },
& n0 z9 D5 g# D U0 O - // 自定义验证函数+ w5 \( ]- X; z! V
- propF: {' F; |" D9 E, {3 t
- validator: function (value) {
1 I0 ~( g4 {7 `% C - return value > 10, F0 U8 k6 o& j; Q3 h
- }) M4 w7 s: s2 s0 r6 C+ j
- }
( K6 W( } o' x3 \0 U8 \ - }2 x( z; |- D& P# m
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array$ M; A! h6 N' o% }
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件0 }# N% ~3 Y, q7 V
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例5 u& {" u% _1 U% X; h: Z$ p7 J
- <div id="app">: u& _2 _/ v: D0 i& a0 {+ y- C
- <div id="counter-event-example">
. y) w3 b. K' U% k4 E; m - <p>{{ total }}</p>
' ^2 p7 U, p- F* W q' E - <button-counter v-on:increment="incrementTotal"></button-counter>. P8 r4 z7 D- n9 ^$ H" J. j* M
- <button-counter v-on:increment="incrementTotal"></button-counter>
u5 F1 P* L/ J# q! B+ q - </div># V6 Q" F' M+ S0 H( V! C7 @0 Z0 ^
- </div>/ H% V' |, m7 e6 J0 o
-
/ R3 O7 L7 r/ ?, p$ `5 j/ ` - <script>
8 _' h) \ Q; {( Z# f1 M0 }, ?0 x) J - Vue.component('button-counter', {9 V' P; p* v" L) [3 ~! @, A, t3 f
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
9 n$ a4 }* Q( h% [9 W - data: function () {
_0 g( X( h; ] - return {* l N6 Y: U) ^
- counter: 0
! z _# @5 h0 v$ ?" P$ i - }/ ?" E, W; v! X; H5 M6 H9 [ c* {! v
- },& X9 B3 x; { `; D3 b6 T z- P
- methods: {
5 b: _% ~1 l2 c/ r/ y& L - incrementHandler: function () {
, D+ {- A$ }- j) A - this.counter += 1) M2 w% L9 _% ~+ E: \
- this.$emit('increment')
! }3 n- V( [; w# t5 f1 U+ Z2 U - }/ h. g( q8 l5 o' ~7 _& v) b
- },4 B# ^6 K& [0 [/ _
- })
7 b1 b) m" z: `/ J7 h - new Vue({
: _6 q& i( W" }& a - el: '#counter-event-example',
( v/ O! P4 a4 T. ^2 {6 _ - data: {: F6 w9 U" n( V( `6 {
- total: 03 x, J1 ?" h4 v: @, p8 U6 N
- },
0 p, Q! o, z4 ~" } - methods: {
; y) }; a' k7 d/ x - incrementTotal: function () {
: a% B8 D3 x& `) c- N F, X - this.total += 1
6 |+ M. J4 b" c0 o, C! Q( J - }5 B, l" g* ] B; ^* |
- }
$ b- C+ f! x' l1 H, d - })
1 }" Z9 V V6 _5 J8 v - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册* l6 f0 t* B+ w4 u) S6 x5 X2 t" P# z
- Vue.component('child', {$ T0 E3 p& D2 a; s2 ~1 R
- // 声明 props
) O: o: J- N' |0 j' Q; s9 U7 s7 v - props: ['message']," t8 m8 {7 P' ~ H$ d0 D
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
b( I& [# d; W3 } t% P - template: '<span>{{ message }}</span>'3 S* B2 B( p8 \8 ] w
- })7 r' D; w$ ?% B; ~7 ` d- ]) \* G. s
- // 创建根实例2 M7 v6 z' T# a
- new Vue({. ^# r0 ]- ^- n
- el: '#app',
" P, R9 `: b( d1 d - data:{, Q: n: T+ _, x/ G: \ C$ [8 }- q6 h
- message:"hello",
, n4 i( I! t0 l- a; M5 Z - }
7 o) _/ p, {: o/ _6 I - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
: g. y! [. j7 L7 O - incrementHandler: function (v) {
' v2 l5 h! r6 l6 R$ ]$ b" { - if(v==1){
0 c, f! v% u' H" ^4 _# u - this.counter -= 1' s7 T% R' M+ p. p6 K4 q
- this.$emit('increment',[1])
* r# B. |$ n* b% Z) N i. W6 ` - }else{
/ `# t( C* m$ g - this.counter += 1) v) I, R9 T8 ~( i
- this.$emit('increment',[2])# M0 q3 T9 q6 H% H
- }( K0 Z6 x- [' i# \) V
- }
* R w$ O/ Q5 f' R: L# T) N - }
复制代码
% E) [2 R9 p. o* P4 T1 M, T1 A: ` |. H9 c
|