组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: 5 p4 C S% @# w3 D$ D$ K
- <div id="app">* {; b. {/ N& h% Q7 d& S
- <runoob></runoob># a, q8 h- h2 B! a0 Z
- </div>
# E+ {8 o) U' s( G - 9 D, k) }! `; p1 }- y
- <script>
" F9 w; t! {/ I- V - // 注册2 P! q& U; Z8 F8 n* l
- Vue.component('runoob', {
+ a2 n+ V2 c8 ^+ H - template: '<h1>自定义组件!</h1>'
* Y( X& o8 P, K4 k2 n: v8 ?! o - })
% F+ H! Z" \) {0 @+ h+ u2 ^0 ~ - // 创建根实例9 j8 Y+ i; E6 ?' F2 q: m
- new Vue({$ x! f6 D$ q6 \6 t3 `
- el: '#app'9 h& @8 Y- r: M* a
- })
; i# V/ [& {3 c - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: . B7 |( M% ^- Y l3 Z3 r$ m& D+ S
- <div id="app">0 s- W/ L; n# {6 L& n/ p5 |) D* r
- <runoob></runoob>
5 p! X2 ~0 _$ j6 l( N: { - </div>! X7 W4 Y0 N6 A# T1 D2 U
-
9 K2 p4 J4 }- d4 `5 W - <script>4 O5 F% I0 I0 e, C; G
- var Child = {2 \& v7 e$ B: ?* c0 O' M
- template: '<h1>自定义组件!</h1>'
$ Q4 x0 r J( m% ~" K9 o6 v7 o2 G - }
. t& k! W- A! I& _4 C& v - 8 H# t8 d" d+ d, M
- // 创建根实例/ f# J/ ?$ h. M V, y1 T' ^
- new Vue({" y, A' e7 W# i1 F& o8 G8 K; n( A
- el: '#app',) o( u: m. {, j
- components: {/ C# |: X4 N( y( S
- // <runoob> 将只在父模板可用, `1 Q4 ~$ m+ b" ^: ^
- 'runoob': Child
6 @0 @5 ~7 Y3 L; l3 p: D, c+ A - }
6 g! A6 J$ n* m% G% q; y5 A# D - })
4 ]9 x2 x% `7 c6 K' E6 i4 P, c - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例2 q/ C+ A2 z% [3 P# G
- <div id="app"># L' n* V7 K+ s. c& t9 Y8 C( [
- <child message="hello!"></child>" S3 n, O6 v- \$ U; @, S
- </div>- g* N, X+ \( S; o
- f8 e2 \2 u0 t; y
- <script>
" U. j$ y4 e& Q, h% _ - // 注册( i% Z" R9 i; n
- Vue.component('child', {
7 [: ?1 `( R; @ - // 声明 props8 v: Y/ I& k1 l9 F* U" Z
- props: ['message'],
6 u8 `+ t5 k% ?+ Y/ r' C" O8 k2 H - // 同样也可以在 vm 实例中像 "this.message" 这样使用
9 b8 f, J" L9 i1 l; D1 b3 O - template: '<span>{{ message }}</span>'' U* ^; x- ~( K% V7 h4 g6 C: C/ E: I
- })/ ~0 f( E) ?+ V8 t/ ?
- // 创建根实例4 H; V5 X: F" X: x. X! A
- new Vue({
$ E" i7 Q* O' Y3 a7 v- }" o - el: '#app'1 Q" S6 D) X0 b2 w/ O! M/ f
- })
/ U3 C4 {! u: M' T - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
. L" b5 Y7 l! M. U- <div id="app">
" Z' D. \7 K$ D3 ] - <div>; K2 J9 _. g7 `6 I# Q! ^8 Q
- <input v-model="parentMsg">% _5 z4 r" c3 q3 r4 M
- <br>
% _& N( g: o. H& X2 M& P+ k- ` - <child v-bind:message="parentMsg"></child>: i4 g& ]" X: j9 d m. x2 c6 N
- </div>
. u" |, }* W9 d+ V% B, D - </div>' z; l$ s) ?7 u: n# f8 `8 t
- & i" G$ s1 s. R- X' ^+ y* }
- <script>
3 g: }( K) @( q7 a - // 注册
( W3 W! m+ Q# B; Z) O% V; S1 ^$ M - Vue.component('child', {
' s4 l, H: m+ f! T: x6 m7 F: x - // 声明 props) n6 C% J4 y6 f- i, t S: @, ~
- props: ['message'],
0 a7 S: l5 u7 \# i - // 同样也可以在 vm 实例中像 "this.message" 这样使用& e- I7 c$ d# ^, G o0 ~ K/ o
- template: '<span>{{ message }}</span>'( o- o- B* S6 K$ H. n- x( q
- })
! B. W# R. I" ?2 t/ j/ D - // 创建根实例' Q( s6 b6 Y# ]4 I8 W
- new Vue({* j2 c& {% ]( d a5 _/ j
- el: '#app',
4 D8 M) _1 q& J- }1 L& U- x - data: {* j& Q* K+ P; b6 G1 t
- parentMsg: '父组件内容'" L9 F, ?8 L3 }7 F! E( A2 X
- }
: E6 T4 v& y% }- ^8 F - })
V. V$ ~+ X; l2 } - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例7 v, e7 [3 [, y: B' p! M
- <div id="app">/ G4 d, Y3 j" C
- <ol>
# q* Q# u) r6 a' d: G) A - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>! Q& s* t# ]9 C: _ Y& q
- </ol>/ j/ E6 p+ L, j: t7 O! Y& h6 K) g
- </div>9 V) w+ ?4 D9 h9 Q# r! p/ L0 {% r, }
- & B5 q' P, a7 }0 y- [9 L S) Y( y
- <script>8 c% x( ]% R! V9 z* a9 Y6 a
- Vue.component('todo-item', {
{5 u% U( I( ~9 A% ~ - props: ['todo'],
5 H7 G8 u1 _' x9 O- y7 }5 ? - template: '<li>{{ todo.text }}</li>'
( s& B5 X, P4 Z w6 J( x - })+ B7 g- G! S- ]' ]
- new Vue({
+ r; X& R" x. U& b5 g r' P - el: '#app',2 Q- K# U/ p( h
- data: {" p$ t% c7 a0 a( Z) Q1 B
- sites: [
% s6 B o1 Y1 W: A* d3 G - { text: 'Runoob' },
. {/ n4 D ~6 Z2 d" @# I9 o - { text: 'Google' },5 G/ ?& A. X# I$ M/ `
- { text: 'Taobao' }
# V6 g2 P* r; p6 v ?: c" W4 k - ]8 j, z+ @! F9 @) |3 }& t- L
- }1 X/ |- R3 H# b( i5 S
- })
+ [- }6 |) H/ t; t$ _" b* o6 n - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
. P4 z) [) q/ c) y( ~$ W& | - props: { }( e+ L( G3 F3 n
- // 基础类型检测 (`null` 意思是任何类型都可以)- [% V% ?; L' w& h6 {, k
- propA: Number,
, [; A* Y4 C5 O* z/ _ - // 多种类型6 \! X6 _& Z- q4 f7 f
- propB: [String, Number],& Z0 n' \$ n# h3 D; i* K, _* Z
- // 必传且是字符串
* l2 U- b: {' c. @6 V7 D% ~ - propC: {$ r) P" w5 q: _
- type: String,; j' N. o6 ~$ J' ]8 y" |
- required: true
3 H: N9 V1 g( |" P1 z - },' z- j* Y2 ?% c
- // 数字,有默认值
5 w9 h- \! d; c$ L- Z7 }: n - propD: {+ |# L% G4 A) s3 _
- type: Number,2 U M& J% \% a0 M, D
- default: 100
, M: H# w/ Q2 a - },
. X- B+ [" Z! F - // 数组/对象的默认值应当由一个工厂函数返回: g4 ]: D2 e: d5 e
- propE: {8 F# c9 s/ J6 e$ [- f5 u
- type: Object,) D. {- H+ C; {2 `
- default: function () {
. |% }* J$ [* F- w - return { message: 'hello' }
+ t- h: n) w' d. y - }2 f6 N- a% h [9 ]9 [
- }, k9 H% O# S/ @$ I: l4 B j
- // 自定义验证函数
( G0 ^) e# j4 x2 x; D - propF: {
8 S4 }" d% ]: \9 y5 f9 A& ` - validator: function (value) { o6 X! w, R" N: I
- return value > 10
1 [, [$ A+ ~4 C7 a; ^ - }
0 O/ ?0 z0 l: t) ^8 n* |+ l - }. X. t9 U- p' J. e" J2 ?: t
- }
9 `$ p* ?. D; g: k/ A! }" s: {0 Z - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
% f3 l) M% e) @5 I- V
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件: t+ V# E& K" Y3 X6 T
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例7 R9 q7 a/ y3 O" E+ R- ]0 _
- <div id="app">
) }: n* }3 ]# u+ [$ ?% _ - <div id="counter-event-example">
/ k. Q0 f- j# N2 j* T - <p>{{ total }}</p>% V" c" o" Q+ Y f+ ~) B
- <button-counter v-on:increment="incrementTotal"></button-counter>, N$ U5 O! s. k0 @. p* R8 n
- <button-counter v-on:increment="incrementTotal"></button-counter>
# P7 V& y4 B2 e+ r$ Z% Y+ c1 d' X - </div>; K( q- t( p/ U2 C; J# G
- </div>5 R- k$ S" z+ @% ?3 X
-
+ h1 K T( t) s4 {4 m3 f5 ` - <script>
8 n3 r8 i: c O- s% G6 J - Vue.component('button-counter', {$ y8 m' v! u! j2 a1 {
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>'," i; @+ l$ l7 o
- data: function () {& @- u- n, ]8 R& _ n! P1 |' z0 [
- return {) Y- i; I; D# O& `# ^7 \4 ]
- counter: 0
2 F; ]/ L$ m0 N8 ~: P# m! j5 z) Z - }; I0 E: v) |( X
- },
d& H- U( a7 j+ D! u - methods: {
7 _1 j$ }, a- q - incrementHandler: function () {
% b) Y4 i0 y/ K$ q" s( z - this.counter += 1* ^: t$ [, W) l6 q
- this.$emit('increment')
5 U# \0 l. k: d' [* w - }
+ S, c5 v! t/ T3 K3 r. i - },
9 F! e1 h7 z- _ - })$ Z4 }; y. }# s+ m" U) A
- new Vue({+ T N& n6 p$ e1 b8 ]
- el: '#counter-event-example',
: p2 B" t) c7 j2 j( c - data: {
) e- R' p3 ?, u* @7 k% C - total: 0
+ _4 K4 o% X7 z# y - },5 \4 G5 c F9 ]" s- q. F# i
- methods: {/ h w6 Z$ `9 I0 r7 V( V
- incrementTotal: function () {
$ T, E3 B# W5 t+ ~. ?7 f0 E - this.total += 1* m0 j1 G. P: L6 ?: [9 h9 y9 o
- }' q/ h6 s" @# u2 F6 a! j, [
- }
& S4 h; p, T; l- q. z- A - })
& V7 ~8 @$ }4 \ - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册: ] ~4 s+ c p* p, p9 P
- Vue.component('child', {
' ~9 R* q2 ~# q* A - // 声明 props
- ^4 S' R* c' j - props: ['message'],
4 [ ?( u) i5 m - // 同样也可以在 vm 实例中像 "this.message" 这样使用
3 K" ]0 m4 x, \ - template: '<span>{{ message }}</span>'% H+ `# a1 a; i- s% a8 F
- })+ C8 {8 b0 Y6 P! A# j
- // 创建根实例; ?* a# }- v* W) S
- new Vue({
; l/ n3 F& x" Y5 p - el: '#app',' m$ ~7 H1 ~$ v& X+ f
- data:{$ j; q" Z8 c- A9 Z O) `5 x9 I
- message:"hello",
2 i, }% A ?5 u# R1 F - }5 J1 }" k5 R# ^5 }/ Z
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
1 r9 A/ ]% b0 P* v- z) z - incrementHandler: function (v) {
, Z% _) r# j! v9 W- R& x - if(v==1){! Z4 x$ O1 i- w9 n, r- e4 e8 \
- this.counter -= 10 }: ~7 R) ~" {5 h
- this.$emit('increment',[1])) x9 b; N7 W0 R! d0 w3 s
- }else{
3 G7 q$ J8 B( b6 E9 G$ e - this.counter += 1
2 T& Z! A- H+ U- _) T5 [ - this.$emit('increment',[2])3 ]0 }3 r! ~% X
- }
9 i& z: h0 I: m7 F% b; [% i - }
" ~( N+ _! f0 c! n- ? - }
复制代码 , W0 t$ H0 Y0 _% a; J0 |
8 q' c/ S5 V: P$ w$ t3 B |