|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
& M# u" U' i9 }4 }1 J0 X- <div id="app">
$ v2 q; o1 ^* }1 A - <runoob></runoob>1 h$ _2 E4 x; D! y3 k0 m8 n4 n
- </div>! A! `* i: v/ S9 d8 P" ]' d
-
* j# o9 i7 g0 u0 z( m; P* K' X - <script>
" I- J' |: q. } - // 注册
6 u( `* x% \8 b) E; Q/ v - Vue.component('runoob', {7 k8 a% _" y6 W; ~/ R
- template: '<h1>自定义组件!</h1>'
2 ^4 s5 D+ S5 w7 u: B( a - })- x3 ~$ w9 C E; T
- // 创建根实例' ?9 d% r* J' ~0 X, r3 z
- new Vue({
: F) F" N6 m* ]" r - el: '#app'
/ u# |: p' f. y9 x! I' Y* q - })
. e4 y0 I r( `( L: S - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: 9 H. C" M: A) ?' I- [# V
- <div id="app">* t7 }. }6 r; ?/ m4 J7 q
- <runoob></runoob>2 g( x. q, m1 v# ] p9 W0 q5 y1 ^
- </div>
/ T3 X' J# Y& M% _ - ' q" w' f8 {8 {
- <script>
* W9 H2 y- t% v/ y7 { - var Child = {8 P) N0 O/ p6 v' x" N+ Q/ h! u
- template: '<h1>自定义组件!</h1>'2 b9 A# H! K+ I$ U9 f# t7 q( x' a
- }
! X _% {1 W+ z/ r: s) S - 3 A' N7 x" w8 v% g; z
- // 创建根实例
2 v3 k! t, g4 C$ z' w5 P ]$ ] - new Vue({
) ~& P: w1 Q, m! h7 s% q" [, c q - el: '#app',
. H0 r) N0 `& G8 t - components: {
! Q9 f% U$ ?5 m0 r9 ?% z - // <runoob> 将只在父模板可用
3 r6 X% ~/ U4 \2 x, a" ~ - 'runoob': Child8 B# l& t5 \& v/ Q
- }* N3 Z/ F/ P+ ` G9 ]9 I
- })
& U) {0 t9 R k$ Q1 L3 K - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例3 X, Y- M/ {2 |- x2 W7 K0 M# {
- <div id="app">/ o m+ |3 _/ L4 X/ A2 Y/ n
- <child message="hello!"></child>2 D( v7 ]; I5 x7 o' D* _
- </div># q# k6 f$ G- I7 O
-
) a; w2 |' `3 V; f" P, O: |$ N - <script>
- N7 J: a* L5 J3 V e, E - // 注册
+ w d1 [! p2 Z$ q - Vue.component('child', {
d) }' q4 i# T/ W# U - // 声明 props
; S% B( i3 o# u4 n; ? - props: ['message'],
& Y$ W1 M4 N& \ m* U8 a* u - // 同样也可以在 vm 实例中像 "this.message" 这样使用/ k# J8 H9 x: g+ r; P8 C! P
- template: '<span>{{ message }}</span>'% P7 U1 S% x* {: Q" I
- })
5 H9 l( X7 k: e7 Y - // 创建根实例0 T2 W- s9 S) p, J8 U$ f% t+ ~
- new Vue({
( u* T9 M# P7 Z, w* i6 A- _0 S6 m* E+ Y - el: '#app'
( [" `* i: n o& v! [0 W% Q$ g - })
$ P1 F' p' z, L3 q0 z2 I - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例$ F; m/ h7 a% U9 Z3 W8 Y
- <div id="app">* c& t0 ]. A0 \: l. c
- <div>7 ~5 @4 s2 v$ F0 l
- <input v-model="parentMsg">
! L" F, }% z5 g8 O4 Q - <br> `5 V$ j; t1 C0 A* q: \' J5 g6 x
- <child v-bind:message="parentMsg"></child>. u: Y8 r8 ~& `5 I0 D& `7 G) V+ r
- </div>
9 E6 V R1 d$ E2 i7 V- b - </div>6 x/ `8 c4 c _
- & b4 a# [4 ]" g9 k' i, L
- <script>7 H5 Z* N7 r5 q; d
- // 注册0 t1 V9 k# R" @5 X6 O
- Vue.component('child', {
) N6 D0 ?; H) t8 K& q7 Y - // 声明 props- T/ i% D" m3 g$ A2 q
- props: ['message'],) s Q& l1 f( S8 T
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
; z8 A$ N; F' M# S1 D7 n - template: '<span>{{ message }}</span>'
1 P! V4 P' V& v) ?3 `2 X - })7 a' G' T# w2 `! l3 ~2 D& Z q
- // 创建根实例! R; l+ U Z, n9 y
- new Vue({! d& a% X: w% F2 P1 R |/ e' h
- el: '#app',- k" U* `5 x2 p" A8 J0 q7 u
- data: {4 [- _3 x p8 `) j3 p
- parentMsg: '父组件内容'
/ t: l' m8 u8 ?# I# |+ m5 u+ q" E - }
% f9 @& F$ W! S) ]: Z/ y - })+ w/ t! z) Y+ E) d- f: H$ w, M5 ^7 Y# Q: c
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
* Q% i; |" k/ w2 U- <div id="app"> ]: j5 t2 z' Z% i
- <ol>% i0 M& |2 y# S- J- M" @
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
& C8 I2 n% H) p8 x' { - </ol>: i0 J9 ^/ a* l4 M7 B& U# v
- </div>/ |9 L1 \ M7 c. f5 j
-
* P* d6 a) A* d - <script>
" h+ S. O. b- E9 U2 v& |. v - Vue.component('todo-item', {6 g, Q) q; B) v% x4 x- V( A( Y5 J
- props: ['todo'],
! l2 ~' p. H! X; ]) Y - template: '<li>{{ todo.text }}</li>'
3 h; f+ C6 L. C - })
; c3 f& m: g$ x7 S( F/ C% _; P; ? - new Vue({
. }. p9 L2 V" I7 D - el: '#app',2 q5 p0 X* N1 O- m
- data: {
6 Z3 k/ k6 J+ t& o# U( C0 j - sites: [3 ?. X. H! s% H* \3 r
- { text: 'Runoob' },
6 q: @0 F9 x& c% W - { text: 'Google' },2 V: t% ?7 o, Z* p/ P
- { text: 'Taobao' }' I5 }- j& }- N4 s8 j* J/ ^* a
- ]9 e0 \; D% Z6 I
- }
$ M: p f* G5 G - })- W) ~5 E F# K$ L$ i( `; u# N
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {0 ^3 m* a# g$ I J4 k5 W! L' t" V
- props: {6 Q: `+ v+ C6 I& U0 a, J4 o
- // 基础类型检测 (`null` 意思是任何类型都可以)
. \9 F: h7 Q# U8 F" o6 ] - propA: Number,1 S& g- N+ D+ v7 ^: ?
- // 多种类型
; R1 c% s1 h; A$ ]* j* }" O - propB: [String, Number],
5 Z, Q0 i+ H, F+ v6 f* P; e - // 必传且是字符串
] X" f* x' Z7 C - propC: {6 r7 s5 {; @* i; Y8 E
- type: String,- H x6 T- `# `4 s" x1 J! q4 s
- required: true
; G" Y+ z; V2 w! A7 F8 ^ - }," k( i; S( n3 f& ^
- // 数字,有默认值- A) j" D( U0 P/ w: W
- propD: {
; ]; A8 |) S: s- `4 `8 c, J B - type: Number,
/ Q8 k. X; l* q1 C9 H; j - default: 100: e' G1 { j& _6 e5 W5 {
- },
! R% @% A% ?7 [. h, A0 M - // 数组/对象的默认值应当由一个工厂函数返回6 u; T' i. d, }5 p' c
- propE: {/ J* c+ G( G. U# d9 ?4 T
- type: Object,1 \# {( u2 l6 c/ z
- default: function () {
/ B6 H: \9 T! D8 R" Q - return { message: 'hello' }
3 j8 P# K7 V5 D+ b9 L - }/ B3 I" o6 Q9 g( M `% M( @
- },
5 K9 Z: V0 ^( v& |$ S3 l- g - // 自定义验证函数
8 Y5 ~5 @$ V+ M' ~8 b/ z6 b/ } - propF: {
& {# s4 l3 O9 ^$ J# a& a - validator: function (value) {
' ~% d' _( \9 e/ b7 O& T - return value > 10
1 O4 K5 k# t2 `3 p. F! Y4 u9 A' f) l7 C$ o - }% I4 m* s# a9 j. ^
- }: g( I1 z a2 W! ?% T+ E
- }
6 ~1 Z" U- B5 ?; |0 y - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array: s1 E5 U; i0 p# J+ ^# L6 }
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
( u( S M6 X6 r
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例2 J1 w2 [3 S9 e/ z' w% E
- <div id="app">7 j$ E ?5 ]$ t* ]8 k- n/ `
- <div id="counter-event-example">5 w! N" |! c1 z
- <p>{{ total }}</p>( t% m8 i0 c* R, F* J, }# u8 q
- <button-counter v-on:increment="incrementTotal"></button-counter>% ~% W% }$ Q) v* W v$ C- H8 @, ?$ G
- <button-counter v-on:increment="incrementTotal"></button-counter>
7 R$ \$ o$ \6 ]- _6 H2 W - </div>6 h. n: j$ X" J- Z, X
- </div>
) q" b9 j( P1 d% A1 @! R# ` -
+ v; E; u2 b5 ~4 ~) S4 z/ } - <script>6 ^: i- H9 X4 R8 F* n
- Vue.component('button-counter', {
6 A8 n) ~' C" ]9 b9 |) d, z- {6 I - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
. R7 U. G# K# a* ~, ~' } - data: function () {
+ G H5 I1 l+ p/ N( V |. X/ ?5 f - return {
. K/ _: b9 V1 B. G5 B5 a - counter: 09 n# e6 X3 ~; o/ v
- }
$ D+ z/ F$ E1 k' a, X - },9 F# b! v5 w" t) v. ~0 j2 A
- methods: {
, H q* h, N/ L8 [. f: q% E - incrementHandler: function () {
* P+ q/ T# p- ], ?" K3 x. j/ K - this.counter += 1
- ~4 l) T- G, p) \2 E2 E7 n - this.$emit('increment')# C) q' d. N( x, A1 e) P! _2 U& c. G
- }+ y [& u0 U0 c/ w6 m+ u
- },
+ P& {7 x0 R/ G- x, G: S - })8 h% U) W/ N2 t0 g" k; @$ t- K9 E
- new Vue({, W- i2 T6 u: ?$ h
- el: '#counter-event-example',# {- Z: R' |" ^, x; D
- data: {: V: |7 @" z4 {1 p
- total: 0/ y1 o1 y$ k* e* G% z$ ^! H; Q
- },5 B8 F8 ~$ i: \3 K. e0 p! }
- methods: {! d1 C- H* z) h. C! |: J, |2 g6 p
- incrementTotal: function () {. D/ _6 l/ L5 W# \1 q6 L" Z& w
- this.total += 1/ N- |- @: s+ P# b& }$ ~, L
- }
; k% `6 I. k |& t7 P% {1 U8 w - }. C* N, k# S ~# O
- })+ w+ C5 o& o0 b6 C
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
. n: D% G, Z8 y# ? - Vue.component('child', {
; P- Q9 l4 w5 T" `4 D' L& d' { - // 声明 props
" a% {$ a6 Q% [# o2 y5 s - props: ['message'],
5 x- n) ]7 v. o; z9 N- F' v' Q/ T9 ~ - // 同样也可以在 vm 实例中像 "this.message" 这样使用( P0 m5 b/ B+ J9 Z. `+ T
- template: '<span>{{ message }}</span>'. w2 m. a. Y$ g; B& d. u) M
- })
+ s! Z; Q _; e* V3 V+ o - // 创建根实例
9 `2 @. [/ C _1 c7 v# k1 ^7 C - new Vue({) w x* \7 i/ h0 R8 u
- el: '#app',/ B9 ]9 x2 P& Y( q0 e. T
- data:{
3 L7 G/ r, I. X3 V - message:"hello",
0 N! o2 d# u6 o. ]9 h; E, L - }
2 J9 `+ G3 e8 F7 h# g - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {9 D: G0 }) I& p w
- incrementHandler: function (v) {+ c6 K. ~; P' O" p: V% m
- if(v==1){$ z, w& f+ q! T( @. q
- this.counter -= 13 \- I+ p O" Y
- this.$emit('increment',[1])3 N7 z& a0 I( F2 `2 L2 E
- }else{
% F, l, ~4 n+ t - this.counter += 1
2 O0 j6 C) E" J" ^% u% X - this.$emit('increment',[2])
2 f" ?& t* r1 E* ?: W1 |. T2 X, K& { - }
N) v) `$ ?. E0 T - }
' U$ K3 h8 M& j' \ - }
复制代码
5 P9 x/ u# t+ M y' X% @4 v' z; G' C9 |( X( _, ?
|