组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
' N- k% l2 |8 l( C2 N0 {" v; v- E& Z- <div id="app">
& a0 c! g+ J5 Q/ @% |( y - <runoob></runoob>0 m1 }# _ O1 f$ j8 o* y& K
- </div>
: E/ X7 y5 A6 ?$ U - " g; \/ i' ?; Y2 Y
- <script>
# Z; f F3 e& U- O& v& A( N) G: a+ I! X - // 注册
; y- I2 a, T6 y4 o; e* P - Vue.component('runoob', {
/ ]3 \9 h M7 b2 b/ r8 L/ T - template: '<h1>自定义组件!</h1>'9 M7 q$ Y4 X) w7 @
- })
0 b. T( E, M8 T: _$ i - // 创建根实例
9 f! t5 h2 q9 O+ `$ c - new Vue({2 H2 {. v& T5 x' G5 e4 D
- el: '#app'7 {3 X1 U/ R1 F1 h, b
- })5 Z1 g7 t$ d. q3 f8 s( g
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: p% k* f" m, S* h5 |
- <div id="app">8 i# Q& ?5 P! L2 f0 ?6 u8 B2 q5 x4 W
- <runoob></runoob>
; f0 P4 z5 [0 l' c+ U$ c1 G# J - </div>
7 T$ W! I$ Q) u0 ~9 C0 ?/ H$ E5 N4 ^ -
4 G( h Y# X! ]8 y& j$ m7 c - <script>
r% ~6 |! o, _ - var Child = {
q: @. C. N2 N" | - template: '<h1>自定义组件!</h1>'
, Q& l3 g0 S. U7 _# t& i - }+ J, y0 }6 ]# V- r% n1 |3 i M7 b
-
* `% V7 Y' t, _" }4 |3 ~( K [ - // 创建根实例
6 t5 l2 Y9 p, K% d5 z% R2 H8 q& h1 Z - new Vue({
6 y, g: D4 @% g _7 Q% |. s - el: '#app',
) X! s& I* D2 {* h8 B/ H* l- O - components: {, J+ S: x3 H; Z# b; |& U& Z
- // <runoob> 将只在父模板可用( W# O( i4 g/ a: N
- 'runoob': Child) ^+ ^* q8 H' |& N( L
- }
m, O" H1 f, _: K' O - })
5 a# p3 u5 b& c$ D' s. S - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
4 g! M l8 T0 g' X- <div id="app">4 E$ U1 p8 F1 U% x
- <child message="hello!"></child>
* A8 u5 J# Y+ B5 _ - </div>9 q$ M- F; l* v- _
-
9 U r# G* t7 H& S - <script>0 o- p" r1 D, g9 M( n
- // 注册. z, y" j5 G( u, c o) J: v
- Vue.component('child', {
. \5 V/ H2 N( z% Q. I H4 n - // 声明 props
0 N+ }) e( A0 y. E: Z0 ^ - props: ['message'],, _% w. M" G+ e6 l5 D
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
! ~& y) D9 D% F/ l; I* @. [ - template: '<span>{{ message }}</span>'+ G/ o5 ?/ T; k5 J+ m: x2 k
- })( @5 X. h3 @! P; l: K$ F
- // 创建根实例
3 m4 u2 u. y2 m. [ - new Vue({
( W# n% X$ k h; {+ ~. b - el: '#app'2 Q/ U# @+ @4 c D* v- D
- })
2 ^8 B/ i$ [/ | - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例$ h: D2 R: i# V# }' T; o4 {
- <div id="app">
. s( U& ^: A( j: I* L' ~( w$ Q - <div>
, }0 B+ R% l. `# O- K# d/ [% T. e - <input v-model="parentMsg">9 p8 R0 [5 {& I/ _
- <br>
6 m; Z X) t3 k& D1 D$ M - <child v-bind:message="parentMsg"></child>0 M) Z D7 X T4 o% {
- </div>
+ A. f6 D9 x2 \5 f. c/ D$ p% @ - </div>* h* d2 A H$ g# {: K
- { W" w& q9 m, O6 _% J
- <script>
* Q5 ?# X8 \5 Z. F& } - // 注册
+ L R1 k6 n& G1 x4 D - Vue.component('child', {% p7 \2 u1 M& G( Z" K
- // 声明 props
% H4 I5 H* W* T5 c8 c - props: ['message'],
$ j* O. @& B) ~6 U: I6 p - // 同样也可以在 vm 实例中像 "this.message" 这样使用
; ~" ^3 p. v9 q* T6 ] - template: '<span>{{ message }}</span>'4 i; K% M8 Q+ Q5 y9 g, l
- })
) ~8 A0 e- ~# t7 i! W! S- ~" u - // 创建根实例! e5 f0 d. N5 p- n, y& ?8 X) s
- new Vue({1 @5 d" |" p' t& F$ _; g, i# V) O9 j
- el: '#app',' p" v, s0 D* T5 @. Y
- data: {
, o2 E; U* A7 q. O0 u9 x# w - parentMsg: '父组件内容'" M( ?% P! w. \. }' w) G' _7 ^
- }
k+ |% F3 {. r5 `0 U! _1 @% \ - })
! t9 N0 t) ^3 u s9 L - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
4 E) a! p$ W3 H: z8 y2 @- <div id="app">
1 U7 `* l; x7 D$ N7 s - <ol>
# L& j" w$ X& x5 ~3 t1 H+ \/ A - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
' S- Z. n# x2 M8 m4 g; F9 y3 K G - </ol>
# j& A3 d3 l1 z, e- Q8 a: v4 X - </div>3 H! R$ t7 Q3 b+ x5 `- c" X
- 9 ]$ }9 @* V8 f7 \3 q; b" L
- <script>
: `7 O. ~7 Q* g, ~( Y( G; x4 R - Vue.component('todo-item', {
( X! ?; \$ p" A8 N6 M - props: ['todo'],9 a; F$ m, H' G v5 h9 b
- template: '<li>{{ todo.text }}</li>' ~% {* G9 V$ Z" A
- })+ i/ ~% A8 i% ?$ T
- new Vue({
0 L) A' [" G# p/ s( Q* D - el: '#app',
7 ]/ P3 c# p2 \' _, n6 G - data: {9 `" x/ o- u) H
- sites: [
8 U4 o& E+ }2 c" K - { text: 'Runoob' },
) N. l' X" ]8 @1 R8 v - { text: 'Google' },
' I, H9 _5 B7 R; I; L3 I - { text: 'Taobao' }
! f$ L$ l4 I5 t+ \* G - ]
0 k( a6 f' x: @. G- m; Y" E - }, h: P0 V& A5 E$ M9 U! h; @& m
- })
2 C" m$ u8 |) I- j3 k - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
, o- s; x$ x1 X/ ^( ?+ I - props: {
+ i9 v ^6 C6 w5 u t3 O - // 基础类型检测 (`null` 意思是任何类型都可以)
2 w- ^7 G1 |2 y r5 u' Q3 c! H& J5 c+ t - propA: Number,
6 c8 }6 U1 W' [; Y: C - // 多种类型4 Z" ^, M' r @
- propB: [String, Number],5 H( W' j k- {* g( ]" d2 h# q
- // 必传且是字符串
2 X; _6 I5 v9 T7 w3 _. x/ y. P - propC: {% m9 v, g% F9 Y" z
- type: String,
: L* t6 Q- u {6 K Q9 |5 _6 P - required: true
- _! C/ U1 \8 g - },
" w: q- v! N: @- U - // 数字,有默认值8 I2 c! J/ A5 X& G: J$ P
- propD: {: j2 f; W3 |' C- q
- type: Number,9 j4 P9 I# f# w
- default: 100! @% \0 V4 M% L1 b2 m: x& P
- },5 D4 L2 I' ^/ y' `: B
- // 数组/对象的默认值应当由一个工厂函数返回
$ [0 {2 T" L$ p0 x8 t" {$ I - propE: {
$ m `1 I! W& Q1 K( M# r6 }' p - type: Object,3 n- b" X& A$ r, I3 I( h# j/ ^
- default: function () {
! o; d' F, l# W3 W+ @/ @+ K2 A - return { message: 'hello' }" q$ q% `3 X% e: @: H
- }
& W1 _7 U- w9 G- Q0 {" f - },
+ e( q( E9 e4 ], c - // 自定义验证函数% e' U4 O8 y% |$ K. C0 _3 K' V
- propF: {0 B9 l" d# s& x
- validator: function (value) {- I$ N# @1 W# Z! @3 K u$ H% r6 x+ t
- return value > 10
' A+ w- l7 h; Z - }; b' G# o0 L1 T1 a8 l8 |" o
- }2 H, O1 d# a, l8 ~9 S7 |
- }
7 ]- ` V z5 e8 F - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
3 D8 I7 |' {( ^1 ~4 F
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件9 t5 Y- c# C" G/ L }2 g
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
- C% m) O. K) P+ F" F9 C" X- <div id="app">% |* J7 z! M1 I/ W& s* r5 _
- <div id="counter-event-example">, {" h; B' v- V* ?, t7 v
- <p>{{ total }}</p>
/ c/ |# S3 g1 W& \9 ], j - <button-counter v-on:increment="incrementTotal"></button-counter>
; D! @7 F% A+ L - <button-counter v-on:increment="incrementTotal"></button-counter>$ O5 ?% Y9 J7 q
- </div>. S& z* s) E. V i8 r
- </div>! y v+ E) ?8 M; f$ b5 S
-
6 n3 ~* V7 r9 O3 D- h - <script>, h, c+ F. {/ I" L k+ f
- Vue.component('button-counter', {' x$ m; ~/ I8 Y$ p
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>'," M6 w9 e2 R3 b0 C' C e
- data: function () {
4 a* A7 M6 R# o$ H, P6 H - return {
6 \6 c# \! T+ _ - counter: 0
, | Y2 i- _% G7 E2 t - }' i0 A5 @/ ]" ]4 O* A
- }," ^6 }0 e6 a" q
- methods: {
& ?: W T2 t& H+ c - incrementHandler: function () {
) s/ l0 B) P: ? M) o - this.counter += 17 K, D! h1 u" h$ J$ t/ x. l
- this.$emit('increment')* R4 c" z5 |2 z2 J) M
- }
3 m: j* b2 M1 Y0 w - },9 P! T; d, G4 n5 D; p7 a2 ^
- })8 \/ n; i$ P- H. N
- new Vue({) f. |2 \0 I$ e P1 O
- el: '#counter-event-example',
+ G- [6 L7 H0 h4 E' W0 v D- T - data: {) ], Z1 H( \. V8 r$ Y
- total: 0
# n2 Y2 p2 q. E4 d6 D' N - },( z4 t, h6 f6 I B f$ v
- methods: {: v3 j1 B! W7 g& \, P( ]$ M! A* B/ A7 f. h
- incrementTotal: function () {3 I9 o5 F; _+ d G( E
- this.total += 1$ ?, x5 z# s: m1 ?9 m
- }
0 S4 r n1 L, a - }
# v' c& ^2 Z# Y - })% t0 t; j7 z# z( H; G. q
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册: e' \0 D0 [. i! g* S' |
- Vue.component('child', {
5 m$ [0 O4 X" W - // 声明 props
) V: X* J" w: A1 `$ T* f8 W - props: ['message'],# z7 P* ?% o2 G2 h8 {( ^
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
4 h# L0 M2 z) q) s* x - template: '<span>{{ message }}</span>'
6 u$ h* T9 \3 M - }). w. \: g% @+ T9 z p9 L4 H- x/ q
- // 创建根实例/ w! ?5 z$ c6 P- N% y" k
- new Vue({& N$ d+ S8 e& Q( v9 I5 Z, G
- el: '#app',, G' K4 @+ _$ t0 j. T4 L8 w( J8 s
- data:{$ q2 s1 H# P# S0 ^
- message:"hello",
% y, i% S! f: _: `; s, G+ E [ - }: J+ \0 g6 `# `4 ~& D7 j
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
5 V! M5 S$ L) _% B - incrementHandler: function (v) {
/ K& n% t7 l, D) X& k: U# `" | - if(v==1){
. r6 @4 W8 J5 p% f - this.counter -= 1& w0 Y3 W2 _ ?5 ?9 R% p3 `
- this.$emit('increment',[1]); _% w/ c! Z1 c# y! i
- }else{* t% P, M3 U, A! T" T/ Z) m
- this.counter += 1
5 |/ ~& Y, M* o" Z+ I3 W6 z: y - this.$emit('increment',[2]), I0 {2 g& r! [3 _/ \8 `: ?
- }
3 F0 y" z6 G' c/ [: Y: R - }8 i9 H/ Z4 e* n+ W- ~) s
- }
复制代码
# X$ c# q0 G/ V2 {8 E- w) R. z3 R2 X8 G$ m ~1 N1 F N7 J
|