|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: 8 o- a8 [8 \0 b4 b" c7 h
- <div id="app">
' U7 p7 ?( K0 Z8 g' I - <runoob></runoob>
. L% R# m$ A8 R+ c. ~3 J. h( } - </div>1 z5 _) ^+ C- ^- c1 Q
- 2 d1 c. \, }- o. |7 ?; X* ?
- <script>
* M( o4 J. h. k& ~ - // 注册, \" I/ e4 q8 p
- Vue.component('runoob', {6 _/ F. d; |8 J, e$ S
- template: '<h1>自定义组件!</h1>': v% M. X) z8 n& R& K
- })
9 n' Y f8 A& @- z! @" G2 I - // 创建根实例# X7 i+ K3 T5 N
- new Vue({
9 F9 S# d6 X% }% g) s' z9 f - el: '#app'
2 v# y7 G: r; z; |* { - })
2 z- \+ q! m8 B( ? - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
: V/ T9 B# h+ Z. @* j- <div id="app">
' `( N) ^0 P. C% h* r3 @6 x: O5 p5 H - <runoob></runoob>
; c4 J% m0 [& N4 G - </div>/ u$ T) N0 Y* z: q2 m
-
1 Y) f& }6 \. G# [# s5 O - <script>/ @4 ]& r; i# b/ ^, P
- var Child = {; c. H, ^) q; w0 r5 ?' D5 }
- template: '<h1>自定义组件!</h1>'
8 Z; ?- @! K( q' U v! S - }: l4 h# P* Z) R
-
& X) O; e; R$ U- E+ _, @ - // 创建根实例3 f* q) X: e- [% L& S' d$ M1 W
- new Vue({
5 b- q/ n, l4 y. Q* T0 q3 Q9 G1 L - el: '#app',
2 V' @$ Z" x1 h4 L) H- C) F* C- i - components: {# j6 s4 x% Z6 s6 I8 p9 O
- // <runoob> 将只在父模板可用
/ B7 |4 _* W1 O. J+ V) x - 'runoob': Child
; G5 M+ k- J% S& ~$ [2 ` - }7 L F3 n2 y" z9 {4 ]1 W
- })$ R' P: R! k4 T: k3 s/ |3 }: x
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例# X' Z) x. `) ~" t
- <div id="app">+ r7 S& l8 n. S1 b; _$ `4 j
- <child message="hello!"></child>
4 z% y y. J- M3 B7 ^3 a - </div>- r7 w6 d! i# E, I( T
- & ~5 I2 I j/ z' p o% X: L( o
- <script>
/ A% c+ O* s! C8 k4 r# L - // 注册+ J% S, w$ L Q' v3 k4 L6 A6 l
- Vue.component('child', {! T! E0 u& T9 h% V0 g; }, a7 b
- // 声明 props! |. p1 T c$ |/ ^
- props: ['message'],
! D4 u& T" p7 }: |1 O& L - // 同样也可以在 vm 实例中像 "this.message" 这样使用8 t$ I/ }( T: G+ S* i
- template: '<span>{{ message }}</span>'
) [, c) f1 V1 r- i" d% o - })6 }5 c1 A' G7 D) s
- // 创建根实例* d: U4 S3 c5 j: R& d# g. R/ {
- new Vue({" e8 K6 [! q5 D
- el: '#app'
$ s W# O/ n3 C1 k4 M2 ] - })
! }$ q* ~ h5 y7 F% R - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
: {8 M# ]# f8 R5 o- j' l/ g% m6 g- <div id="app">5 N% r* n" O$ s6 q; o" W$ q E
- <div>
" A! K) }4 H8 Q6 }8 i9 g( b" b - <input v-model="parentMsg">
, O5 W; w$ j* ?# F& |) E' r( J - <br>- q; ^4 |* p8 g* I
- <child v-bind:message="parentMsg"></child> V9 ?( p+ m" ?3 }7 R5 @% I
- </div>
+ r8 P5 P8 N) |7 h6 K - </div>
8 ^3 M1 C( Q6 K% B1 L -
2 D7 w5 @. l) F; X - <script>2 e" `% {+ {( N, b1 y! c. w
- // 注册$ e+ j8 d4 R4 c, ]) u
- Vue.component('child', {4 q3 g8 n9 R* B, ]: G, _
- // 声明 props
% x" v M6 ?' S - props: ['message'],
2 W# m, {! Y! ^# F1 z2 H - // 同样也可以在 vm 实例中像 "this.message" 这样使用
. ]3 a2 |& m) f - template: '<span>{{ message }}</span>'
" m- X* C0 \3 }; u! ]! H - })8 z$ G4 {: z9 w' A$ Y3 e
- // 创建根实例
* ~* g0 K" m& S: U. X$ w* O+ H - new Vue({$ i' x" Q# D/ e
- el: '#app',
! |5 X- x& J, q; j. y - data: {
; e2 u$ t0 I" V+ o+ T% } - parentMsg: '父组件内容'
( b3 p# S! J! ? ~- X - }% S G0 E1 L8 N4 e
- })
9 o: A, @2 e: U. B: P7 V - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
2 _5 k0 x' b+ H- <div id="app">: D @: @, X4 V2 C) W N
- <ol>
+ ^) i, l. T" {, b F - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
) G# K# K: Y" U4 N% \4 } d: Q- X - </ol>
0 O( M& Y: o3 u; l2 { - </div>9 C% Z+ i+ f# d' o# ~
- , {7 e6 a2 a+ _' }3 k# m
- <script>3 |# a" v7 G( E
- Vue.component('todo-item', {
" m. ~8 B, w2 r3 j$ ] - props: ['todo'],
& e/ q+ U% z3 g" @% ` - template: '<li>{{ todo.text }}</li>'$ x! b4 b, ]1 W3 i
- })
, _3 u# p$ e# T! v! d' @, b - new Vue({+ ^ o. j0 V0 P h* G" x! O6 u' J
- el: '#app',4 O; r6 X. E( i: B
- data: {
3 L' ]5 ~# m# ^# X - sites: [
, s C2 D3 b1 G b( z# [7 J - { text: 'Runoob' },; z n8 F" M$ ~; ]& m) t' W
- { text: 'Google' },; H; v, G% P; ?1 \* {
- { text: 'Taobao' }
4 O3 p: j0 U& ~ - ]
1 h! C* b5 L3 W" J j - }
% P- a, D) l2 v1 I7 X0 I( X - }). ^/ D' Z5 o4 l1 v& f6 e2 {
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {, k/ \ k5 `2 D$ i7 d
- props: {
9 q0 B5 v" u6 d - // 基础类型检测 (`null` 意思是任何类型都可以)6 m( [- W3 {8 e3 N6 |7 W" h! W
- propA: Number,
& M7 ]+ B2 f1 s% v: q - // 多种类型; Y2 J- e8 V6 e$ s* }$ u
- propB: [String, Number],9 J$ `' F9 x- ]
- // 必传且是字符串
4 l9 l% w8 O/ R- ^6 i, W) z - propC: {
* z1 M1 L. @ L, W8 Y/ B! B$ P - type: String,4 C/ C6 f* I, N# T
- required: true3 T g/ S0 [+ f! C2 u
- },
4 X- K' e0 E B0 l* m( b - // 数字,有默认值
4 |, |: M7 U+ M$ F s* ?" V! N - propD: {2 M3 g3 S* |! ]. W2 ]7 F
- type: Number,: @# g9 z& k5 A$ O) C4 Y% a( c2 u# X
- default: 100
+ r3 d/ O: y$ T/ _5 Q5 x5 m+ E9 U - },* L" O. L, J$ R# C
- // 数组/对象的默认值应当由一个工厂函数返回 i0 s- \. w1 d8 `
- propE: {% j) s$ `) c/ |2 ?# @2 o
- type: Object,9 [% G6 r. Q* _! }6 \# ^8 S
- default: function () {
! ] C3 ~$ R; ?8 V - return { message: 'hello' }
/ o* Q6 I8 h+ P6 D$ Y+ | - }
. O: k5 I: q% G0 C% W: g* I3 a; U - },
+ C& p: y- I8 }* G$ q - // 自定义验证函数* w8 S7 k8 P4 x: R- h, Y# @* a
- propF: {
; v* k; B$ _& L. y$ ~5 `$ g - validator: function (value) {5 X P A. n) \+ w( W6 U* Y
- return value > 10
3 s1 t6 P6 h6 P+ B! `' ]/ ] - }& H/ ^1 i) D6 ^
- }
' O8 x& |# u P - }
5 y2 F3 L2 K3 x! X. \ J - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
" j# {# `/ c! O9 ~7 u
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
8 n! G& `. r; A1 x; m; R5 D
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
6 x5 a5 X; r; |9 |- <div id="app">& c, S9 M7 l& Q' A7 r, L" n
- <div id="counter-event-example">5 @8 c# g$ b/ {9 F V( D- p$ {
- <p>{{ total }}</p>
) \/ M F, ]6 @7 T& O - <button-counter v-on:increment="incrementTotal"></button-counter>2 F& G1 I5 v/ q( A
- <button-counter v-on:increment="incrementTotal"></button-counter>4 C$ u A: L8 U, L- D' ]6 e2 t
- </div>
3 B9 A A8 i& w1 d' U3 _ - </div># }- H7 m/ Q' e* Z
- , Q% m* _" r+ h: }: |' ?- W' P
- <script>$ g; M7 L) S: c
- Vue.component('button-counter', {+ z' @( S: K; e9 h
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',- W3 h- l' k) B8 y2 [# m; b0 b" T, Z
- data: function () {
: ? n' J b4 d - return {7 e/ _2 i* g) `4 |, h' v5 @$ W4 A
- counter: 0& [" k0 ]$ v o& U8 h) |5 n% C8 v0 K
- }
* Z* C! h8 H" m/ D4 Q - },! f8 I- w3 A/ f% n$ h9 _
- methods: {7 _. T, i; o$ k# t
- incrementHandler: function () {
/ ^5 Q0 H9 p8 n6 ?. r+ Y - this.counter += 1
, D9 v/ a* M+ c" j4 A' t4 f - this.$emit('increment')
) B0 P4 q) F& \! O8 F2 T - }
0 W1 ?3 a! l9 v9 \/ m+ w2 q - },
5 A" G6 X. l/ B [9 y! `" e O - })' x+ a! ?1 B( U
- new Vue({' q2 K& b; r9 j1 `0 F" H* v. l0 H5 W
- el: '#counter-event-example',9 \* p+ P5 U/ }9 Z6 s, G
- data: {6 A2 O: f+ z! l/ P
- total: 0
! t) _ r- a @5 J0 h Q3 D - },
8 W$ L7 d& j6 { - methods: {1 z; e# ]( F& u% V* }
- incrementTotal: function () {
, T a8 o: M k- C v' L- }; f9 B - this.total += 1& V) K! i; u7 o2 w, p+ D2 k
- }
$ G0 w+ d1 Z( i- o - }
% P, I+ h4 |' {- }* [ i0 i - })
( v2 L& L/ ?7 M, M* x - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
' H% Z9 |8 O% l* M7 ~2 Y+ p) P - Vue.component('child', {1 @$ G# m3 I. w" R% Z4 N6 W5 G
- // 声明 props
, n; D3 o5 X7 i9 F" M) N# v0 W+ B - props: ['message'],: R- q. V8 ^. g; L% j8 J
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
" P* O Y: H v* r - template: '<span>{{ message }}</span>', e q) L8 ~# i
- })
7 [+ z+ }; s$ u: A3 A* g7 Y+ F1 i - // 创建根实例
: W( E' w% F+ k( p! }4 E - new Vue({" K- P4 t( Y1 D5 G6 W: j: L' I
- el: '#app',* ^: R+ r5 ]- v2 H( E W
- data:{9 K. Q% B S6 \
- message:"hello",
d3 s4 l2 N4 |$ ^& F U4 V7 n - }/ C8 h5 t9 X" ^0 D! H4 _- g! s
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
; U" l3 i' N; u - incrementHandler: function (v) {
& }9 ]: J1 W4 d% n; ` - if(v==1){
: o, V5 K$ A5 P- J' S ^ - this.counter -= 1( F# }3 l) N$ ^6 I% V) i
- this.$emit('increment',[1])
0 H7 j) B( \* ^) N |6 [ - }else{
# ?4 n- P& |* v4 e - this.counter += 1( e9 N, \0 l5 W$ }1 {3 s0 Z
- this.$emit('increment',[2])
$ r/ p' x7 F1 _* p - }
9 C% ]! ?4 e$ c8 q6 C. {/ ~ - }
( p" L- V" a$ P% V, @: \: _4 Z4 R3 p: H$ n - }
复制代码
7 p& b7 B' b; _- Y! b6 j0 R- w- I. L" O s, ~, i; J7 ?
|