组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
( G. E6 s. C D5 Z- <div id="app">
' `0 y. z( P0 k! P! t6 ? - <runoob></runoob>/ V! U# `1 A% Q @8 `
- </div>" p S/ ]" Y+ h' m+ }8 q, T4 i
-
+ I) s1 P( c9 F% m! I - <script>
6 J6 L6 X" K# H- n/ c - // 注册
- F7 y, a D5 z, d. a - Vue.component('runoob', {
/ n) q; s0 F0 M# h/ j - template: '<h1>自定义组件!</h1>'. H' t2 H2 N3 ]6 j3 Y# _
- })
( J3 q7 e5 D$ i9 n - // 创建根实例
) h, e- h' E. v) S9 v3 Y1 Y - new Vue({2 E5 H( G Z4 q0 k
- el: '#app'
: A1 l) Y" g$ W- D9 w( o1 L3 Q* X. e2 M - })( z- V" _/ s, U) [- Z/ R* I
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: ; P; K" T! I% M. r9 \5 R# Q
- <div id="app">+ |0 c3 a8 z+ r# [5 m8 b$ Y
- <runoob></runoob>
2 F w& G. a1 A- o9 x - </div>
0 Z5 i: \! }5 m8 G1 |. J -
9 _; n# |" d/ c4 e) L/ j# c. E. |- c" { - <script>
, ~' z9 c' |4 Z7 O1 h, F. @ - var Child = {
1 b( L- t- I: o& r - template: '<h1>自定义组件!</h1>'( A0 e1 ]) M$ O% h( o9 Z( r9 G
- } m. r6 W5 ~8 l- J" S
-
+ c+ f* S( r! y3 |% z8 K) A4 x - // 创建根实例
* K5 S6 d7 ]7 ]( ^9 r - new Vue({
) Q, J6 @) e& A3 x - el: '#app',
) C4 }5 I0 r: A$ n0 ? - components: {
+ P7 t( L7 C/ \9 K. n - // <runoob> 将只在父模板可用
\* I, m, w1 a1 z2 ], m - 'runoob': Child
^6 s! e2 \' U/ R - }. }( F; s! Q' y9 M) P
- })
, C3 k8 p+ t @2 l" L" d. x& O - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例- [+ D8 _% @! p3 E' a
- <div id="app">; ~6 q$ Z* ~$ D
- <child message="hello!"></child>
* Y6 [, h4 }+ N - </div>
4 N1 I- G0 t/ F9 [: {- ] J6 j+ C - 7 S& W3 `* i( m7 }$ a
- <script>
3 f8 e. M B! o: @+ w! T - // 注册1 \5 O2 }$ O* B0 q! G1 I+ L
- Vue.component('child', {
7 l7 p s# d) @, p0 n% c - // 声明 props9 w7 I2 \4 P% t' \9 f! V- g1 C9 l
- props: ['message'],
' W4 x) R* r% T9 s; i$ D3 i7 E - // 同样也可以在 vm 实例中像 "this.message" 这样使用
n/ V5 o9 C. m* V$ S/ d - template: '<span>{{ message }}</span>'8 S6 u+ T. P! H
- })2 j& ^4 m E# ]7 x. _. O0 y1 S" e1 p
- // 创建根实例2 o, z0 o9 v) J: f6 s* R
- new Vue({
' H" v; x! Q+ F - el: '#app'
9 S6 A6 J1 j* a% w - })
, ~& R, {- J0 I+ ?- b1 [- j - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
\# ?2 g6 Y2 e5 M- <div id="app">
$ j% y- x: A6 N - <div>
2 t9 L. V) r' |5 _6 ]+ c1 W# f9 q - <input v-model="parentMsg">: a, K) r3 i* ^2 T' [
- <br>: D. B# @. \: K: e* ]
- <child v-bind:message="parentMsg"></child>* \! W. q' E+ w8 c5 U
- </div>$ E) e* T9 R+ a: m0 P( B! |
- </div>
5 X* E- P2 B4 e# H0 E - 4 j0 }2 j: e+ z" c! R0 Z
- <script>
8 L9 {- _9 H% Z; ]$ | - // 注册6 Z) h1 r" i- I) X$ N/ I1 A
- Vue.component('child', {0 ~2 y8 O/ j2 [, w9 ^: L
- // 声明 props
7 ^! u1 c* _3 y# r - props: ['message'],! }- s7 C- P1 T* H
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
- [" s' m1 n/ }1 Q' i; s - template: '<span>{{ message }}</span>'
$ V1 N' r; A: {" o1 e8 b - })
- R7 p0 `9 \% e6 B - // 创建根实例# z4 U: t1 w: m
- new Vue({
; b2 }# u- ]$ t) T - el: '#app',! [1 I" M$ S3 B8 w) d; N
- data: {5 ^2 O$ j5 S8 b% @" V: d
- parentMsg: '父组件内容'
" x" P6 s9 d: O) c( V( n1 A% } - }; Q% n: d, P3 n- Y& ?
- })
/ g4 M. Z% B# k - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例+ c4 e) u+ |/ v0 \$ b( `/ ?. s
- <div id="app">9 K4 t. R( U/ ?- v6 Q, \( U
- <ol>
3 x2 K$ G7 _/ n4 }+ p4 M; V7 r - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>9 u4 V9 Q5 y; K
- </ol>
/ `0 V9 a# a6 N# \1 U% F S E - </div>7 k F5 f2 |/ g8 V, v8 s8 K
-
+ D/ r1 C1 D# K$ d - <script>
$ m2 z. y; E. M$ W - Vue.component('todo-item', {
' i! u B- U, q# r - props: ['todo'],
8 A" _) a3 A2 U9 X% _% {5 k - template: '<li>{{ todo.text }}</li>'4 Y& r4 @3 ]# O# T0 f
- })( s$ A$ q7 V% _: A* h2 d; I
- new Vue({
2 D. @/ ]6 ?) I C. Z. j - el: '#app',- A% d3 n6 y. r. n7 G1 X- |
- data: {
' `% ?* i5 V. c5 e! q - sites: [$ B2 i8 H9 S+ K. H2 v) ?
- { text: 'Runoob' },: n7 ^/ y4 |. @9 B
- { text: 'Google' },
( y+ B5 \9 Z4 M4 W) D8 y - { text: 'Taobao' } i& g2 T( T/ a8 f7 d& y
- ]
; @% c: y6 x p; J# R: |6 d. W! U2 T - }& s- s5 g6 n1 |7 ~' E3 V8 f+ H
- })
& s' P9 Y- j2 q+ m - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
% A& B# O4 n; q' C - props: {1 M1 C* j1 z/ h, Q0 _1 I! L
- // 基础类型检测 (`null` 意思是任何类型都可以)# f' d& r2 N5 a4 ]* g
- propA: Number,
1 G' d- v7 M; E - // 多种类型( ?9 |& Z: } \# l
- propB: [String, Number],# ~$ e4 J$ J* b' c
- // 必传且是字符串
. i: G8 t/ B; ^/ { - propC: {
, H! J( ^& d& f3 {7 w! t - type: String,- y6 M) r1 U5 o$ I9 f2 p
- required: true
6 n& y" n& } ^% i - },
% {$ g' N5 S. K' |+ Y - // 数字,有默认值; C' r2 o0 }$ C$ W# C# d
- propD: {
4 j3 j6 N. g$ O4 \6 Q - type: Number,( Y0 J. _. t) _% h( {
- default: 100
0 u1 ?; M" ^+ ]1 a9 L2 n; N3 q - },
# M) c+ ^9 Y; f - // 数组/对象的默认值应当由一个工厂函数返回
" H" d% H- [$ L6 [6 Y - propE: {6 p2 w d5 C7 O: l7 a
- type: Object,; u" C: \0 z r! D
- default: function () {8 C4 k0 g& X/ z: W2 h9 g# C
- return { message: 'hello' }
. s3 X; [) @0 Z5 S; i - }
! c/ S# g2 J, j* k( `" r - },
4 h3 B" h& R$ X - // 自定义验证函数
: {- k9 t* D. y - propF: {7 E. q% D2 F/ e. ]6 V
- validator: function (value) {. V- G+ I% e' c9 z6 @
- return value > 105 U0 C) W. P( `; S5 U. b& \( N
- }
3 K; J# H) J7 t m - }
4 l' _" W( _+ n/ ]# a - }
, h; \ d0 ~8 a3 R6 T - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array- G. R2 J# o `
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
( f: B7 }, E2 B5 i5 v
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
! S9 g, T; b0 z9 r1 \; l! S- <div id="app">
, _1 k$ G# ^! Z" }! k9 B% v/ Q - <div id="counter-event-example">
' X. D5 A1 B$ I: {' `0 k: m* ?4 g - <p>{{ total }}</p>& w- S9 L' e3 l6 [* p
- <button-counter v-on:increment="incrementTotal"></button-counter>
3 C8 L+ k8 p7 W. j$ n! a( U5 f/ ^* t - <button-counter v-on:increment="incrementTotal"></button-counter>
' z7 Z* c' V# b - </div>
; {6 V& n, E% O" c) K$ E - </div>
0 p; w% j0 d: ?4 G J x - ! M8 w( q0 A w6 i' X/ Q3 I% o1 L, K
- <script> S5 R: A2 D4 i6 l- S- l5 b6 p
- Vue.component('button-counter', {
5 E U" C; g; z$ D( O - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',3 V4 P% @2 X& w3 L
- data: function () {+ o" \+ Z2 D# A& D# x
- return {
/ f8 m$ l% n+ M9 P/ U0 m - counter: 09 Z# s$ T Q; i5 J3 Z" U; I
- }
1 A; B+ g7 E+ s/ i) a. M - },
; T# V$ {. s! G/ P) ~! u! q/ n - methods: {
$ c: c- D0 N z8 T' w - incrementHandler: function () {! j0 Y4 y h- B6 {! x/ V
- this.counter += 1; n, k' S k7 {* R, ^% Q5 e- H
- this.$emit('increment')
% q6 I. D4 E# O; t; N E! F - }% a5 E4 T+ |' \" G* d8 Y1 F R
- }, l" m8 K! p4 c
- }) E, C) G! v. D# I4 i8 i! o+ v% U
- new Vue({
, O0 g/ m+ Q A/ U3 H0 r9 a, ^ - el: '#counter-event-example',9 c' k f/ @: k, `! y
- data: {( N/ d/ ~. e( o) n: W8 A
- total: 0
$ T h U' o; c6 r: o - }," m6 k% u; B2 s
- methods: {+ v' U0 i) h, x Y& m
- incrementTotal: function () {' c7 _1 Z) L$ y0 T& p
- this.total += 1
. d; W( _ V1 q5 r2 r( n - }" m* Q; P+ j+ B
- } x6 [* q# z4 F0 _9 `
- })
( J5 V3 a9 L4 [. s8 q - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
+ c) j/ v: j$ D. h W' t. B" r, k - Vue.component('child', {
0 V9 W. k: E5 Q+ q& s1 y* R - // 声明 props
4 l3 ~; J8 M g7 \* B) S - props: ['message'], s- K+ O0 l' ^, S$ i: y. e n. L
- // 同样也可以在 vm 实例中像 "this.message" 这样使用( G/ \" s2 _% d. |! n& W, w! D& Q/ o
- template: '<span>{{ message }}</span>'
0 ]; l. G. J: v5 J) n1 o0 i b) a - })0 v: X' c2 q# u2 U7 b
- // 创建根实例% C* Z1 ?* x- c% q/ ?- Y
- new Vue({
6 p3 ~( ~- E/ m) _$ G: d - el: '#app',5 y. F$ d2 C% X( J
- data:{& v2 y+ u. I8 V5 e( a2 M6 K
- message:"hello",3 W/ u' A4 D7 r; l
- }- x' Z! j. h% L. U! G- M
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
, D3 {- n. H# y& [4 n ?$ C+ p- m - incrementHandler: function (v) {
" m/ e* s1 ^. E7 ~8 R/ y3 _: d - if(v==1){. \9 y$ s) A( o; k# W. N/ D" k
- this.counter -= 1
( c3 i; e* v3 _$ L: w - this.$emit('increment',[1])7 ~6 j; @4 Y. D% R0 r3 e
- }else{
. w* T# D- K) d; r+ q! @1 g" L. G0 P - this.counter += 1
$ D O" W0 j; A" W - this.$emit('increment',[2])) i" D# g! i% P. w' Y
- }1 K8 i1 Z7 V* N+ b; }. R
- }
# N' ~- ?9 k& a/ I" O - }
复制代码 3 O- \/ R8 O# X$ e
( l: ]/ s/ u% I- Y
|