|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
. k* E/ H! S" L- <div id="app">
5 E2 A1 l& B3 G2 }. s6 J - <runoob></runoob>
' \+ S+ v" O$ \. q/ _5 X8 G9 C. D - </div>& v% o% i) L( T7 g6 e
- 0 ?. ?0 _7 T" f9 @$ Q/ }
- <script>7 R9 s/ N! U9 c9 U- q
- // 注册
; X6 b; e- d; B3 J$ ~ - Vue.component('runoob', {& j% M! [0 |4 f8 f8 b: R6 B
- template: '<h1>自定义组件!</h1>'
# y7 u! G m) H3 l - })2 p% ?2 a3 c9 O; g
- // 创建根实例
$ u: X! o; ]& s - new Vue({: l7 S3 {9 Z+ B7 h
- el: '#app'+ m; F6 K4 u ~" S% T
- })
& G( R$ W6 y9 X: }1 j - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
: u1 `9 ]# U& O1 r6 [ N y- <div id="app">
# t( u. z* R, ~8 g4 M; V* N - <runoob></runoob>
) q9 Y x2 W0 ]7 Y& n" Z+ v - </div>5 {9 b' z) f( v# \
-
' J, i5 X" e9 N9 Q - <script>
4 }5 g* x9 S( i+ Z4 J" M' [ - var Child = {! K- G- o: r9 L x! Q, y1 g9 _" Q
- template: '<h1>自定义组件!</h1>'% W9 V7 r7 M" p$ Y# m
- }6 Y" H# I/ j( x
-
5 p6 @, u$ W/ N! M% ~& H/ K6 m& I - // 创建根实例
\9 u: D# Q- x- | G" x - new Vue({* a7 W* _- h: V8 ^' y% q% i8 o
- el: '#app',3 B7 ]6 Z' E0 y
- components: {' R( C# E; }& W. m+ m. s4 s- h
- // <runoob> 将只在父模板可用
" l# j9 |' C0 Y. h$ K - 'runoob': Child
" W% r: e! T) a9 Y - }
* k2 d1 I) Q' Q" E* j - })! m9 s! {' U* M9 ^2 H% m4 N
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例) g0 l. N5 J( p3 @2 N2 H" |
- <div id="app">9 ~5 d+ b; D8 J; o W
- <child message="hello!"></child> m5 n( e1 q, o1 l
- </div>
) r' I5 N+ A8 J) y7 P" n4 _ - / G2 n3 F, z2 F/ @7 N( M
- <script>- j! b3 g$ d% R P
- // 注册
- |$ g: J7 b I( k# f% a - Vue.component('child', {
& E I2 X7 v! |( j+ @5 U+ m2 v - // 声明 props5 b6 g! O3 R- A% R$ C
- props: ['message'],$ q6 T7 {, u! S
- // 同样也可以在 vm 实例中像 "this.message" 这样使用) \' f1 Y7 R( V1 E! N: t
- template: '<span>{{ message }}</span>'
x1 U! \) r) f& n6 `; P. l6 P0 b - })
8 Q" Z/ h, H$ M S0 L* ] - // 创建根实例
3 v/ j1 I0 [ ~# w - new Vue({2 a1 z1 R( y. D
- el: '#app' L9 V5 O2 M$ U9 ~) Z% p8 m7 h
- })9 j" l- r4 ~" k/ l" l7 k" e' O
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
$ d, J; @0 ~2 p8 c8 c- <div id="app">
6 ^5 Y- A# I% t5 \* ?! k - <div>
' |' ?1 F0 w0 U6 r) T2 P1 J7 L - <input v-model="parentMsg">% }! f0 F$ c3 [ p1 @. [
- <br>
9 p3 _1 O& B0 t, x - <child v-bind:message="parentMsg"></child>
2 \ T9 a. I/ k; `4 l* f6 V - </div>5 H! S/ N% k# k$ I# n: x- C+ c D1 w
- </div>$ V! S3 D& ^# s& ?
- * b* `' }8 }) K- d, q, s
- <script>
* L' S, }! ^0 m7 T! G8 J. v - // 注册
# @- T( S- k3 V" d7 s1 } - Vue.component('child', {1 Y; _& _. {5 T
- // 声明 props
$ ?3 d5 H# R- G. A2 M - props: ['message'],
p! g3 k3 n7 L0 Y7 B - // 同样也可以在 vm 实例中像 "this.message" 这样使用
2 H, J0 E: g0 f0 U6 {$ Y - template: '<span>{{ message }}</span>'
" a4 K" Y' C! _: P - })
) h# g# A& b7 v - // 创建根实例' z5 d* F9 T" l
- new Vue({
& f( U, Q& E7 B; q - el: '#app',
- c1 Q- W$ p$ P& w - data: { k& g7 U/ d5 |& {& q, ?
- parentMsg: '父组件内容'
# t; B) @0 k* f0 x* `6 O7 R; @ - }( v0 m4 A* q: d) l
- })
( o9 r( E1 h9 B - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
; e6 r; M+ S# U- E9 o- <div id="app">
5 u N' M: u5 F8 N - <ol># Z9 V, a6 R6 A: @+ b5 z) f+ f' d- m0 U
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
1 @) w. z) {- {+ O - </ol>
; o `5 v8 C; x( K y - </div>
7 Q. y! S" I2 y8 e - ) B, o( K. P/ }1 @: v
- <script>0 \" X: o8 M$ X5 L
- Vue.component('todo-item', {
% u6 P- e) H# v" K% p: u4 Y% S - props: ['todo'],
9 @2 K0 a# j8 Q2 U8 b7 h2 m - template: '<li>{{ todo.text }}</li>'
% C9 p7 H( b' q: ~8 r - })% M6 n& ^0 ~- ~0 u" s* p6 [& u* W. [9 @
- new Vue({
& x! J0 o9 h; G" a) N3 Z; r1 @2 Z - el: '#app',2 |, w5 }" _) }& q7 r. i* x$ R& E
- data: {% C4 I$ m0 M$ x- M: n) ]
- sites: [
2 h2 N8 O0 F; `% Q+ P; i - { text: 'Runoob' },! [' i! \- V r) X- w
- { text: 'Google' },6 J7 g N( h/ X; b+ [+ d+ }
- { text: 'Taobao' }- \9 w3 m" Z! K8 x# l
- ]
0 S1 I" W& N0 H* Y- z - }2 @7 y E2 m3 J; ?* N: M# U' W4 F' R
- })" v& z% a) T7 u4 z h: ]) a
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {9 f$ X( B% f W0 X
- props: {
& @5 J2 o# \: J' p9 h f" D - // 基础类型检测 (`null` 意思是任何类型都可以)/ u$ U+ B. p& V& Y l# a- [9 A
- propA: Number,
; k+ q+ p2 j3 p _3 q - // 多种类型4 Q5 ]# F7 i7 Y
- propB: [String, Number],
$ ?$ J+ ~( B& P2 r0 R/ l - // 必传且是字符串+ l/ m- }+ b C. v1 R
- propC: {
9 s6 j& b! H& ~! R, x! u - type: String,
1 {2 ]% v" c$ |' W9 T/ P8 H - required: true
( g' F. V' _- d8 [6 q7 I# E& v$ Q: e - },1 ~* R& k6 E& f- F0 F8 `, ~* {3 v
- // 数字,有默认值
8 y* U4 g e2 M% F$ D' p - propD: {8 |) w- l9 y _1 S
- type: Number,4 _. A- ]; l# ]( K, l, O0 F) V ?" j
- default: 1003 P2 H; S! w/ t/ o4 J T
- },
4 W. u* I" \2 c - // 数组/对象的默认值应当由一个工厂函数返回- ?( [" Z8 K; o
- propE: {
0 `; F* j" O, k8 X' J - type: Object,* t; Q# s5 L: A' r) W0 d
- default: function () {
( O! u% Q0 E" s$ n/ _. h9 p& V - return { message: 'hello' }5 V1 |+ P0 Z; [6 w9 m
- }
9 _6 U% [& `( k' j# R7 m& E: u - },
, p; b: z4 `0 E) A - // 自定义验证函数. W" k7 g& q9 j1 {2 W8 V( k
- propF: {4 o' n* J5 F3 J4 W
- validator: function (value) {
, s6 M9 n! F) m0 T( m# o - return value > 106 f8 x7 `1 f% d2 o3 d
- }6 J$ S6 d% b4 V4 `1 v
- }; D; V) c" u0 X$ ]) T7 q
- }
W( P, L1 ^2 Q5 {: m- q: D - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array1 d( ] e' y. Z! H4 H: Y! [
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
+ z2 v) `6 |1 U2 [; N& W
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
0 J2 S9 \. U: L4 o- <div id="app">
( \5 G4 u3 e W3 a - <div id="counter-event-example">
2 i4 B) F5 r0 ]( O - <p>{{ total }}</p>! B! T! z8 x4 |( I% }
- <button-counter v-on:increment="incrementTotal"></button-counter>
9 W: m4 M4 H" J! _& W, N9 j - <button-counter v-on:increment="incrementTotal"></button-counter>
( L4 m4 H0 x( m. {6 e4 s: H- k - </div>2 i( S( A+ ~' k6 s+ @) B
- </div>
6 u$ y; ~$ [4 k -
. I3 J$ E0 m$ E7 K# z3 w - <script>
! P+ M+ T5 q' ]/ H/ A# h& \ - Vue.component('button-counter', {, \1 Z7 S, I( z! ?
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>'," b% x( K/ {' q5 d9 }
- data: function () {$ k$ z3 y/ `% p) {! m2 r
- return {
# _" X" y s$ L4 U3 U+ Q- s - counter: 05 r6 ]) v6 u ?9 O
- }
7 ?# ~' a; |! K! h6 N0 U - },
% O* T; f! g6 A4 \5 D& r, X2 q# w - methods: {" x3 r/ i0 e ]! Q2 l; M5 b
- incrementHandler: function () {
, P& g+ G1 j8 X+ u$ V - this.counter += 1) M/ t% R- J; |- b
- this.$emit('increment')! ~& ]0 U5 [2 j8 m
- }
' U, C5 M2 A" i/ u$ X- v - },
$ a9 ]) v, A7 o. ~ - })
g- P. B( J5 r, K: [ - new Vue({/ `9 w9 [9 t" _* d0 W
- el: '#counter-event-example',
" N' u4 R. ~# S' [' y9 v. K - data: {4 w( E; ]2 u0 k7 l6 O% ]: @. c
- total: 0
) M, h. a6 ?0 l - },: f2 x% q! h# G0 l! ^. d' }
- methods: {
2 ]6 B9 X. p1 Q4 H6 C* ]& ? - incrementTotal: function () {
) d' R/ |6 O9 n6 B9 L" A - this.total += 1
; F& r$ w. y* g/ D: \) k0 Q. K - }- P, f" f" E, h7 p/ _* N, f( _) F
- }- Y. G6 q4 m& f( \2 q1 V' ~; X
- })" @( P5 r; d, D9 u: f, `2 u
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
& |1 h# k+ ]/ {6 K: w: n Z - Vue.component('child', {: ?; ]; q+ \& ~9 ]+ v) J
- // 声明 props
# \3 S5 m* Y6 x3 t; D - props: ['message'],
$ c9 Y j" a" ~8 } - // 同样也可以在 vm 实例中像 "this.message" 这样使用
3 ^$ ]. [8 B9 w0 u, U$ \/ b - template: '<span>{{ message }}</span>'* P8 |8 q. x5 n9 e4 p1 v2 f
- })
6 @% w4 ]/ z+ ]# G* O - // 创建根实例; X' i) T- K0 y% l2 G S
- new Vue({# I: D1 J0 u. ]3 ^; f3 M4 y3 d
- el: '#app',4 t Q9 X3 I8 G+ F
- data:{' n; o3 t0 `1 }+ `9 ]
- message:"hello",% l1 E3 H1 a/ l( @; [) l+ v, J
- }# c/ @: [. s5 ^
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
! s5 Z3 T2 b s. c$ |2 g - incrementHandler: function (v) {3 b$ j5 I( P; q; y9 M
- if(v==1){
, q0 h! s4 H! W, A - this.counter -= 1
' q/ v: J# ?, g6 f0 ?+ T- F6 n - this.$emit('increment',[1])
0 i6 Q( _7 ^, B; r/ |- @ - }else{
3 }6 Q) m( Y' O: W" d1 U: t) l - this.counter += 1
) p% K7 { x8 X$ @$ n - this.$emit('increment',[2])
) o2 W: H# E+ v Q% F* z - }" y+ n3 m$ L0 J6 P J1 D }
- }
) p6 c* y: p# E1 h" ? {$ b2 _ - }
复制代码 & J' A/ V; U- z
8 }3 o) F6 U: K+ M# G+ e
|