|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: # r- @1 e' e6 M. t
- <div id="app">/ T- |1 O/ i* V$ ^/ p( C6 ^; s
- <runoob></runoob>
0 V! `6 Q$ @+ h - </div>" Z6 b2 p4 w/ g
-
* m8 p: v% {! N: v* ] - <script>6 p c& K4 \* S5 b( q1 m3 O
- // 注册$ U* Y- i! _- n5 i- y" h! }0 m
- Vue.component('runoob', {
, ~; g4 ]) f0 k, `+ x+ v# x5 j - template: '<h1>自定义组件!</h1>'* C. ]/ R% |$ v* N( n4 x! z+ C
- })
* K' {- z- V e, _5 k6 a9 S/ s$ C - // 创建根实例
) Q# i& P% |. _5 p0 D# [+ E3 o - new Vue({, J1 b, ^0 i0 W$ T9 f8 m A( A
- el: '#app'0 l5 ~; ], ^& N
- })
- s! g# y! O/ P. T/ Q - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: 7 k! w- Q4 b, w# t9 b% u3 l5 Y
- <div id="app">* d! A4 n/ n1 r+ Z3 F! G( s2 U
- <runoob></runoob>' F/ f' D. n- W1 X9 E/ M$ s3 [; h+ Z
- </div>
; C3 a& V, l3 ?- O$ p - ' g3 G) F/ ]. G4 k# \8 r
- <script>* L! f' G" c" }6 |7 L$ E& q
- var Child = {
2 @5 f# ]- B' w5 K+ `$ e3 e+ w - template: '<h1>自定义组件!</h1>' F% _6 o$ U `$ h7 h7 U3 W
- }
2 l( l+ @6 p' @ - 1 p& U7 l9 r4 L: P+ J
- // 创建根实例7 j K2 N( A3 m2 M- u
- new Vue({
$ ~: |* e& d6 @. A - el: '#app',
/ J3 {' L Y4 u! X* N& d - components: {* W) y+ E, W* R0 x( _
- // <runoob> 将只在父模板可用1 } z! J7 b& I4 D( I
- 'runoob': Child5 q9 p. X4 c! F) g4 H
- }
. i9 C) c# u1 ~ - })# `) N& u9 v9 ~# {" _8 S
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
4 `* B4 p+ p* h2 }) n) c4 L- <div id="app">. O7 o& z5 r& M q
- <child message="hello!"></child>( _& v0 {6 |) h- U$ W: e2 h( W( b
- </div>/ n* c4 ~2 y( r. k/ x
- 1 f, L2 ?5 N* v7 B+ ?4 T, ]
- <script>
4 m4 A$ z8 \; s1 Z% d0 t) a0 x- C - // 注册
4 g! L f- U, M/ Y% R4 z - Vue.component('child', {8 x* Z' g( m: j1 V. }
- // 声明 props
* ? G6 J, @& J) v8 k" z - props: ['message'],
7 p. Y" D1 v' h9 ^5 p: q - // 同样也可以在 vm 实例中像 "this.message" 这样使用
- B' U; [5 y7 n4 {0 H - template: '<span>{{ message }}</span>'
?5 X4 i, x. H5 P+ V - })
# M" K/ a! s: s Y' K - // 创建根实例
1 q. v' e* t3 ? - new Vue({- }# D; ~& e3 D& c# G; S
- el: '#app'
+ l; V4 B. X0 K2 B - })2 ^7 P0 l; j+ r: A! P- [1 @
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
' D+ f6 \- B! C$ T# ^& c- <div id="app">' e+ V `9 ~% E- h9 c" L0 S
- <div> C1 v8 [ N- |, D* N3 D% s
- <input v-model="parentMsg">0 w6 R' E: t+ y1 h- Y2 t, M
- <br>* k" z6 y( }9 R& i& I
- <child v-bind:message="parentMsg"></child>
2 O3 ?( f2 I9 P9 h) N2 a - </div>
6 z4 O& k6 ]4 P' g4 F+ p/ W8 ?% z8 X" q - </div>
& R7 j4 V( m# I, b - 4 v# K& i! T9 \! c) i! j
- <script>" W+ |" X" m0 ~# }& k
- // 注册
( _7 l6 F7 _% ?$ _8 j/ Q - Vue.component('child', { s) l# o, E. V) X1 ^/ i; F
- // 声明 props+ D* Z7 L! b* U J* A
- props: ['message'],
5 E3 a6 l, c( E ^3 _; Q" l: m - // 同样也可以在 vm 实例中像 "this.message" 这样使用" E* Z! `9 ^# a2 y, }/ d* ?
- template: '<span>{{ message }}</span>'
. a7 Q8 q6 b% [. y9 ?* x9 o/ b - })
5 j" q- w& I7 F! R9 o' Y1 w - // 创建根实例
5 H# K8 ^* }7 U; T - new Vue({
2 \* B5 V5 a- |! i. p. x) A. p- r - el: '#app',* F& Z ^9 R. e% n/ i! u* q
- data: {
6 ]# M/ L, X+ ~$ w7 Y' }7 W0 E - parentMsg: '父组件内容'5 m7 }* r t7 w' v% b j- s0 _
- }
- u6 n7 e+ Z3 u7 [ - })" ^: a+ w& k; ?+ ~" }
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例! `" N/ E2 G0 a( j9 ]
- <div id="app">( T, K9 C1 n' G; V5 U# v
- <ol># x$ u9 r4 t, U
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
: x% b. I8 J; f" u9 T# O - </ol>
4 M5 e* _8 J4 ~8 v - </div>
% k+ P8 V" P" D, F, W - 6 Y8 |+ V% G: B9 ^
- <script>
/ g. m( `5 X# `, H" S9 L' G$ | - Vue.component('todo-item', {
: r8 S$ U2 x( |! ~: s& K - props: ['todo'],; j3 {: B3 S& p" \/ X
- template: '<li>{{ todo.text }}</li>'. r/ V! ^: j& ^& g3 `
- })
/ o0 `# D' _& W3 f* f! ?# m - new Vue({
( g% \' a% I+ S# _: @$ W - el: '#app',
$ z9 H- D0 @/ r$ @ - data: {% }3 A# |' J% [- v2 N' I& P1 ^
- sites: [
$ t5 O; I- a6 e {- ?7 U+ b1 B - { text: 'Runoob' },
1 X$ i) _" s- a& k - { text: 'Google' },1 y% l/ x6 }0 J4 ?: D4 V o
- { text: 'Taobao' }
5 f& U4 c8 g. ~. T - ]# w* [: u+ H. \6 \
- }
( _/ W, G& E `, } - }); i4 [' A- a; h
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {- l0 s! T3 b. y: |4 K
- props: {
; D! ~' P4 S+ t- l - // 基础类型检测 (`null` 意思是任何类型都可以)
/ _6 L! j# C! `6 N6 j - propA: Number," f& n& m: ^. q$ U3 c
- // 多种类型2 K! Q! }6 U3 }4 N
- propB: [String, Number],
% [6 l+ G9 ?' Q: @8 }6 l - // 必传且是字符串( T _7 _6 {5 ?- k
- propC: {0 e, Q$ E6 n! L: w/ X5 W: t
- type: String,
1 J5 [9 `$ ~6 O# X( h - required: true* F4 r0 J0 _; i9 }
- },8 }$ ~1 Y, ]( Y% G6 a0 E
- // 数字,有默认值4 V7 i, ~0 Q- R; M; f* G, `& h2 ^5 z
- propD: {' g. r; `9 s, e* }
- type: Number,- ^7 E* t1 ~( y. M
- default: 1004 I$ G- k) B9 E5 n$ F1 o4 e
- },
2 a! j$ F" q) Z1 ]( R - // 数组/对象的默认值应当由一个工厂函数返回/ Y, ^3 N6 l' p
- propE: {
3 v4 G9 x* G. i - type: Object,
3 |" Z% n3 e& [. R6 N8 P$ X" }) \ - default: function () {
1 T* }3 L, ]% o' x5 ?4 H% ^- ~ - return { message: 'hello' }. z0 O6 K6 e/ K8 \0 R
- }. p. ]6 i1 c" [* Y& c" L8 J4 U
- },* ]# }% c- Y B; |0 C, v' k; y
- // 自定义验证函数
$ c; N) s, u) i* I# X) u - propF: {
% p; n1 x: ], N5 w& {# M - validator: function (value) {
, A% T K& H- ^6 Z- M - return value > 10
3 b# Z+ m5 R) W3 K+ A - }4 g4 S1 ?6 b% D
- }
! X8 {+ w% L+ ]; m1 W - }" O. b2 ~3 X ~
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
0 j& A; y. R( r' M/ d5 F
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
& ]# d# E; H" t8 F0 ~* ?- p$ T9 X9 k
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
: a5 k( |0 M+ E- <div id="app">
" T* ^3 j; S- {- l5 {' u+ h8 t - <div id="counter-event-example">& }/ k5 i0 K; t) T
- <p>{{ total }}</p>, _3 E+ I& t) L! C0 [9 T
- <button-counter v-on:increment="incrementTotal"></button-counter>
9 J: W+ I. e M3 f - <button-counter v-on:increment="incrementTotal"></button-counter>
( X5 h0 J4 Q. ?0 W$ i - </div>
& z" D# d. M+ k$ a8 H7 { - </div>0 }4 R/ M4 w1 t& [% H; o- n
-
8 n: B% `6 O1 \! A& T( b - <script>4 d# |! t: ~5 i; [2 S9 F
- Vue.component('button-counter', {
! J3 _8 F0 s$ g. w, L3 ? - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',0 L* q' Q$ v7 s8 q& a$ v
- data: function () {! w! u' T3 L( C# Z# I9 t
- return {& q9 w+ M, O% O! u8 s' B% O
- counter: 0: ^; P3 V- S5 b4 u' B4 a
- }. L7 _! H# t0 A, P, z6 I
- },9 T4 e* D$ z3 c, J. D# g) n
- methods: {
/ u: l- o3 x6 n' ?0 k8 a - incrementHandler: function () {5 h& a/ U, T N4 F& F
- this.counter += 1
5 Q" j8 d7 D& {& S - this.$emit('increment')
! i' C# M( j' k {6 W& ] I - }; n, O+ D. H; `$ T
- },
- Z( v/ ?! T& O5 [9 w% j - })
0 K: g/ y& ~- |3 f8 D; P" J+ _ - new Vue({
) K, {( A& v' a5 Q - el: '#counter-event-example',( z- ~9 R7 \8 L: F$ |- R1 d3 a5 R
- data: {" k3 e9 t5 r E* F
- total: 0
4 J" M X9 z/ w7 T - },2 D* m, @/ S" p& `0 C3 h
- methods: {
" v- `6 [+ K5 C, j - incrementTotal: function () {, `% G; J# Z6 E! Z) D, h0 z1 k7 r
- this.total += 1
7 x3 c+ g6 b& T) V6 [ - }
5 C, _# C: x4 Q9 F - }$ ]$ j5 t$ G. h# D
- })# U+ D; @ `4 c, ]/ _
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册* H. |2 [) @$ J- [% {4 p
- Vue.component('child', {9 G0 x( ]" _6 e0 f/ o: k
- // 声明 props# v" Y% [" W+ }
- props: ['message'],
+ A3 \, O$ F$ K - // 同样也可以在 vm 实例中像 "this.message" 这样使用
6 o# [7 W- d! o$ T3 }- L9 O - template: '<span>{{ message }}</span>'
8 }( j- e* B3 v8 q! N# c: c- r+ R - })0 p" f. j/ O7 U+ Q ~$ l+ ]+ l
- // 创建根实例! X" n# n, C) p# @
- new Vue({) _5 \2 s9 b( d( \& B$ U
- el: '#app',
W+ F) R' Y/ V5 n - data:{2 s+ }. I- ^+ Y/ h2 h: a9 m" T
- message:"hello",
" z1 X9 F9 I: v* a# ]) [8 g: A - }
3 j3 m( I/ T! ?1 V9 h; p - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {) k* x5 m" e3 `! x( w
- incrementHandler: function (v) {
4 {; w7 o2 p4 [+ L6 @% C3 K, I5 I" w - if(v==1){8 a) F- d2 ^( k
- this.counter -= 13 c, j# Z! u* n/ q
- this.$emit('increment',[1])
) K9 L G0 a( f/ x2 } - }else{8 W. l v" h$ B7 R' h" K3 i" ]" e% ~ T
- this.counter += 1
% }0 V8 p5 o V: Q3 b0 J, H! @2 m - this.$emit('increment',[2])
4 j1 G4 y' e) \. m2 T4 \ - }
, Y ~, U7 _0 Y/ @, z$ y! M3 I9 { - }
4 `0 e8 v: I/ }1 F2 X6 G0 y' | - }
复制代码 9 Y: v) ^$ f2 u
6 b9 T* B4 h" p" f |