组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
# {. w$ l% S9 L4 W3 B& ]7 r3 B" T- <div id="app">
7 m' h( a! a% p7 c - <runoob></runoob>
0 w, a% z' ~- Y: ?6 n* m4 T - </div>
8 T! } e8 ^& b/ n" n -
+ F) z7 [- @: g% @) E" j, H: b$ u - <script>- o9 K7 g0 y/ A; M" M; }. \! b
- // 注册
4 e- k: W9 \# p( F1 k - Vue.component('runoob', {
; T/ \; G2 K, w( O% r. v% k - template: '<h1>自定义组件!</h1>'+ Z2 V, e4 }9 {0 ^! h2 @' s: J
- })* f: ]0 ?; c% g, e4 _ X: F
- // 创建根实例) C' O8 R4 j, X, i
- new Vue({
& E0 `4 e J; }* D - el: '#app'6 |5 I/ }" T2 D: U; u
- })& Q* ~6 J+ P3 s0 Z
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: . I4 M: g7 F* K1 Q1 I
- <div id="app">( `' t3 J' y/ t2 O, @( x/ ], R4 g4 J& n, e
- <runoob></runoob>( Q- A5 \/ ?3 x% L
- </div>7 M& S p4 ~ L
-
2 k/ X9 N j D' i% M - <script>
0 J ` A) ]/ \( s1 G: ^ - var Child = {& O4 x/ Q% y. s2 [% ?8 Y! P/ O c
- template: '<h1>自定义组件!</h1>'
; q6 c# }3 `, S- w* c8 U% J8 r+ k - }
2 D# x& r. `$ E0 K$ R0 f -
$ X2 N. q% Z( W! ^4 J8 H - // 创建根实例! D! {3 x1 b1 Y, U, C$ E) N5 M7 [' \5 k
- new Vue({
9 ?+ [4 q9 N! I u$ E% O. F - el: '#app',' H2 r, I# B* p) h1 W- K" G% d
- components: {1 g3 h# w1 _& h6 R0 H
- // <runoob> 将只在父模板可用
. b8 I4 j* n3 p$ k; S0 f$ Z - 'runoob': Child6 G% r2 d; x+ v) Q
- }3 p! H+ o9 J, o# C! j, D- W
- })6 u R m* o n% H
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例* v, R# _2 m9 ~3 z
- <div id="app">
1 q6 n1 ~! \$ ] - <child message="hello!"></child>
- P# j" B$ ^1 g5 l* F! Y - </div>( B7 V7 ^7 {. u2 @' x
- ; Z$ n' Y0 w, M; U) S) N- @
- <script>
. G' m }4 q( F, H7 a' v$ G, p* B9 w - // 注册
, E( V8 i2 q9 h$ M - Vue.component('child', {
3 b8 V' S' j- }& p+ C& H) A - // 声明 props
9 h+ E, ~; l G - props: ['message'],
8 {( g, G7 X' S4 r - // 同样也可以在 vm 实例中像 "this.message" 这样使用) p4 ^. K o/ b3 K* j$ u
- template: '<span>{{ message }}</span>'
0 Q! o2 r% O' z0 A( |' V1 [+ K1 w8 d - })8 ?; t7 L) D3 u$ Q A
- // 创建根实例( g$ r* ^5 \, X% b
- new Vue({
1 z" N4 e O6 _ - el: '#app'* ~" g) [/ y9 q
- })
! `% M. I4 S) j# E3 a; F( G - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
1 P6 H7 ~- R7 ?0 X' ]6 @- <div id="app">
3 X; {% Y" }6 k# [+ A u* @ - <div>
( j* W; j9 l) {9 F. Q0 ^ - <input v-model="parentMsg">! c0 T' C4 z; m \5 m8 s
- <br>* P& N3 s1 t% }/ N+ z) Q
- <child v-bind:message="parentMsg"></child>& Y$ p! j8 c. I% M$ g" L( v
- </div>
6 N: Z1 M0 c* m a- b - </div>
. j6 J: @- j8 v, q9 }, @# Q2 g -
% ^* p5 n* ?3 h: d+ J- k Z' Y) ] - <script>1 y$ t+ h6 P9 ?9 Q
- // 注册
, X, s0 P }1 x. h0 V6 G" I - Vue.component('child', {
0 O3 Q: g/ X0 G' y - // 声明 props2 B$ S9 b$ d' i, y B) c1 a$ [
- props: ['message'],
& k5 w3 i' W+ J8 B! t - // 同样也可以在 vm 实例中像 "this.message" 这样使用
0 {- f$ B- q1 F& T2 f0 m2 ] - template: '<span>{{ message }}</span>'" B4 l) v% y. V6 R6 B1 d: J# p
- })5 w. `# Y% B1 x- W/ c. c
- // 创建根实例5 }* f" ]1 l% x8 `- l6 B/ M# k
- new Vue({
6 r6 Y* g, o }- r8 d( b8 G, w6 D - el: '#app',
/ E) Q. {- r" Y ]" i5 w. D - data: {
: J \/ Q# D& d( h - parentMsg: '父组件内容'# ]( y v6 w0 ~
- }0 Y+ a5 J* O* s ?
- })2 Z" X9 [ ?4 }6 v! Q a& y' l
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
! W& S$ h( l, I+ q& I3 `- <div id="app">
3 {5 R; S1 Q( h N - <ol>
+ N+ r1 A2 V! G% \7 v - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>( b( q @' K$ M, ^/ T8 _; }
- </ol>; _ ~9 k: h o+ C
- </div>
8 L3 W, |1 ^" P -
* U) R9 U/ P( s; f3 y - <script>
1 S- H$ K+ a" u4 g. N% \ - Vue.component('todo-item', {
/ b8 |9 y' x6 |2 _, ~ - props: ['todo'],( |4 b( R1 g: j' Z$ A
- template: '<li>{{ todo.text }}</li>' `% t3 b+ o" y. c8 P: c
- })5 S# k* ?# r9 @: q: o
- new Vue({! E; @# h1 w( {4 l7 F4 U
- el: '#app',
% t: D3 F# y' |% @ - data: {& g! u( z' H+ k
- sites: [
! ~8 t b3 H) N, Y1 f - { text: 'Runoob' },$ Y3 v+ v5 T0 F& F, v$ p: z3 ^
- { text: 'Google' },
4 M2 U) _+ N: n E - { text: 'Taobao' }- W9 \8 S$ `7 c! z
- ] n- v, R2 d' n$ V
- }
1 ^) S2 o$ g+ a0 E7 P+ t" h0 o - })
. M5 Q1 O! h; w5 f4 _ - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {, e5 p* p" ?" x; L" T
- props: {4 R$ A$ C, [- R6 D4 c# C
- // 基础类型检测 (`null` 意思是任何类型都可以)
3 \: Q4 l$ ?9 ?1 L" O0 g0 _' k - propA: Number,5 h- }, m9 D0 P
- // 多种类型: ^: }2 g5 ^, d" c
- propB: [String, Number],8 E K+ M+ x$ _3 Q# d) t G2 V
- // 必传且是字符串+ b4 k+ y& c2 ]( `9 Z9 _8 Z9 N
- propC: {
0 A3 b: |8 ]1 E8 a3 | - type: String,8 R- c! J) q& [3 Y9 k' O+ q3 ~& D
- required: true: m6 \$ R4 m" A& B& A+ F z& m
- },
1 v- Z$ d: U$ |' A) q1 n, H - // 数字,有默认值: }7 i" F+ _' T; D4 L8 o
- propD: { n( ]# K. Q' ] w# E# E% H
- type: Number,- E% R1 Q. h" q3 J
- default: 100, i2 j4 j5 ^( o6 C0 X( m
- },# k0 K0 d' d2 ]5 G6 \) a
- // 数组/对象的默认值应当由一个工厂函数返回% q* d4 d3 q: y
- propE: {
9 J$ m$ e$ g9 r2 }2 {. S* u4 R- _# W - type: Object,
5 o# }7 x9 D' ` `# p; W2 X - default: function () {9 A5 T' m3 M0 y; H& b C9 ~7 Y$ k
- return { message: 'hello' }
0 p/ y) `' `/ o0 K M1 m# _" |9 f. f - }
. u8 L% ]0 V+ y: X! _) T6 K - },
# h* q! E0 C4 l+ Q - // 自定义验证函数, h4 P4 s, y9 C# I. h
- propF: {% C$ ~1 w" G: ]2 O6 L* |
- validator: function (value) {
# r' S6 l# s3 ? - return value > 10# R5 V; ?5 u) ~
- }
, t$ {* t- z" Z& d" L: ^ - }
4 x" w% ^- c. _; z5 G( ~, e - }& w: b' D- D3 L) [0 a
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
1 a/ C8 P' H5 Q# B
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件9 O* g; ~; O& M6 `
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
9 ?0 Q& N0 w9 U0 d6 {. a4 j* ~# m- <div id="app">/ w! {& X& _; {) G
- <div id="counter-event-example">
. F! P2 W, B! S( a( Q$ M* c+ \- A - <p>{{ total }}</p>7 O+ I+ V1 H' z3 T. R
- <button-counter v-on:increment="incrementTotal"></button-counter>/ ]' S, k# t* f) Z% q" Q _
- <button-counter v-on:increment="incrementTotal"></button-counter>
0 w0 G! y" C7 [( Q5 }* t - </div>& k( x/ n9 H* i$ }9 z' L
- </div>
/ k5 A" E2 ^# e - ' R: }0 e* \( ^
- <script>" t# U6 [, z: P9 A0 m
- Vue.component('button-counter', {
4 S, K, z1 C) W2 _6 T! c4 Y - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',, o8 ]% X+ h0 T1 }7 d
- data: function () {5 a+ `2 c9 z3 n- x
- return {
: J6 R9 E+ C' o; s0 e) K - counter: 0" F$ O4 P4 i) k) T
- }2 Q3 D: t) l* }4 v; G. `
- },
7 h7 v9 W% e/ Q# h - methods: {' F% E0 d- X0 \7 [; }( \) s6 f
- incrementHandler: function () {
6 v5 l6 G* c; z! x - this.counter += 1& ?7 z* b6 V0 G( u+ K; p
- this.$emit('increment')
+ W* r" l- U9 Z, v9 S8 h - }/ G, H w5 \# W7 R( }" E
- },1 @+ c5 E$ f+ M5 @* k) j
- })4 p1 t8 d9 @, O7 [) D5 A, W$ {
- new Vue({
\4 C1 m4 `) q/ \. X; l6 O - el: '#counter-event-example',
4 `: K: [% i% i. { - data: {
" y7 A! F/ V2 O0 S1 u. @+ v - total: 05 q. U. j- D! @( E
- },
# V# a0 e3 ?: E - methods: {
, o4 @% [3 v6 W - incrementTotal: function () {
# o1 I2 K; i' R F9 W; R& i - this.total += 1; i1 A# J/ e) B; B
- }
- w$ `" J/ U) E6 n - }
6 Z k7 K3 \+ N! l - })
# @. T1 ?! `0 G4 D, I - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
+ N, e7 X2 m4 c2 x. I1 @! ]7 s+ _ - Vue.component('child', {
2 U$ {9 {5 x7 V - // 声明 props: ~! h9 L" G. _8 |# W) G! T2 A
- props: ['message'],% n0 z8 b. r! y: J
- // 同样也可以在 vm 实例中像 "this.message" 这样使用5 D Y8 b, K+ f+ c
- template: '<span>{{ message }}</span>'
0 K$ i) m$ Z9 s+ P - })7 I+ r! b7 ^/ K% z
- // 创建根实例
2 ]) t8 b4 D0 Y+ J$ r - new Vue({: F( B2 F& f o( S) t) X- W
- el: '#app',
$ k/ k. ~* ~5 Q: @4 l - data:{
0 @+ |1 r7 }" T) Z4 A9 A - message:"hello",( S2 y8 V4 ]% G! p' c P
- }; S- h" Z* u" \- t9 M, u+ W4 q
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {4 ^" S9 p/ n. s9 i1 K/ G. _7 ?0 g% ~
- incrementHandler: function (v) {
4 _' p( `, Y( j4 b/ L: j - if(v==1){
8 K; k+ C' L) @ L7 ^5 { - this.counter -= 1& U0 T+ C/ B/ \2 t2 N
- this.$emit('increment',[1])* l; F$ B d4 s% m8 k! N
- }else{' \2 a! p6 y6 u& V$ }
- this.counter += 15 K% \: Q. @: X, @$ D, s. s0 t
- this.$emit('increment',[2])
& B4 {/ n- X, t - }3 l5 {! l8 [: z0 P: Q
- }- A6 p* p: }; K, Z9 S- j
- }
复制代码
0 X' t0 s! `% E8 o# }& A: r' ^& E n7 s/ X; U" O, `4 e
|