|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: ) u+ Q4 q+ ]- e. y9 `6 S
- <div id="app">
. C8 x* O7 K1 R. U$ O6 B - <runoob></runoob>
5 u2 Y: |2 ]7 g4 V0 H6 q - </div>
" N3 J* P; ~ A8 h0 [ - . X0 h+ z* y- L9 d4 D+ O6 j
- <script>
3 K$ ?( f B' T$ A0 O2 Z4 h1 K* V - // 注册
1 S7 @6 G' B5 l. c! e! J' }* ^+ W# L6 k - Vue.component('runoob', {
- i$ N+ d1 l3 k. H - template: '<h1>自定义组件!</h1>' t' z4 n7 C( b* A
- })
; o! K' w( Y+ A' d# m - // 创建根实例+ M# k& f# V2 ~+ j
- new Vue({
, x |, r7 K& I7 C- j - el: '#app' @4 m; ]' j$ Z4 T2 U
- })
6 X V, u& F8 G! b - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
9 J" m) v& m2 h- <div id="app">
. t& z4 P; h' N - <runoob></runoob>
- D8 ]( A7 d0 A) q6 u - </div>, a' ^+ f) T& q4 z' }! h2 j
- : y+ h ?: m3 @! }3 V$ h% Q
- <script>
! e O9 r- Q* ^ - var Child = {3 k4 M1 g& _1 l& Y, D6 H
- template: '<h1>自定义组件!</h1>'
! P/ A9 |& s; R& C* A - }
' N. h1 ^' C2 a' H' y -
+ G! y2 I5 ]8 V: D5 r/ ? - // 创建根实例# u% |0 v2 k3 i% i* g
- new Vue({
: |. u3 V+ N2 D' e+ ~7 K7 c \ - el: '#app',
$ T* K; D* o" f* N: ~, V: z - components: {! r5 T3 \) l& E
- // <runoob> 将只在父模板可用
( h9 q; \4 ]& {. ~ - 'runoob': Child
7 ]( e. Z$ d# D$ z' n4 ` - }( i! ]. A6 Z+ L
- })
# Q# O$ J: q& I8 Z" D; d - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例" Y. F: h/ b% d# w
- <div id="app">
, v1 f+ i5 Z6 |# d% T - <child message="hello!"></child>
: L$ W" _' O( s! c) h - </div>9 X( ]2 }, j3 J$ Y4 j. s% H
- " a1 f7 a2 e4 g- ?1 g: Z
- <script>* f0 W. r% u ^7 g: f
- // 注册4 h/ e) g( E; F+ _# W: i" j
- Vue.component('child', {' i" j( ]" d6 I: N, Z
- // 声明 props
6 e) o+ B, z( ]0 e: _ - props: ['message'],1 M3 f$ l5 `2 R7 G( k, f. `; E$ D3 S
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
( A/ B& \/ w) E! M j - template: '<span>{{ message }}</span>'
% v: e9 n- z, I, b - })
6 |9 D8 \ U7 [6 k+ R0 t5 ]8 x! A - // 创建根实例
) L! ~0 i: c8 e: j& J - new Vue({
( }- O+ n0 `2 ^! w& j - el: '#app'
& r0 U0 B9 D! a4 x! T9 ~ - })
4 z& q4 @( T" `1 ?) M( y - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例8 t) c+ g. F5 o7 i% p9 ]6 P
- <div id="app">
8 g& ~8 l/ s9 U' F4 S' u2 z6 _ - <div># S* R/ z s' T
- <input v-model="parentMsg">- X5 X: o9 Y) T" ]
- <br>$ b! C% z& J0 t2 Q2 t' R* ~/ ^
- <child v-bind:message="parentMsg"></child>. y, Y3 Q \% f! U
- </div>
9 ]) r; Z; P+ g2 D( A5 s) y3 ?: l, D - </div>
. ~& p/ N' E5 z8 V& K5 y \3 U -
6 ^) p; w r7 P - <script>' [: U6 k+ W- P8 s- z, @' B' v* i) b
- // 注册
9 x$ U2 R" w' i/ r1 Q - Vue.component('child', {/ Q6 e8 K& n1 g9 R
- // 声明 props8 ~9 o0 c- i5 ?4 l+ E4 }* u) W- V
- props: ['message'],
8 C' X; |; ^8 m- n0 j - // 同样也可以在 vm 实例中像 "this.message" 这样使用
5 }- B5 I3 z2 E. v/ ~: s5 {& g - template: '<span>{{ message }}</span>'0 g: |% N9 i8 g* U7 D- r
- }): \* d2 }, D; e% K# `
- // 创建根实例6 S" |* u: f) M$ m5 S' H$ z
- new Vue({
* a1 P c! _7 [, A - el: '#app',
. z7 ]6 j6 \6 ?* K5 C6 [7 o - data: {
3 y9 s$ l. y1 U. U$ W, e - parentMsg: '父组件内容'+ A8 K1 Z) E' L- k/ I0 P
- }8 _3 [ I& c) U, s, F
- })" ~ x1 c' E1 ~& G
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
% M- O' [' O) e- <div id="app">7 ~' [. {2 T+ ^
- <ol>0 x4 l7 j9 ?6 Y$ j- R; }/ Z1 m
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>: A. U+ G' i/ a, c9 p$ e
- </ol>$ p# K, e% w2 n9 B! b5 u
- </div>$ _0 F6 Y& g" u" ]1 F
-
/ C; Q; z+ p/ m/ e% B - <script>" K6 D; ?' s. \; C: A
- Vue.component('todo-item', {
' _ Z) X7 I% B% u - props: ['todo'],
' |- _. J0 O4 x2 I - template: '<li>{{ todo.text }}</li>'
V" W3 A! Y/ y$ O$ U - })3 l, d2 o/ C8 a1 ?3 I: p' U% Z) O' [
- new Vue({( b! G5 l$ r# I4 p: [8 _
- el: '#app',' f+ d# U( J; t) u, O, m6 ?6 z* Q) Q
- data: {
) a: i; i: |% z( P- z - sites: [
" J8 }: ~8 C$ s: ~' M$ x3 e - { text: 'Runoob' },9 B0 B3 O; h. R9 S8 U4 x; X, M7 C
- { text: 'Google' },7 b6 D D. m! _9 @: ]
- { text: 'Taobao' }5 C4 y* ]1 L7 f$ a+ A3 E
- ]
- @! h7 d1 C d$ ^# r8 d g - }
- f* e, s+ @ ]( f, K5 v. O' v& c - })" ]0 \: z9 z) x. D8 i0 u4 m
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {( h2 U$ `- y+ h( j
- props: {' C7 w/ l1 w0 |) C3 k. K: ?
- // 基础类型检测 (`null` 意思是任何类型都可以)9 T+ Q" K1 q) r5 e- J! z( f
- propA: Number,+ u' H x+ c9 Q3 k
- // 多种类型
$ z [8 C9 R8 z - propB: [String, Number],& @1 L) g1 z, D ~- d: `# | m
- // 必传且是字符串. ~' p% m( j9 h
- propC: {& P% y2 s' }7 d8 O
- type: String,
# F3 U) V( V" j - required: true/ S" _8 M& F. y A: {! Y. Q
- },! j; S# C& W W q0 v8 G
- // 数字,有默认值, H/ v+ J$ C, W# y& l+ ~% Z
- propD: {4 _+ T# l0 e i6 q2 h) g
- type: Number,
4 P4 n8 A# @4 r - default: 100" \$ ^# P. S! E" o" t- s
- },; b: n2 m* J5 G4 v4 v
- // 数组/对象的默认值应当由一个工厂函数返回
% C2 I. D' N. s - propE: {6 O+ K7 I n0 o
- type: Object,
: N! W- x e* a- P) d B - default: function () {
# X6 J% M) f1 s - return { message: 'hello' }# h- n0 [) R1 _, z% P
- }; t/ ^5 c9 ]( y8 W6 t& V J* n4 f- n
- },$ t0 i( `/ z) S& k& b) T$ P
- // 自定义验证函数
: d' m& z' Y7 S# G k - propF: {5 X, B3 p4 b- a! Z: I) A
- validator: function (value) {6 Z1 A$ U3 }; Q' X! S' l6 L5 Y* H
- return value > 105 A' W; g0 X. D& Z
- }( W# i4 ]1 @, k% y1 ?' i( d1 R# B
- }: ^7 o. N% g4 }; A7 B
- }
0 w: @3 A& e3 @3 c( n - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
0 c4 n3 i4 S, w$ v8 S
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件* q4 q( y( [2 ]$ L
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
* {& i) r: C2 \$ [- <div id="app">
/ s L$ l( ~, y. B d C9 t - <div id="counter-event-example">; I" n ^. p; ^1 _2 U
- <p>{{ total }}</p>
2 k* [3 i8 S, B; U5 e" c- G - <button-counter v-on:increment="incrementTotal"></button-counter>
: y) D& s/ |! p5 \' |6 n( S! s - <button-counter v-on:increment="incrementTotal"></button-counter>. V- H, ]' X9 P G; z; Z5 B
- </div>( z4 V+ m" {2 Q$ P
- </div>
/ L; {% f% k/ G* r m z8 T% k) H -
- ?( X* g' {) ]6 L H - <script>6 _+ d, n6 Y- \3 |$ P! |
- Vue.component('button-counter', {$ \$ a H' `- A- _7 J
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
3 w1 ^9 F3 F4 P6 V4 U# \" X - data: function () {
; Y; U5 _: U- O" D' O) U - return {
3 E& a: n3 {3 r- L, { - counter: 0
6 i. F( Y( M6 a: m2 F) B/ X - }
$ d" {" F' W4 T4 m* e+ P: r - },0 f `) Y0 N( s( d# M/ _7 S
- methods: {/ o' x# m3 G$ Q }
- incrementHandler: function () {( g) n" r, m3 A/ i
- this.counter += 1
6 x) @3 h/ D- E# k, T - this.$emit('increment')
' f+ A/ h0 J( k9 \5 p; t' l - }
9 F$ L% A; y7 R - },
# O; V, f4 Y6 I: l; O - })
e9 Q- [+ A3 Z - new Vue({
5 Z, f6 v/ `9 H7 v5 Q/ f S3 [ - el: '#counter-event-example',- u" Z8 L) T; H# u! P
- data: {0 c/ o3 P/ ?" l8 A
- total: 0: m1 t1 {9 ~6 q+ z# ] L
- },0 D6 o6 j) d% ]1 K' o) D3 f
- methods: {- m: |! U1 j7 @) g6 M4 p
- incrementTotal: function () {7 S# N( U. B1 `7 o/ N
- this.total += 1
: _( k) v* Z) u0 y' D - }
; P# }6 f2 p a( ?! @& @ - }% z% I* S' }. i! ]
- })
+ h) E0 @$ n1 \7 i; X; @* k" n& M - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
- F0 Q2 X0 e: L6 u5 A - Vue.component('child', {
3 {* d5 C: o' k# I# U - // 声明 props
6 K3 j: E# @0 { - props: ['message'],! o: I4 J: }# I% _
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
4 v+ W% ?9 J9 L g9 K3 R* b - template: '<span>{{ message }}</span>'
+ B) b0 R$ @3 c) w3 K - })) H; Z. s$ {0 K3 f2 }( k
- // 创建根实例% k3 V5 e8 }; l3 D: n6 m, U' I8 \
- new Vue({, i* d7 r. U: n
- el: '#app',
6 b) j: x! O" H; \: u: ] - data:{
2 l; Y* E/ k# l2 }( f - message:"hello",
- K" f2 U6 s% m5 c - }
7 f2 _- a" n! X3 \: t: j! T( r; s - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
3 b+ E* R: c4 o6 } - incrementHandler: function (v) {* f$ r$ s- e' r
- if(v==1){7 x( J2 w- V" G
- this.counter -= 1. j5 q; |( K. L
- this.$emit('increment',[1])
( |% g5 R* W- W! C3 p - }else{9 H7 t" }# n: q) a8 {) p- X$ F
- this.counter += 17 Z6 S9 k% |: S c0 a! B" x
- this.$emit('increment',[2])# l7 ~( o/ |6 k7 h, H
- }. C8 W7 d9 k. S, b. i& c
- }
! D8 f1 f4 M/ {7 a5 \" M1 h( B - }
复制代码
3 t' z0 t- }0 _. Y H. Y6 W7 b4 H3 G" m
|