组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
# l) |- s$ R @, e" z! W- <div id="app">- P& Z0 E! j- e, |1 t! w4 \7 A7 {
- <runoob></runoob>8 U* i0 t% o6 {; h0 P6 I4 s+ Y# Z
- </div>
}1 A+ K4 g3 ?3 b9 H7 _! b -
8 X2 U) v2 Z# `$ {4 e - <script># p% p5 L1 u1 B
- // 注册
' [) M' w7 g) R7 P) `; ~* s - Vue.component('runoob', {
3 U! e) G- f I# f; s" a - template: '<h1>自定义组件!</h1>'
& b. i0 T* e3 W, B9 W* J- o } - })
5 Q0 U' [# Z) Q+ G7 _ - // 创建根实例: [7 {- f0 o/ j# H' H" U
- new Vue({
+ \% w; c7 r# Q- \, { - el: '#app'
1 S. y6 \1 ]7 B( N6 u; w - })7 ]) S+ q$ ~' W- D/ m* ^
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
8 [* U5 s- t7 l( Y- <div id="app">
% m; I0 h& h+ m$ I, ? - <runoob></runoob>7 E2 r- f: G. A4 y
- </div>
6 _6 e8 n1 S7 a6 a+ ?+ L5 W -
) Y4 K, n- j4 d4 a. C, `. z - <script>2 P9 q3 n5 j& B5 X ^
- var Child = {- J$ c$ T9 B( X$ |; ^/ q
- template: '<h1>自定义组件!</h1>'
: u: y" ?1 v+ u! h6 h - }
! A. l: }. E4 u: S# M6 H -
+ d9 y; L$ Z+ C# ` - // 创建根实例
7 ^. h) c- z( c+ }, I# A3 M - new Vue({
. C9 a( k0 w+ Q0 w& m - el: '#app',
# T* t) S9 ?0 i* ~$ z& t - components: {
! U3 X; R! p# k5 d9 P- j - // <runoob> 将只在父模板可用
m! F7 @3 s! o0 o - 'runoob': Child
$ H8 W* @) [: A: }4 g$ a% y& t. i1 D- L - }
2 i- |& ~- s7 \; g) r - })
/ m; ^# d3 b; k% y3 _- S% |) n G - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例- |# \8 i! x! p) w
- <div id="app">
% y+ H& L5 O6 l# B$ z+ G - <child message="hello!"></child>
+ R2 K4 o. _5 } - </div>7 w+ R, P( L% [ l
- ' ]; u! M; @6 _, Y" }; ^* H
- <script>
( o$ v2 \ `: t M2 ]- C) V - // 注册% ?: M; J: z \. m( L
- Vue.component('child', {6 C& ^! [8 `: B7 M5 P+ x" S
- // 声明 props# x8 n% L r: j( C5 [
- props: ['message'],: l3 \4 z; M$ h& `3 E4 z
- // 同样也可以在 vm 实例中像 "this.message" 这样使用7 F' D9 X2 O& J5 `
- template: '<span>{{ message }}</span>' s7 P! \: A+ \7 R! V
- })9 `; W( n0 f1 H$ w" N& }: n
- // 创建根实例
* C1 p$ X' w" O* l% P, M - new Vue({
0 a5 o+ s9 k3 k* E& o0 D- R - el: '#app'
, F* d* }7 e% ?0 d y - }) Q$ N# E2 A1 O( b% J' W3 H- l
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
2 } N- i. h2 P+ J' ?8 u# k( S0 p0 ?- <div id="app">- H# x9 _; h' K" o' Y+ x. {
- <div>% P' N! ^/ v' ]! C+ H" B
- <input v-model="parentMsg">( V9 z4 L! R' `0 |; d+ ]. U
- <br>
+ @/ p6 t( ^+ Z% C' ^8 e7 q/ Q - <child v-bind:message="parentMsg"></child>
& r+ y- O0 P) ?* P - </div>2 s, A* D8 f4 b3 `2 m8 m
- </div>& x9 i. a. w* ]4 P0 O% O* p
-
8 _% U7 V( r) p4 g% k' u - <script>
. ?2 ~* E+ J( ?/ _: @ g7 o - // 注册
6 i3 h; @& U# `: j8 c* _ - Vue.component('child', { w; R0 T' c( B7 A
- // 声明 props
1 ^2 _% j' u$ u" V: S - props: ['message'],
, J0 J5 {: x" s - // 同样也可以在 vm 实例中像 "this.message" 这样使用
! r# Y$ G ^7 @) z9 e6 n - template: '<span>{{ message }}</span>'4 Y4 b4 ~8 F$ g
- })0 @+ _, O$ I, V) E. U: v+ ~: L
- // 创建根实例
6 T" h; t1 [7 B& u7 u; y - new Vue({& e' g% q3 W! l% N. ^
- el: '#app',( @3 b1 d5 M0 f) v; b% d
- data: {
9 m8 P! V: w1 @+ M+ z, z" [" H - parentMsg: '父组件内容'+ A: m2 F2 m9 |8 W# T
- }5 L* v# x; @' i- _; J
- })/ n4 j, H5 F3 O2 A% O5 S/ u
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例) O1 p4 ^# v8 ]! k$ q" e: x. T
- <div id="app">
! {! `+ v: q2 L6 j* j& [ - <ol>
) _( f* K* W t$ n - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
8 b2 R" ]3 Y0 z$ Y - </ol>
! t# F: B/ V% ~$ h - </div># z9 X2 A; _9 x+ N
-
& j" o( h+ ^+ r* u - <script>; z1 D2 h- m$ j6 J6 U7 Z) k
- Vue.component('todo-item', {7 S8 {" ~$ t6 j% t% W/ O' V
- props: ['todo'],$ T/ w5 p- Y# X# M" w
- template: '<li>{{ todo.text }}</li>'6 O; a. }. l$ B9 B! J
- })6 u$ \! g5 G. k; u
- new Vue({3 G. H$ g& x0 A
- el: '#app',
/ B+ v" E p4 {! Q$ j3 x! J. L5 H - data: {! E) a0 N, j. V# D: e
- sites: [
0 H& N& S( @ a - { text: 'Runoob' },+ h& d2 a3 T( y
- { text: 'Google' },
. @3 r' v( q- n5 u# q7 U$ w+ _ - { text: 'Taobao' }
2 K/ m( k' u) ?8 H! b* } - ]
: i8 `, F, U4 E - }
/ W( d% W b3 q8 A8 n" p - })
* t7 j m, t& Q. E3 r% E3 T6 M* B1 P" v- b - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {8 Z, q3 c+ X! I, ~
- props: {1 u$ |) h: { C8 q/ ~3 {3 E# r
- // 基础类型检测 (`null` 意思是任何类型都可以)" q/ H- { d: [- p+ K* N
- propA: Number,
: O+ W) r7 s# P - // 多种类型
6 F; C( U0 i8 _$ L5 V$ W$ |- c' g - propB: [String, Number],
, q) e# L5 r/ J4 Q - // 必传且是字符串( U. Y5 { d- A9 K2 Z9 f+ g
- propC: {
) u% ]1 ]3 q5 }9 T - type: String,* [7 j" u/ v& \- n0 `& i- y
- required: true
. P7 v1 K6 @% D/ ~1 R - }, Q8 N- E: O9 a9 U, N/ }4 Z9 l
- // 数字,有默认值
* f6 m3 g: m7 \ - propD: {, V/ k1 V" {. g/ S9 Q" Z) r
- type: Number,
/ {) c4 y: `* b) p - default: 100$ v, Y- |9 U2 i
- },% \3 z( d9 R y( |# i" |0 f% f
- // 数组/对象的默认值应当由一个工厂函数返回
1 h( M/ U) B. v* o - propE: {
* J2 T! P6 V0 |- o. Y - type: Object,5 s# f& Q& ?: I9 b: L7 `4 J, e
- default: function () {: }; G7 l! ~% d4 g3 s/ P
- return { message: 'hello' }
4 }' U! K4 z) L - }
% c* C2 K# F' b0 S: } - },9 V0 W( v! b( L
- // 自定义验证函数+ J! S3 z1 R/ S
- propF: {# R6 d3 F6 W, o. \( G# f
- validator: function (value) {
" b5 H: |( ?" M7 i; ]. Y - return value > 10
4 B; w7 g! ?1 c: x& Y - }
# G; W: L# B [+ @+ o, U' s - }* s) k6 {& K# X; m
- }6 F2 ]7 C1 i Y* N
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array) J8 M0 `3 U! G! ~# ]) s$ N; b% p
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件$ O, ~" O* m9 z2 `' D7 |
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例) p( P6 y; ~/ @% s" q! z! c: }( J
- <div id="app">
# c" h$ G% i/ | - <div id="counter-event-example">
5 S h% ]9 @( u- y4 @: [ - <p>{{ total }}</p>- Z: G; l, e, r, P$ }
- <button-counter v-on:increment="incrementTotal"></button-counter>% h: J' r; d% J! @
- <button-counter v-on:increment="incrementTotal"></button-counter>1 i6 B) l; b0 _+ G8 [. x$ t
- </div>
1 N$ G3 a- r) l1 q - </div>9 m( `# Z2 H4 L: I. G8 Q; l
- * l9 D& `4 Q4 d8 ?% @3 x
- <script>( C8 R. y3 N# D* v3 @& e
- Vue.component('button-counter', {' V7 f9 y% C% Z7 D# r
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
+ V$ O8 C8 W) m$ I - data: function () {1 u: g7 M9 X# Z! F2 [, y3 z
- return {
3 H' q j4 A6 I4 R* z - counter: 05 P5 ]8 `/ {+ `# q$ \
- }
4 f3 m6 @8 w6 X2 V+ z, [/ V; T - },' q0 a& G4 G' r. T' c
- methods: {
6 l2 W6 X/ O9 `5 M2 ? v3 u - incrementHandler: function () {
G6 {2 N. W S3 {+ K! ]0 ?& X - this.counter += 1' \4 d& m$ n1 g9 I9 y' F
- this.$emit('increment')
8 m( Q% s, Q4 J: }( ?; Z2 X, a - }( p% ]+ A/ W7 o8 I) z
- },
) {% g" c. K8 |, o - }); O o! ^) p+ q
- new Vue({
5 s% l! R* d1 J7 V; h5 j9 ~+ o - el: '#counter-event-example',2 k& H. ?4 p5 S0 e) N* I4 B
- data: {+ v% N* }1 i: A% a
- total: 0% c' w' L$ `& X9 Q0 {, z4 v& E7 G! L
- },) O; o/ t. Q" ]( E v7 S$ U4 u
- methods: {
- H5 t# M$ D$ Y$ W4 N4 A - incrementTotal: function () {
' m, r# v# {' S+ o: V - this.total += 1/ ?- U5 Y# N' W6 l
- }
" U! |2 p% `( ] m8 C& ~- a u - }
" f7 O0 O3 [6 P; \ d - })
8 z7 O C" i" ^0 f# s - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
5 L; k) y' ?: ^# s4 p. n1 x - Vue.component('child', {
$ l% T: V- I7 q! u7 X* @; M+ H - // 声明 props+ T6 @5 X9 P6 c. f: N/ |% V
- props: ['message'],
( {& G2 w; o& _ j, V0 g2 ] - // 同样也可以在 vm 实例中像 "this.message" 这样使用
$ C; g9 N5 U8 ]& F* M5 ~ - template: '<span>{{ message }}</span>'
4 _3 P' ~/ c* M; I9 z6 H& P8 f - })
5 w" T/ g' [, L - // 创建根实例
" ^& r0 H3 e. @6 Q+ N3 Q( J4 @9 { - new Vue({
/ k' [: O4 D0 S+ J - el: '#app',
) C+ t2 v- Y* N$ e - data:{% b$ Z) m9 g. K
- message:"hello",
. E* }' V1 ~; T- ? U- ? - }
3 F# s n: N% p# c& H. ~6 ? - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {- b% n) @& B- s/ b; B
- incrementHandler: function (v) {
) Q7 ]" j) N' Q! ^ - if(v==1){
: _0 S. Y5 d; Y& F - this.counter -= 1
4 l( w4 `7 F# M. m$ }% l - this.$emit('increment',[1])
" l8 T* I4 e2 n; m4 G" O - }else{% f }* [. T/ p0 p$ d+ u
- this.counter += 1
5 I1 F S. B& ^7 l2 q7 w2 V - this.$emit('increment',[2])
2 t3 r4 h: \& `: v" Q& i - }
8 z0 U. z8 b# A7 S: w2 }! m0 ^ - }
7 X% K% ]' C! Y; k - }
复制代码
/ `) S: I" @1 b$ C- h! N5 l: B8 n; ?' |6 U, B
|