|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
5 X8 c9 D4 i5 C2 }7 C" u- <div id="app">- ?- v% T5 V& w' P
- <runoob></runoob>& D) T" D% x7 N
- </div>5 ~! E/ B" c5 ~. P% K
-
- _* }$ ?0 n- Q3 N - <script>' [ R" l- s: J( t: |7 }' q
- // 注册
- Y5 c3 X! \& w. t - Vue.component('runoob', {; B$ ~3 n6 g: |4 `2 ?
- template: '<h1>自定义组件!</h1>'' Z. q9 X2 l1 y9 m: }7 T
- })
) P$ F8 J" [# Z5 f ?* p/ ^5 N - // 创建根实例
+ p/ y( V! \: w9 _3 f# i - new Vue({
0 {/ r7 G- u7 I+ z e2 @( \ a+ ^ - el: '#app'3 P( I% R' _5 a) x8 Z: x8 j: Y
- })7 D8 L' o; P& @- d# P2 x. s7 a
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: " ]- x; D7 F4 \& o( M& O: g/ l2 n$ P
- <div id="app">
( r- c$ C2 Q& I+ ] - <runoob></runoob>2 Y. ?" L# i0 O4 q6 b- c1 `
- </div>
3 R- S% t8 U* q# B# [2 [7 h R7 X - ! S1 q4 \' l8 d9 V. N
- <script>1 { F3 N# p/ b3 j: s7 U) Q
- var Child = {
6 V( p7 W$ `0 }& x. L - template: '<h1>自定义组件!</h1>'! G1 S5 `: V! z- P, \9 K4 h W
- }' v8 B$ _! W7 f* P# \( G0 C. p
-
3 r! ]; J4 p) n - // 创建根实例* g. `2 W4 S7 \; W9 w
- new Vue({
+ e, D( P+ n6 } - el: '#app',$ ^& B" g1 H) _9 n& v, T$ R
- components: {9 V% B$ k m+ j Q o
- // <runoob> 将只在父模板可用
0 ]4 { w+ Q) h4 b - 'runoob': Child
& Y% T' I5 Y1 G7 ` - }
3 }- M! `1 @) ^$ h4 \, c# n - })* _* E8 d* G3 `5 k8 O6 q
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例" ~: [2 J/ T9 k$ O
- <div id="app">
7 l+ d/ K3 M3 L+ T+ E - <child message="hello!"></child>+ C# P0 r( D: y: |3 ~4 W# T7 V
- </div>1 C$ s& G$ X% E0 @0 G3 W% B7 b; f
-
- z. P5 @* v# ?2 r( d' F% D, }. v# g - <script>
u+ t+ n. J8 g - // 注册
* L. \4 \/ y" y: N( s7 ]9 K - Vue.component('child', {
. S5 o- Y5 [/ P' ] - // 声明 props0 y2 p( ?' V- u+ u# Q( u1 h6 o1 _4 c
- props: ['message'],
& K: V; ^6 {% Z# ?; t" H# t - // 同样也可以在 vm 实例中像 "this.message" 这样使用
/ G( G& c2 }1 x - template: '<span>{{ message }}</span>', O2 L' H9 X, q/ e4 f
- })
$ O4 Z' E+ Y5 @& o - // 创建根实例1 E# M' r, K; ^8 t1 T! `
- new Vue({5 ^+ P/ K: k$ `% [
- el: '#app'1 [5 `+ Z" {8 c- `$ m" e! D5 O
- })4 ~. r4 |9 {4 V) q1 i4 ]/ T/ F$ ~
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
$ H' U8 R3 ^& ` N; `$ r4 ^' I- <div id="app">/ a: N& U4 o$ k+ E
- <div>7 l; S# b) J9 g! j: v2 E
- <input v-model="parentMsg">" }) m9 B! M, d) t, N
- <br>& x# Q+ \( i& L0 n4 o4 z0 R
- <child v-bind:message="parentMsg"></child>
* E- L) k, g/ g - </div>
, A, |) T4 x( p5 s& O6 S( i/ J - </div>/ C. n. u1 B& {
- ; W; z0 A& o5 B; ^4 d$ L
- <script>9 ~2 o' `# k) _! l( K: ~" `' R
- // 注册. E) D* M: c0 _( A: ~9 ^5 J. W
- Vue.component('child', {
5 M! ~9 h/ d, v7 w5 O+ m - // 声明 props4 \6 `$ \4 `- P& l! d+ M
- props: ['message'],
8 I4 t. T. \5 r7 z8 @* n I - // 同样也可以在 vm 实例中像 "this.message" 这样使用
& \ t+ N, F6 G: k8 \! f - template: '<span>{{ message }}</span>': j- O- p6 u/ j
- })
* G; A4 z: m1 r& b$ T - // 创建根实例5 s3 @' L# R, l; b# ^1 N! ]
- new Vue({' _% T6 Y% E" {& {' C$ q
- el: '#app',
4 `: s, z+ K1 x' b2 _# C - data: {
+ n6 G# G- K; H0 v, t9 r - parentMsg: '父组件内容'
4 |. D3 m0 @/ v0 S1 ? K" _# a; m - }
" k) b, V7 K, C7 ?1 M - })
4 E9 B0 Q7 _& V6 Q; c - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例6 L& |! X; L2 s. l
- <div id="app">
: \/ S0 T" M( V3 Y0 R# Q - <ol>
8 E# W) V0 G: g( u$ M, y) | - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
3 I* S7 Q/ u' L" |, M - </ol>0 X V' x( q. ]4 Q! D
- </div>! j" {8 Z" G: `% m( i0 K: k6 |
-
2 M. _+ |' [/ M7 k - <script>
: L/ ]9 H. M" F' N% k3 X6 ` - Vue.component('todo-item', {& V9 J% V. u+ ^) p0 l* z( [. @
- props: ['todo'],) h3 }3 }5 f, b1 J; O C7 A! i' `
- template: '<li>{{ todo.text }}</li>'* e! s. f x, w4 S* U& g. v
- })7 m. u+ y9 [* u" ]
- new Vue({
, R) J0 [1 P% S/ y/ R - el: '#app',% V8 Z2 L+ } _2 E9 W* W! B; _/ T
- data: {
- x4 p) h. k' J* y - sites: [( E# z C# V9 O+ a# q" d* ?# Q
- { text: 'Runoob' },
; U5 w$ J- i% \- z6 E+ ^% R - { text: 'Google' },
& U4 I, N+ ^5 h" q1 i* m - { text: 'Taobao' }1 H h. t; l3 c4 X
- ]
. k9 a7 v! P9 B - }+ q/ m8 \8 g4 s( Y- E1 N; U; D) y
- })! `; I; e( U" B) L7 H5 `
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {( }/ v' k, p: P# Y
- props: {
6 a! E: X5 y, W; u - // 基础类型检测 (`null` 意思是任何类型都可以)- V) u" p! C7 `) D E! P$ Z, \0 o
- propA: Number,
, p; v0 K* Z4 {1 O1 I - // 多种类型( O4 M$ W, Z$ H6 y) ^$ Z, [
- propB: [String, Number],: y5 Y% y9 h8 \4 Q! m; O/ r) T( l
- // 必传且是字符串
6 Q) w, E% y% ?" G# X' u - propC: {6 p( N; K/ i+ @( z4 ^( } I7 S: g
- type: String,# Y, ]( `/ {" j5 m. G' B
- required: true
8 R e+ T3 ?4 ^4 O1 U! M - },
L4 D o5 c3 G% Y - // 数字,有默认值4 @+ X- H* i& J% h
- propD: {
/ Q( K, m. w& J* [! c s1 J& w - type: Number,4 a; T! v5 O) F: K3 d @2 G/ H
- default: 1002 a) {' s6 M4 h+ [: F
- },
% D0 z8 f. |1 M) C - // 数组/对象的默认值应当由一个工厂函数返回
7 T. U( z1 b4 y' B' }( R0 ~% }4 w - propE: {$ r& ^. m7 _7 }9 J+ `
- type: Object,4 j* Y4 q% P% M1 x5 N1 q2 ~
- default: function () {
! T \( b- n% R; l8 P1 ` - return { message: 'hello' }
! H9 a n9 `% ^0 g - }$ }" F0 S4 |' |
- },
' _% P* @. ~# {" |& H4 n9 {/ U* H - // 自定义验证函数$ i2 J) K- ^! s' C* R2 Q
- propF: {
2 C4 x) \, n% r! O+ r4 i! A3 W% t - validator: function (value) {
6 w+ a- ?6 ^3 v4 | - return value > 10
0 Z; g6 i8 X7 X0 e - }4 {* c& ]( \. R$ ?( `, b
- }3 |# A1 N* F$ i, h/ b: g5 R: |4 @
- }
( L2 S* Z- h e2 T* z2 H" n - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array4 b. a! Y. ^" Z: ^3 i+ i! a
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
6 p1 i6 Q' t: Y, R
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例% b( i6 E, a3 U& u
- <div id="app">
6 _( K* {9 g6 G - <div id="counter-event-example">
- ]; T* v8 L5 V4 _* Z- N, u) ~3 Z - <p>{{ total }}</p>
4 j2 Q' R9 V" ?9 S4 k8 U - <button-counter v-on:increment="incrementTotal"></button-counter>
: m; U) D0 ~/ U7 A - <button-counter v-on:increment="incrementTotal"></button-counter>' C2 p! O1 L, D
- </div> h% D- ?+ m) a2 ^" v2 D
- </div>0 V6 z \ e3 F+ l
- : y# S' k+ F" X' V. d
- <script>( T+ w- P" `9 k# |3 ]: n3 p
- Vue.component('button-counter', {
. I3 B; D* ?, ?3 A3 ?3 m* F" m2 d - template: '<button v-on:click="incrementHandler">{{ counter }}</button>', U2 H7 u* L* j1 j
- data: function () {, L; Y) p6 W8 ]- r5 @
- return {; E" r: H; `, K
- counter: 0
0 `+ l+ n3 |. C# Q8 f; I1 J- A - }, C$ w& h# H8 r g* E; A
- },
. U- {+ X7 U S) ~1 }4 o - methods: {% j5 D( a. m. O% w% @# i) [
- incrementHandler: function () {
$ P& d# P# f# [" R% g$ P3 S6 k - this.counter += 16 N! b' j9 a n- f& s8 w2 M4 q
- this.$emit('increment')6 k. E- N" h' b" C7 @* v; T8 {: E0 D
- }1 l! ?! u3 W# I b7 _' q# Y: [
- },) J1 V. J: K! n2 b4 N
- })
5 q" t3 u. d" d0 D1 y$ H - new Vue({2 c# O; N! V9 n }& Y! R! H4 N
- el: '#counter-event-example',
7 `, E% x3 Y- Q) S" d) w ] - data: {* ]. N6 K/ c' X4 c l; t x' ^
- total: 05 W! z3 r! W2 `0 Z8 ]0 A
- },* Z$ Q8 S) @5 z# N, r' X! b9 B
- methods: {, d! D! C [) B, j( H) G# E
- incrementTotal: function () {+ b" E+ C- ?: e: f; G
- this.total += 1
Z0 \4 g0 D. N$ W" n8 ^# C) U - }. w% N; x W+ R- A4 \; q
- }
, j/ i; E$ K: e; W6 m' V! ]4 c - }): n( E* n$ x* u* @3 N( k
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
( N& k4 J# ~; w+ I6 o8 c" X - Vue.component('child', {; Z6 p" T& A' q+ m0 o- s' K. V- n: h
- // 声明 props
) S Q$ J' Y0 T) j! ~ - props: ['message'],6 ]8 c: b4 x( O# w G3 k# d
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
) C: v" c; Z4 L6 K% n - template: '<span>{{ message }}</span>'
9 _9 _5 n; O) J% t" o - }): @0 `. u1 l9 f7 i: |
- // 创建根实例$ X0 B6 q; h) K8 R. U# M
- new Vue({% g* [3 V1 w1 j. @* s" O7 `
- el: '#app',5 {3 T$ X2 Y1 L3 q! u- [0 n6 @
- data:{
* r' h5 J- W" Z" F. t - message:"hello",
) t" E# h& x$ U - }0 h/ ~) D2 |! s/ U/ [- |$ U8 B
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
) }" F$ k, s& H1 e - incrementHandler: function (v) {
. k- j i, ]' r - if(v==1){
6 p" R' Y! l" ^ - this.counter -= 1
, o8 \1 [& ~& l) U - this.$emit('increment',[1])& Y' ~! U7 o1 \& y6 D
- }else{
7 D6 _" Q+ Y( N: K7 g' n& d: X: M - this.counter += 1
% T2 M1 g3 E, m' o' b8 Z3 I: Q' { - this.$emit('increment',[2])0 s5 E; Z4 i. r* ]$ E
- }' l& \3 n$ d. O; _% t# z" W9 H
- }
! ^1 B. K& |8 w9 ], m% I$ |& R - }
复制代码
# C" U q5 |! K: o% u. }% {. V
1 K% `" N& z& b: k0 {3 Z- T. D |