|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
6 _- O! Q e0 t- <div id="app">, |5 T2 W3 |6 B2 ]
- <runoob></runoob>4 K" Z# K. E$ t9 `, X/ T
- </div>7 ]( O, F, x) n, p0 `: H
- |# l& A# B/ z% v" w
- <script>
4 `7 z% ~2 p! a# S - // 注册& Y5 A, l. }/ ?: ^2 x: i
- Vue.component('runoob', {% d, }3 R, |9 u4 W
- template: '<h1>自定义组件!</h1>'
' q* P; O! H9 R1 [0 P - })
/ E/ s- v7 x1 s" b2 g0 ` - // 创建根实例
* o% U9 N& e' F" G% } - new Vue({6 l0 T7 c9 h) [
- el: '#app'" T; z1 t, a! _2 J9 h" s
- }): M+ l8 H' @7 R8 R& I8 J
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: , Z% L) e# I. A1 d$ o/ A* o( ?
- <div id="app">& t' g# l, ~! d# ]; C9 N1 z
- <runoob></runoob>
7 \- C# _6 R- e$ I5 ?2 a - </div>& [& A7 t/ Y. P
- 7 N* V, W4 u. {1 Z2 j
- <script>3 C' s9 H2 H7 e p, G
- var Child = {. G! y3 w9 P6 S( Y! e5 _ S
- template: '<h1>自定义组件!</h1>'# A% \! g+ q, M! R4 V
- }9 Y' u- @1 |5 ^( l
- ) c6 H2 W9 M: r" ?5 f0 ?& {
- // 创建根实例/ O& @4 r# }% \5 j8 d- t5 s* W
- new Vue({7 d4 k: v* y: V( T; Z; S; ?7 D
- el: '#app',
+ c1 N: V3 U( T$ ^+ a - components: {
{' J5 }/ n+ N9 ^" v3 ?" _2 k - // <runoob> 将只在父模板可用& `6 C- F$ p& ~$ v( [" ^2 p
- 'runoob': Child) i: Z4 [* V2 j# e
- }
0 K6 B5 P/ I$ z1 Q! K - })4 A( _. k1 s* W( ~7 p
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例2 Z0 m. ~* M) ~; [" ~
- <div id="app">0 K$ e9 z" S9 s: M7 {
- <child message="hello!"></child>7 T! i5 Z, w8 M7 P) |3 h: s
- </div>* w0 { h6 {& S* \0 ^
-
( z, \$ W4 A8 ~: X4 c- a8 p j# L( m - <script>& r3 ^* R. j7 Y5 h
- // 注册
6 g4 f' }, L: @7 u - Vue.component('child', {
6 d3 h$ h( H5 }. A' [& d - // 声明 props
8 h6 w3 V7 t! R( m- x' ]5 h - props: ['message'],/ F' G: ~( ]) B; m- ] y4 B, P
- // 同样也可以在 vm 实例中像 "this.message" 这样使用6 K) c6 _: }* {9 t
- template: '<span>{{ message }}</span>'
, f8 H7 y; A( i - })
3 Q- T1 ~9 c& I d - // 创建根实例2 }: P! {4 G, q9 h( u
- new Vue({6 @6 h) B/ h6 f: K" S# `
- el: '#app'
) V( `7 F0 B# B* [4 c) D - })
+ c% G( v2 N5 c9 Z& ` c& P - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
# R: x9 x) Q; E4 A7 P6 U, z/ I- [- <div id="app">& a% W7 I1 R- v( u
- <div>3 b; Q# x/ J$ _3 N* }
- <input v-model="parentMsg">
. l! G/ k; _: O# Z( e - <br>
2 O2 }! l2 N( f9 v1 R" C; @3 N - <child v-bind:message="parentMsg"></child>; V5 k# h1 Q% _% k2 t4 a% \. D- P
- </div>+ T" y2 ?5 r# [! S# @4 O" |
- </div>
3 a/ ?8 o$ x6 _ -
- R) ^- R7 l8 l' R1 H$ p$ d - <script>
9 {, h. d* y# Y8 p1 S0 C# I$ u9 ~ - // 注册
4 n& C" D0 [7 v8 s4 [) j5 x - Vue.component('child', {
6 {$ T, b5 x; L& i- D - // 声明 props! |7 O+ ^: ^% a9 C9 w
- props: ['message'],& Y; K- s: c2 n$ o
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
; o: Z3 F( v* \: ~- `0 T! C - template: '<span>{{ message }}</span>'
* v& `/ s; T( O6 J7 n7 I - })% m! [0 e& t9 j3 [+ m; [; _3 C
- // 创建根实例( W2 }# c6 t' b+ D9 Z
- new Vue({
' t8 _4 ~* f& p* D; U1 _ - el: '#app',% w, v9 N1 { g4 ?
- data: {7 G0 s _7 V1 H% S
- parentMsg: '父组件内容'
4 u( Z2 e" Y& e6 W/ F8 ^5 X/ s - }
8 ]* h* d" @5 J* m/ r& o - })" a2 u0 g/ Q! A% H' d
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
J( S( |5 G) a% g+ u( b: i3 g- <div id="app">
/ H2 q7 ^! `9 f) R+ f9 ~- Z - <ol>2 K$ y: {4 z u6 H
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>. D) F$ J; f/ I/ G* h' \2 z) N( A2 p
- </ol>0 M" x+ k4 n+ K, v! t" ?
- </div>
% l' d$ ~0 y( Y6 X, }9 X8 L - 1 \' Y& M# S0 Y- H$ S
- <script>
' u4 N( G# t. |0 S+ }. j - Vue.component('todo-item', {4 T: h* @" G# A5 b9 f5 h
- props: ['todo'],
4 F* r8 I ~3 I( z' r- }' }( [ - template: '<li>{{ todo.text }}</li>'
/ J- q( x$ d8 ~5 v9 `) w2 \ - })7 O* g( {- }" S2 w3 ?
- new Vue({
( k U# p3 s, A* J- K - el: '#app',! e# s0 x! |, C: X
- data: {
9 _* \4 o, `7 m- ]) m' g" ^+ g - sites: [7 ?' s v! U6 w$ ?2 J3 }* x
- { text: 'Runoob' },
, s0 ^/ [) H' N9 B2 m+ w" X - { text: 'Google' },8 H; {( e( ~7 `+ w% | `; B. m, s
- { text: 'Taobao' }, B' ?2 k1 v" M& B* y: r
- ], L. X: f7 o8 A" b$ |
- }
5 ~. T/ L# A" ` - })( X- E, O! r, d* i$ u, E5 J
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
; G* _) i7 N" |1 V - props: {# d. L' S$ c$ j8 p4 E
- // 基础类型检测 (`null` 意思是任何类型都可以)6 [. I; j) _ k: H7 b5 g3 a) q4 g
- propA: Number,$ `! {& P0 _. m: A$ n' u
- // 多种类型* c9 M+ h; m3 @) o9 ]
- propB: [String, Number],
6 w5 X+ _( u1 h4 V2 @ - // 必传且是字符串
( e% M7 e% b6 s3 A' v( ~" k - propC: {
4 ^& E; Z" L: i: G1 U) n - type: String,$ W. r+ @8 c+ a
- required: true9 u3 ~7 q I- o5 J1 J
- },
. x' S4 [! u) S# j - // 数字,有默认值
* _5 t5 g, t$ l" C* b7 U" n) a - propD: {
* _* c% R/ t' K - type: Number,* z( d! H) t) I9 A
- default: 100* c. s* x5 ?' n( c- }
- },
/ a) A" v) k" N8 _# i ? - // 数组/对象的默认值应当由一个工厂函数返回
+ o! Y8 h, A" O2 |2 g4 @- J - propE: {
' ~# g9 `4 }- Q: K t- n; p - type: Object,! e6 l9 U9 V2 g9 z' g5 D
- default: function () {
* P" V6 A* L, {- ~% O$ d# R' s - return { message: 'hello' }4 s; F3 t6 M8 c# S" X
- }" D) v2 B& E- H7 R) J! {
- },
2 E1 w3 p) ^0 g& w/ l( ~ - // 自定义验证函数
2 g5 @8 {, ]0 a% z# `1 K! C" I! P - propF: {
! ^# R; j7 t. ] - validator: function (value) {; {& H8 M6 x$ c2 {
- return value > 10
0 {" T6 l2 P. d - }7 U( a3 o' R c( W; y- C) ~
- }* r* v% i: _" q6 p" j1 L
- }
: L1 ~0 c5 c9 c+ W - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array3 |1 q5 i5 j4 s% k: J6 J
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
% N& d5 f" K% P
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
7 i. Z/ p+ J. W- <div id="app"># t% ]7 O5 L- }
- <div id="counter-event-example">: l& l: `+ D4 c4 p/ ~5 ?$ d
- <p>{{ total }}</p>
- E7 E' E& l9 ~$ ?2 q - <button-counter v-on:increment="incrementTotal"></button-counter>' {+ W6 ?6 Y4 D* |6 k( ~5 Z6 d
- <button-counter v-on:increment="incrementTotal"></button-counter>( a2 m8 y+ n/ F
- </div>; A+ [* D o$ b9 h# w& B! R
- </div>
* k( Z6 c. Q ?+ e/ m9 ? -
! q! Y6 q4 w1 i) [6 `6 v - <script>2 t, x' B. R! z+ v, ]5 t
- Vue.component('button-counter', {
# s* d# \. M( K/ S/ C - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',# d! B4 {3 a) Y) v' c1 O
- data: function () {
% F5 E/ ~: E% D- x6 M# k - return {
% Q+ M5 Q3 h! S+ ? - counter: 0
" N* X. j: F1 p& N - }
5 F& w( c! }) m1 S$ e, ~; ` - },
1 k# m; N+ T4 |& | - methods: {
$ y) H$ \: b0 ^, z; ~ - incrementHandler: function () {
# q( h! D/ ?) `: j. @ - this.counter += 1
& g0 l# [$ ~, D% @/ K - this.$emit('increment')
8 w2 M8 K% |/ P0 J - }* Z' M! K& K) K K0 a& _: y
- },: {# _1 @, U9 i1 ?* e: F
- })- ~- P; y6 y$ n
- new Vue({
$ W- b {" F+ G A x' P - el: '#counter-event-example',) x! a- D P7 S% [, X
- data: {
' e* { R! [4 V4 Y2 S; ], g - total: 09 m0 A( o' U2 t1 D6 }+ A8 N
- },
+ }, P# j5 l3 G4 t( a% f - methods: {
0 {1 X( n* z# e" ~ ~. s# o - incrementTotal: function () {! Z# S6 w2 j8 V6 p) x( R# H. O, e
- this.total += 1, W& ]" M0 V0 c' u2 y, i
- }8 m: r4 E c/ O( |' p0 D
- }
1 j+ A0 R7 d {' X4 J4 h0 x - })0 M+ e% @: t5 e( W
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册0 s2 v0 ?& t+ M0 }
- Vue.component('child', {
9 ]9 E f. R0 U' j- s1 Y - // 声明 props4 G3 v% `7 E* x+ h2 v: {; i- S
- props: ['message'],( k1 u: ?- P% R3 D
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
# y9 [* o& @3 q5 L - template: '<span>{{ message }}</span>'4 t# [, _4 T; S2 n9 S1 X
- })) P6 V' [; ]7 K
- // 创建根实例
* V2 o( d1 q& w* m - new Vue({/ k' s. D% N- \4 _
- el: '#app',
3 h1 g x. w0 ^9 n! _3 \% F: C6 P - data:{! n$ W) Q- c# z5 G6 l9 R9 [3 P
- message:"hello"," }5 n' m- ]1 N1 w; P' @. f& a
- }
7 |* O% M( X9 y# c" A; V - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
$ b4 g/ @7 l! }1 y$ `& F# u: ~ - incrementHandler: function (v) {
7 h6 K! P+ Q% u: ^0 L4 M( u - if(v==1){
, Y1 L/ R5 p* y; o7 F$ J - this.counter -= 1- Y+ E+ y% @9 H+ c6 G8 M2 s
- this.$emit('increment',[1]) d8 E- j' D1 L3 ]2 W8 X- m
- }else{& r5 X) h [+ B- I2 J/ R; _
- this.counter += 1
+ k" ~* y$ l1 K8 }/ u+ a+ \9 V - this.$emit('increment',[2])2 o y+ K9 P# N9 Y( Z; m
- }; ]5 H; }8 Y9 e: [2 d: _
- }
# J* M- f& P4 e/ ] T: Y, W - }
复制代码 ' j5 z) O& X$ [, K3 `, `/ k
+ m" B! V5 Y# G; i; S: [# Y
|