|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
& N0 T9 ^: j+ {) J! j" _- <div id="app">
1 r3 Q' C( I, U' }! F; ~4 w; ? - <runoob></runoob>
4 q+ z, s0 S0 K- d1 I( l3 [1 ` - </div>' T+ N* `% h" H# `
-
1 S1 q: N! _& i! i - <script>! w( m7 I/ P) a: h" m+ ~0 \: @% R& @. T5 [
- // 注册6 F3 H' w7 R! y' W/ s2 u
- Vue.component('runoob', {; X, m* g3 T* N6 x
- template: '<h1>自定义组件!</h1>'
0 |' Q0 z& O% B' {$ z" ^0 ]6 o6 X - })
8 n/ m0 B+ q- N2 R - // 创建根实例- b) c! l* L/ I7 w
- new Vue({! _( Y2 E5 i5 \6 W q8 C. ]" F
- el: '#app' z! N$ l; K* ]. d, n( V6 |0 V
- })
: O- ^5 v8 w8 h" ?" w - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
* }. _% T& \; G4 n; U9 h$ {- <div id="app">. k0 N+ {3 n3 D, d) p5 ^
- <runoob></runoob>0 ]; r w3 T- B( l* w1 d/ s! m
- </div>9 g w" \/ m e9 a2 D
- ! V- T/ A/ K4 o7 J* ?
- <script>; T! g4 I- W- U) w7 B8 C; j2 Z) Q
- var Child = {
; q0 u! A& m' z% S - template: '<h1>自定义组件!</h1>'
5 ^' D/ Z% G9 Z5 R U0 _ - }
* t9 q" X& O$ O0 V( Q7 c/ M0 T - " Z6 y2 x. ` V4 K8 z1 Z0 }! @
- // 创建根实例+ G. T5 w/ S; G& u* i
- new Vue({4 K; o$ d! I7 `4 }
- el: '#app',! M- d# |9 c8 s( Z: t
- components: {6 i: I. ]6 F# S D" Q. S. D6 V) [
- // <runoob> 将只在父模板可用# K6 [* m1 f: |7 `; P' I+ z
- 'runoob': Child
2 X/ M; W2 o' L' J" u) E5 }- e - }' ^2 @" U# G7 s7 _8 c
- })
2 t( v6 |+ o& Q* W5 x4 J - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例5 x' s2 i( a6 M$ L
- <div id="app">1 A' G, c1 l6 y% I3 o
- <child message="hello!"></child>
2 {: F5 O; H7 H( H6 P. r - </div>
, {/ Z1 _5 P! n& q' Y4 P" C# F - 7 L+ p1 A V9 J5 Z: z
- <script>
$ N! ~1 P+ J" Z! r - // 注册; h. T! x( S) H. z$ u. G( {# i
- Vue.component('child', {
5 U9 A# J' a7 W, Z( P6 q - // 声明 props! I& T3 U$ A" Q# ~0 d
- props: ['message'],
( X# A1 K! m$ l; J- F* e/ b - // 同样也可以在 vm 实例中像 "this.message" 这样使用, t% r9 S! P" h# B1 Y+ z
- template: '<span>{{ message }}</span>'2 v* v9 g0 R, l& {, }4 }
- })
" i* f7 I- e; h Z8 e3 C - // 创建根实例
6 `% I* }+ {1 P: w - new Vue({
" P/ d% k1 V2 i' H - el: '#app'/ \" g( e6 n6 G6 q1 s. n
- })4 ]. A4 v& m! c$ G8 S
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例" H6 \, F, X* n j$ y: U$ t
- <div id="app">
+ g, B+ x+ E; ? - <div>
% F7 p1 l. K4 p5 l* y - <input v-model="parentMsg">8 r/ Q+ A$ A. |$ D! I8 w w/ Z
- <br>. H8 X# l* N2 i
- <child v-bind:message="parentMsg"></child>
* y$ o5 `; D1 y+ W W - </div>
4 x) w; j. u: M0 C5 i6 G' U - </div>1 B3 }# Z0 R3 G8 N4 |1 E' I
-
" I9 t' V& H# q" E - <script>
- C2 t9 q4 Q/ b% Z' p - // 注册3 t3 ^/ R+ C0 Z
- Vue.component('child', {
; [, r% r& {* I1 E/ V - // 声明 props
: d4 X; V/ W6 a6 a. i" v) e - props: ['message'],
6 \. x" ]! H1 k7 N& ^, d- U U - // 同样也可以在 vm 实例中像 "this.message" 这样使用
, x: e S4 J2 |6 H* k* X" P* M9 y - template: '<span>{{ message }}</span>'
9 Z( \1 i, ^! `0 V7 [; F1 {! d2 n - }); R9 F C6 u9 Q' x7 F
- // 创建根实例* k- H: s* }+ Z& M P
- new Vue({1 q2 w3 G$ n3 M$ Q" w$ A3 {8 g
- el: '#app',
; C! Y; M1 Z( D. s8 C. F - data: {
% p% c: [7 v- H" F6 F - parentMsg: '父组件内容'- M+ Z8 b& _( d0 `3 R( V; ]
- }
1 v; W: _! X1 V* N - })4 X$ z9 F- U5 v
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
( T7 f0 ]6 q3 H/ e" D- <div id="app">& e' f, ~( g& |- t7 U8 n" b* V
- <ol>, u+ d, B+ [5 f7 X, j
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>7 Y3 `! s5 Q& P
- </ol>) m6 Z. t F6 h4 X
- </div>
# y- l& B( V8 g) `" U - ( `- w: ~4 d( q. Y- I) Q1 V9 |
- <script>
' @7 U `/ H0 U \- J4 w3 b - Vue.component('todo-item', {
! X4 ~4 ?1 [, t% ] - props: ['todo'],3 w$ }, U& e) ^* O1 M: P8 h( U
- template: '<li>{{ todo.text }}</li>'
( s9 b/ J5 ~+ G - })! [5 N p- P# _5 O0 U
- new Vue({
) H2 V+ i: D8 ]# b - el: '#app',
3 Z5 B4 z k' \ - data: {
% b9 t8 k' h+ v, [* g. v2 q( n - sites: [3 u6 v3 H( s8 b$ i8 q7 |4 q
- { text: 'Runoob' },; a2 a* ]% L1 `
- { text: 'Google' },
' p' a5 K( Y! {& j6 k" u) R, j3 b - { text: 'Taobao' }
& _5 r2 v p i: s' l - ]
4 P B( T: {8 k' V2 B - }
: [$ V& [8 k7 I) |, c6 u9 K - })8 G: J" `& f' D8 s' N7 |* h1 i- Z
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
8 }6 |% W$ J/ G1 g- G - props: {
& u3 K* y* f& P* q& |9 i - // 基础类型检测 (`null` 意思是任何类型都可以)/ T0 q' {; n# j% l; I
- propA: Number,
# J2 E! Z: s' K: {% F - // 多种类型( q' k% Y' `0 X
- propB: [String, Number],
3 j4 U9 _4 x, f( A& M4 P% W: u5 Y - // 必传且是字符串) z% U7 |2 E# M0 h1 s
- propC: {
* L Q; g+ |- F$ j& ` | - type: String,' y& `! x3 z) R' |
- required: true
3 \ z$ G5 g; `" c9 R - },& p3 ]. w) A. H1 ]; q
- // 数字,有默认值
+ p5 r& K9 S9 O* F - propD: {
/ |; Q0 x, P0 X5 u8 x. O- K. W - type: Number,) L9 M4 y7 o! B W
- default: 100* G' D% x& Z& ^8 m, l! }
- },
# p3 B" \7 y4 Q: r; t% ^ - // 数组/对象的默认值应当由一个工厂函数返回3 Q/ g$ q3 |' ^7 L( j2 L- l
- propE: {2 m' B S6 J' ^
- type: Object,. {1 F0 w3 U5 ]9 G$ \& N% K
- default: function () {& F) d! P% a( N# j J/ z7 g4 m0 L8 X
- return { message: 'hello' }
! r! ^4 S' Q+ j/ X: J! _ - } k" v- e; c5 h/ p( b+ G J2 m
- },1 f( D( Q8 p# G( r6 R6 Y6 v8 V- Q
- // 自定义验证函数* t3 d: A5 P) e. {
- propF: {3 y' k, s( k; n; H5 F5 t
- validator: function (value) {, i3 p5 n7 @; p% I
- return value > 10
* e9 k Y4 a1 i. i: k - }
K6 r+ g# V- K: } k. X - }
G* Z7 W& m+ b- M! Q1 E5 N) Y8 P - }8 L2 ?+ t: e2 u% J' R
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
" g- b1 R- x) r3 Y9 ?3 Z1 U
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件1 v0 J3 z1 s; h0 D8 X
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例+ V4 [3 s; O1 S) h+ R& r% I: f7 H
- <div id="app">" M: I& w( M. P7 m
- <div id="counter-event-example">
4 U7 d5 n6 O' \6 F, T( `, L* q - <p>{{ total }}</p>% J+ a: h" j( j/ D! j! d- a; E
- <button-counter v-on:increment="incrementTotal"></button-counter>
) v o0 ?: l$ T, a2 x+ x( d- X - <button-counter v-on:increment="incrementTotal"></button-counter>
$ h! s# d1 `- K - </div>: @4 @6 \ D5 X9 W) N) x7 K5 h
- </div>1 v% u8 h/ y, \5 x: }2 F# J# d" _, l
-
7 o8 e \, H2 T+ _- L7 T* Y# _* g- _ - <script>
2 L9 M% O$ Y- ?: O5 J7 x - Vue.component('button-counter', {
n* f \8 c3 W$ d/ g+ x' _ - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
! k) k% U- y9 I Z - data: function () {
0 ]2 a: h# X1 q" \+ | - return {
7 s6 e2 L; a: U4 {/ ^* U& F& P - counter: 0! S7 I% l: X& i) j5 R3 E7 H
- }! I( O% w* y" u' i3 p; D8 Z) L
- },
& G2 S. e. c9 c - methods: {
0 O) E" R5 Q% ~: w! N3 t - incrementHandler: function () {% C" u3 t! A2 T8 S* ]* ~- N8 m
- this.counter += 1
+ [( b4 J. u( z. R' I7 |$ \& R - this.$emit('increment')2 o1 {7 Q) E# V0 ^+ O. }4 U: j
- }9 n' H" D' ~0 O" M7 y; L! y
- },9 X+ z. |4 p- ^: J" i1 i
- })
2 A5 K0 A% B9 p - new Vue({6 V7 D+ { n" D& h6 R
- el: '#counter-event-example',
3 d/ u- R* b; D - data: {
, q2 D* g: N0 c/ W6 c - total: 0
" F1 d c( j" Z. d* N' B f - },
7 E) F% f8 D/ ~7 n - methods: {
" e/ n% k0 @6 f3 |7 s* D - incrementTotal: function () {
0 r7 z7 }# T; T - this.total += 1
! n! Z z1 F) b1 ^7 Z6 s - }* V7 I0 B7 `0 C2 ]4 E
- }$ l' J% e, @* D" ?
- })' e9 `6 M# b( ]5 I( @/ f4 a9 F
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册8 y9 H; i( @( @4 ]2 G: _
- Vue.component('child', {/ q% j3 R: h" V: {2 X0 ^9 b/ X
- // 声明 props4 }( p1 H) x i6 p" H
- props: ['message'],) R3 S# f; A2 B5 E. Y4 r P& N
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
; \# H: @3 b2 l; G% ~ - template: '<span>{{ message }}</span>'
. Q: y& I# v9 \' j- \# N" J - })4 ^9 G, N" j, o2 x2 G
- // 创建根实例
j$ q c: E- X8 J. s - new Vue({
b' _! Q/ q' ^) z5 ? - el: '#app',
+ r e4 F2 X* O2 n: M - data:{
9 F; n& M9 ^6 f2 z9 G+ K0 A! w - message:"hello",1 {6 o& H( g% \# E0 `& l8 ?4 T1 j9 V- y# _
- }/ P: g' m) p9 V7 e0 H7 e
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
9 Q$ F: W' T* O) W7 y7 m# X5 T - incrementHandler: function (v) {/ c# b3 f' I6 u
- if(v==1){
9 R$ X. F4 S! y7 K! c - this.counter -= 1
1 D; q9 X5 L" B3 m' Z1 L: A: ? - this.$emit('increment',[1])
7 _# v7 h/ g* O3 a% F; a+ x/ @* M - }else{- S( U4 ?7 F, ~ [
- this.counter += 12 g+ l" L4 M9 B" V. f
- this.$emit('increment',[2])
+ D# Z3 w$ N( Z - }1 l$ t6 Q. N" o+ `5 f- }
- }
- ?* y# R( B+ B8 } - }
复制代码 ) u- \5 r; p7 E v# k" c
4 a' ]" {. [5 Q* o |