|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: 2 o: ?* { E9 }- ?/ b' b; w
- <div id="app">
. S% d) q+ {1 Z( Z+ F n - <runoob></runoob>- g# g7 C- {, X7 @
- </div>2 P$ v) a( o' ], G- L
-
f) k \& e+ r& _) S( Z' k' y+ q - <script>
& J ]0 n5 p/ a. g - // 注册# \) Y0 _9 f3 o3 P$ x$ f7 [8 R
- Vue.component('runoob', {
' \" `) h2 q. f. h+ V4 l - template: '<h1>自定义组件!</h1>'. W9 n: _: T, x4 n
- })
4 Y' u+ r7 x( C" \! L+ M" d9 o - // 创建根实例
8 h; S7 i: Y% [+ e4 i3 y - new Vue({7 M+ M& z# W8 u, r$ \
- el: '#app'( F; h C) Y- r3 v( M4 m
- })
' y9 ^) c, L. Y5 M+ y0 [: } - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
4 U0 b6 E4 H \: F: A- <div id="app">
7 T: G- `5 m8 n5 I - <runoob></runoob>% j8 E& u3 Q! ^' T- D, _) J) n
- </div>
* V" ]# E8 {; y6 C - ! Z# _2 O6 f( K9 a7 P
- <script>7 t) O9 ^5 z( l9 [
- var Child = {3 n" |5 Y9 O$ d: A6 X
- template: '<h1>自定义组件!</h1>') L- E& P# A3 z2 @! r
- }: l9 s% K+ c! Q' p* p
- ( J, Z9 S* F+ u2 f
- // 创建根实例
. k# p, b) \! c" v) X% Q$ c' K( o - new Vue({
2 j6 L9 ?0 Z; O% `- I% q - el: '#app'," {- Z2 T0 M2 H& Z! o* F
- components: {
- D( E2 @- y) m - // <runoob> 将只在父模板可用! N0 \) ]' `- O' ^4 c3 i" `" _
- 'runoob': Child
0 U8 d( l) L( P! w7 j+ G, @8 @! } - }
" ?" S! `6 k6 l. ]) ]4 S1 D - })
$ P9 }" S; \ p) m - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例; C! V1 i- n' Z- k" q0 x
- <div id="app">
$ T- r1 j7 L9 \2 [: g4 ` - <child message="hello!"></child>; D* o# G2 F7 b0 j
- </div>" x. u j% X5 z
- 7 J, V: _8 B" @4 w! r7 y. ^
- <script>
9 s8 X- m8 ~% F/ D" K - // 注册
$ \6 ~( ]' i# f" w - Vue.component('child', {. D+ I" D# f" _
- // 声明 props/ A m+ i0 ` B9 c; ^( P3 l2 ?2 V
- props: ['message'],! {2 n$ c4 D5 q6 Y' [7 w9 f
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
; f$ `8 L; N* |1 }2 E h3 w8 R - template: '<span>{{ message }}</span>'7 j. ^) ~, H. Q7 H/ o! s j
- })2 W) q1 j: s! O$ I; N( S
- // 创建根实例) E5 c" S4 L: K# g" }2 `
- new Vue({
) p4 C$ I6 `% \2 g/ [- N - el: '#app'/ ^+ Y7 m8 k- M& A6 H
- }): m3 {( T, z. n* |" t/ g( d
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
6 F% d. {8 f7 @; j8 y5 x( a4 V* K- <div id="app">* l1 m8 G. g1 [4 E9 t* Y. m6 _% ?2 a2 \
- <div>" v: l: l. @6 u) q: v2 a" q; p! L
- <input v-model="parentMsg">
* V' g) z; `5 V - <br>
9 |% J" p6 N- m1 E& f" _ - <child v-bind:message="parentMsg"></child>/ y# G- m- Q9 @% s& n* n! m
- </div>
, {, [, B: X4 c- m* n: b - </div>
6 |+ P, L8 J; w" ^( ?1 p - + t, ?: j% J% j1 l. k k
- <script>9 w+ J! h' I5 ^$ b2 n
- // 注册
4 n/ c4 q" U2 n$ L2 d - Vue.component('child', {/ Y8 ?9 o/ u2 [/ i- R7 P
- // 声明 props
6 \( K g, B1 y9 W( F/ G( f3 }' K/ Z3 c - props: ['message'],
2 S L3 Y8 S% e2 {5 x8 x! X/ V- B - // 同样也可以在 vm 实例中像 "this.message" 这样使用5 \/ B4 |$ c; I- ?
- template: '<span>{{ message }}</span>'
8 d# ?. Z1 z/ z' ?+ I - })
# T+ A1 {5 c, E. ^0 k - // 创建根实例, Z: L- E3 }( |* N
- new Vue({
+ k# C4 C# N- Z1 k' q! o: X. R" ` - el: '#app',% |6 L& Z7 ? S1 N- K3 j1 I
- data: {3 T+ O5 y$ c3 R: K: a8 @$ }+ x* R
- parentMsg: '父组件内容'4 f0 [& i# x! ]# U
- } S4 o* q. H" ?. |' c/ M* \
- })
7 M9 ? q0 o1 U. P: P - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
$ r& Y7 f% ^; x: ^& B( n! v- <div id="app">& N) F6 c t1 C
- <ol>
8 s( K" r( R$ a( `6 S - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>: O( g% H3 T5 G
- </ol>
" }. n$ H% ~) H/ p* B, t/ X - </div>
" q5 U2 O$ j& D$ R -
: u' V5 h/ r+ t( p$ ^6 \ - <script>
7 x9 O1 K9 l. G; f5 d+ ` - Vue.component('todo-item', {+ T0 _' A0 ~5 F7 B+ V. X
- props: ['todo'],3 }+ J; P* B7 Y% J4 n% o
- template: '<li>{{ todo.text }}</li>'
" @% o0 [: }; N: F% B' Y4 l - })/ _& l7 y; A( l5 ~6 P$ k) T3 V; i
- new Vue({
% |: ~8 d$ i5 a3 C - el: '#app',% ^. R5 t t! d6 D/ Q! o) m
- data: {5 I) k8 z( u" ?; q/ k# _* M
- sites: [
1 ]# [ d1 K. f8 E) D- F - { text: 'Runoob' },8 @4 o3 y2 w5 P0 Q+ P
- { text: 'Google' },
+ c% ~, O4 u1 ]" [7 g7 ^' e5 x - { text: 'Taobao' }
# G( K- l: Z9 H0 d7 }) e - ]
3 M( n6 X. w w+ _( c - }
& N; c3 I+ q& y: @8 Q5 m' U - })
7 u) }- H3 h3 l# M/ Z - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', { q& |5 |8 c# J, Y& W0 Z* L
- props: {
- y) `; _+ q& `; e* m- H - // 基础类型检测 (`null` 意思是任何类型都可以)
; S7 `" y- l$ v1 ~2 k - propA: Number,; A# n0 v0 L! ` y
- // 多种类型- p4 |" b# h1 ?2 W% M0 u
- propB: [String, Number],
: O: P3 S2 e/ H* I - // 必传且是字符串
( b3 @4 V! e" E9 r, a/ H9 C - propC: {) ?3 @3 B+ [, o
- type: String,
! R) u* T/ Z. ?( B7 W8 H - required: true
9 D$ ?! ?) L* `, c% y, v - },8 m& n. S7 r- w, F2 A' d, z
- // 数字,有默认值/ n5 K1 I! m+ g l4 K
- propD: {
! b; t7 l6 }. [" k - type: Number,
* Z* c# o1 Z7 m - default: 1006 ^. `: K R; s" B5 u+ y1 D
- },
5 _0 E5 r' x) a* i( ~# c) Z# V) o! G - // 数组/对象的默认值应当由一个工厂函数返回4 z% i" }' p7 g) l9 R ~
- propE: {
) e: o) V+ ?3 P - type: Object,8 V2 ]) O% Y2 H2 N- ]3 ^' o
- default: function () {
4 | n: n; ^" p0 h" ^& C; { - return { message: 'hello' }" r' d% l$ ?+ _9 N
- }
3 A* l n; K- }2 W - },# J5 L' h: }4 G
- // 自定义验证函数2 Q; a/ r' e0 y/ h) W3 V8 J. P' ^1 G
- propF: {! P" i+ |8 U; v8 O( s" O
- validator: function (value) {4 M$ j4 n4 K" \; U% H! D6 |- R
- return value > 100 m, q" j' t+ |" o
- }
/ }9 ^! N. a/ f. q4 A' o - }
4 e% ?5 n! }* [$ q) W - }8 y3 [2 Y# F2 `' ^$ ^. B/ c
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array1 _' M0 _1 v' B
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件: N+ ~' D5 ^/ a
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
1 y# I6 k% k: w' B, ?7 _- <div id="app">7 ]7 y7 l9 u; O7 L# |& P! O! l
- <div id="counter-event-example">" J) A F" A0 M2 F8 B
- <p>{{ total }}</p>
$ f0 [, Y) y. w2 V - <button-counter v-on:increment="incrementTotal"></button-counter>
+ f! H; C9 y' ]9 P5 S5 t) p - <button-counter v-on:increment="incrementTotal"></button-counter>9 Z. A, `* u/ U, F: M' f: f7 C
- </div>
0 y2 X0 ~ e7 n - </div>
' w! ]9 d* u" {* }7 u* E& e& @ -
1 f, k2 l: y% ]! ` - <script>
3 r+ m7 Q; ~* v0 u - Vue.component('button-counter', {1 Y7 J" X* {# B5 t) j
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
. i3 ^8 d! i; g/ Q$ C6 r - data: function () {
3 ?2 A. ?* ~7 Y1 i. q, e# r - return {! s1 e, i) t" k S
- counter: 0
/ K: l) d7 c8 h1 h/ X - }/ ?0 o$ W$ ` Y
- },/ L) W& [, m3 V4 H6 D/ V
- methods: {
. W/ K) [4 E# d0 ]% h& @ Q - incrementHandler: function () {
0 n1 _8 @( x, H - this.counter += 1
# O& X! ?- f$ n7 t6 S: N5 _ - this.$emit('increment')7 L0 A4 K' t+ B: L
- }( }6 i: a' o: B6 H8 q" h( f( }
- },6 n+ [7 G) @, h$ n# m: u
- })
5 o+ E! f& p8 q1 D - new Vue({# Z$ h( z4 G K" k J, _, u/ h
- el: '#counter-event-example',
C8 [4 L" p1 l8 F3 H - data: {" U% [0 n" R2 {) Q2 T
- total: 0
9 w$ ~5 G- g* U6 m* O& b - },, q5 x) g. m" e
- methods: {( y/ f. A. S9 u" a( j5 w7 F( e: n
- incrementTotal: function () {
" M5 K! N1 f9 P" ]4 K; ]2 Y: v$ H j$ } - this.total += 1- q5 z1 \0 m( h: X
- }; ~. v) F, M, X5 I$ m1 e
- }
0 Y" K# V" |/ i& I. L - }) Q: K! w% `4 E, @" t, x& P7 c
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册- W+ Q. k' Q" p" a
- Vue.component('child', {
1 i( U. M6 l4 k" ` - // 声明 props
a6 Y) l6 i, y, ~0 l( r! V - props: ['message'],
* d- f; J, T( X7 |% |4 f0 E - // 同样也可以在 vm 实例中像 "this.message" 这样使用) c3 I. e/ @6 I Q g q
- template: '<span>{{ message }}</span>'9 V0 j# W- L" n+ X3 W
- })- ]; ^' t: B. [. ^6 C. P
- // 创建根实例) f9 `5 `2 ?/ J
- new Vue({, H2 v( R( U6 |! B) X
- el: '#app', |6 `7 V* f7 T. W9 q
- data:{! s4 { e( [1 l; |: v
- message:"hello",+ T; W; p; p) s) }2 K; G: v
- }' J& @+ X6 m- @- W4 o `: s* E
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {" i0 c8 }* G- n* m8 F
- incrementHandler: function (v) {$ o4 ^$ ~* g c9 v5 q
- if(v==1){
: V+ R j- {4 q" U - this.counter -= 1* `- C$ U2 g9 j8 D5 K/ f
- this.$emit('increment',[1])
" R4 |) g: J& q7 v% {+ J - }else{
% P; I; d/ M' Z8 b - this.counter += 1
/ s: G" A7 n5 a- l t1 I B - this.$emit('increment',[2])
( x1 w1 T" R( \ t5 W - }
- [/ ]: m4 O1 ~8 n+ V - }2 B; W" z6 N9 v2 l% }
- }
复制代码
! v+ i0 n" j% [, i5 [
$ A; B4 r0 d! T' n! C: T |