|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: L2 \0 g* ?/ i# Q1 \5 M5 A
- <div id="app">
$ g3 {6 M9 {' f0 X$ r7 c9 o - <runoob></runoob>: l8 q& B4 g. I& g8 y6 |
- </div>
( v% T2 t6 d1 t0 e -
, ?; J/ E! P5 S - <script>
, S- K' W4 T9 Z) D3 R - // 注册
$ ^% z7 Y4 z; t1 T c - Vue.component('runoob', {' A N8 N& R. J; i: `; S/ q$ \* c
- template: '<h1>自定义组件!</h1>'4 Z. [1 ^* e+ c$ S
- })
& n) h7 P& W2 x- C {. u& v. S - // 创建根实例1 ]# w4 ?8 F6 _1 F9 i5 h
- new Vue({# V# j5 v, U- X0 U }& N) u
- el: '#app'7 j/ B7 R9 i% u: w/ l. K9 I* y
- }). @8 k# f/ n1 S# B' l. F0 q
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: ' m% w2 c# R( S' {) z+ V
- <div id="app">
9 h9 K3 Z# X' O( q5 t - <runoob></runoob>
6 ]- g7 d- x9 h& J8 N8 G - </div>* @9 J) _. b/ H6 b+ L
-
( { w0 P$ h; h- P! @8 X7 f - <script>; P2 a+ s. _7 a( l* E N
- var Child = {6 V0 m# I# i0 q- A2 O+ w5 x
- template: '<h1>自定义组件!</h1>'
7 `/ V+ l( d1 _$ C! E0 t - }2 P1 q7 @1 r* N5 R
- 2 N+ G1 c4 C* O; J e
- // 创建根实例0 y4 I7 U0 w9 g: S
- new Vue({0 \2 v) g2 W) H, l6 @( I! ^( ^
- el: '#app',1 H/ ~0 V: R ?7 I$ o1 D
- components: {& J; s! h6 f# N; L6 D0 E) L' O
- // <runoob> 将只在父模板可用
- w/ k9 Y$ `& o9 T - 'runoob': Child
# ]* b+ z# P: v( s/ v, ] - }
0 h4 w/ J! D' f- u1 U( Y - })
! h3 x5 a4 J a: P6 K4 E2 @4 [ - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
1 i; H2 t' @% } l6 {% l- <div id="app">* x$ x. s2 S( t
- <child message="hello!"></child>
) D. o- Q* X! d5 I" {4 Y- k5 C - </div>! c& c X7 g' N6 a/ C' Z4 y: e) a
- ; \) {: E2 A( u; n! Z5 v" e
- <script>: Q7 @9 I. ~3 Q; z( |% A6 L6 c0 E
- // 注册
2 m+ ~& ]0 D% t Q( a - Vue.component('child', {
* Z& J, U3 i9 `' Z - // 声明 props
5 ^& N m/ o& D3 _1 u: E - props: ['message'],# u. Q4 E+ J# k1 w
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
( }0 Z; h8 K& k% a4 z( }$ ?3 a# E - template: '<span>{{ message }}</span>'2 I0 A( ^% p G, [% G" G2 x7 v
- })
, F$ G6 b6 Q& Y a3 c, N4 F& L p - // 创建根实例; i; w/ K4 ]/ @. W' V! l! h9 N
- new Vue({
: f& }. d5 `' R# B" ^: i$ K - el: '#app'+ Z4 Q& X6 A9 m( F c& M2 \
- })
P1 u& M5 j4 ~9 U7 _$ |( s - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
) }* v! K2 [) g, `0 |, R- m; f- <div id="app">, J# P9 y8 d# _
- <div>* H @! x w. N/ B1 F
- <input v-model="parentMsg">8 x. {+ F4 k8 I( ~; ?# [) s( F
- <br>; s, Q) @4 k9 @4 T3 g
- <child v-bind:message="parentMsg"></child>& M2 i9 S/ a6 L! }
- </div>4 ^% D) H8 }$ N# L
- </div>
" b) ^% Y5 ]# {* B% [& W -
) n( i) {8 ~+ }/ a - <script>1 ?5 G( N2 }" h1 F& @
- // 注册
" {& B/ }. v% n& m/ ] - Vue.component('child', {& r2 k# {9 P2 A# V: T" P' h* z- ^
- // 声明 props
. f5 t, l* Q9 N$ j- z - props: ['message'],
* a7 A) Y7 t1 ? - // 同样也可以在 vm 实例中像 "this.message" 这样使用
& g0 t5 y$ h m9 W: Y+ v2 ]" f$ d - template: '<span>{{ message }}</span>'8 y$ O6 A& ?4 v
- })
! q" R8 A# D5 S% E - // 创建根实例' C6 y8 J4 w+ d) d9 a! Q
- new Vue({
" H, w( U; w$ { - el: '#app',; \; s1 L( ]3 u3 r8 w' B
- data: {5 C4 [( T; S! G7 N. @2 i
- parentMsg: '父组件内容'
% s x' q( }) b - }! p. d$ j) O' P6 h
- })" _5 v# y$ v2 f0 ]2 s
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
4 c, V+ ^) g; g0 t% N- <div id="app">
) Q! g, P2 M2 ~8 d" x" c - <ol>
3 P' N, _ D5 b7 G( l - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>% ?; D& A4 L* m" w- l
- </ol>0 t, I5 W7 p" j1 f( [& X% o
- </div>! f5 m5 K: }+ D5 V7 ^+ F
- 9 ?% j/ v1 _( [5 Q) V- u! x
- <script>
4 e( H. e: A+ [ - Vue.component('todo-item', {3 q/ \6 o5 g% } Y, P
- props: ['todo'],2 v N' j1 u; ]( }7 f7 @) e8 H
- template: '<li>{{ todo.text }}</li>'" [: X+ i: r2 U# [
- })
4 s# n: y5 ^' k9 b - new Vue({
4 ~. @/ @: e. h. F* j! H - el: '#app',8 c5 }8 e& f3 d% I2 D# B
- data: {& s6 J. b0 n6 g r! N# L' I( E
- sites: [8 e1 t# w, u/ X1 b! {( d
- { text: 'Runoob' },
# A0 Y4 R% u2 o* I - { text: 'Google' },! k; M0 y! k$ g% U& u! x U
- { text: 'Taobao' }
/ M6 T' z# n4 v2 O& ? - ]
% }% |# [7 x# S - }* ^9 ~' y- ^5 {+ p) g" n; u
- })9 u8 ~7 }, A0 c8 C
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
4 p3 C) D8 r, W$ W: }0 o - props: {
; v* D8 a& u0 g- g% }' k4 x6 Y - // 基础类型检测 (`null` 意思是任何类型都可以); L* `) p z* B- K; M2 x
- propA: Number,
3 V* {7 f' c) M2 V - // 多种类型% F& U+ n4 R1 A. m, @ @6 E
- propB: [String, Number],
5 {* L9 x6 O7 ~8 n3 }: `: N - // 必传且是字符串
- D6 Z f" S0 u$ V- z - propC: {# L& z ` i! k! S- S( e/ X
- type: String,+ {, B2 h, D; n, p# W7 p1 K; k2 r
- required: true( c8 c% p4 |6 v8 x/ d( c' \ {
- },% a5 T; ]% l; w. y3 C
- // 数字,有默认值
1 e! x8 Y9 g- p+ P! Q! n - propD: {
1 M A; S( q2 c# Z - type: Number,5 q8 F1 H; r2 {5 t* R
- default: 100
3 L% ^8 {( [- R1 P5 n F - },
% X! I9 W5 J" ]* C4 k, ?) p - // 数组/对象的默认值应当由一个工厂函数返回5 Y, x- X, S; O S* ~& a
- propE: {6 Y; O0 M# [7 d' p( u
- type: Object,& j! K t: n1 v4 a
- default: function () {
6 c4 C2 a. z! s3 w, g& S - return { message: 'hello' } E3 n) C! y- p$ G/ Q" p
- }
# f2 Z# O% X- l, L - },3 W4 ~. u# s" T6 C, {" f
- // 自定义验证函数0 O* O' b6 _# O0 L. \* G
- propF: {
% p1 B" Y' y+ q( q& C- Q - validator: function (value) {' |" h* O. Q5 ]# e! E8 p
- return value > 10
+ r6 r2 r5 W- L4 m3 B - }
7 E* M& M$ d6 h! H - } P: r# ]: H- L; \
- }; ~0 ] G8 j( e v# x/ Q3 q
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array' |5 m! O; b) n) k$ Z
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件, f9 z3 t- } C* Y5 x+ S
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例1 ^+ Z2 h* l+ ?* \' J" q( E
- <div id="app">
, Q) M# `% w5 x/ |* S - <div id="counter-event-example">, A: s I: z3 l/ W) a+ z
- <p>{{ total }}</p># C6 Q: \( f3 i* [2 o9 C6 J( G
- <button-counter v-on:increment="incrementTotal"></button-counter>
. H# U( M7 W- X; m5 ?( S0 } - <button-counter v-on:increment="incrementTotal"></button-counter>
g4 C: K/ {7 d* k/ w/ X - </div>- M7 J5 z: C: e- R) @0 ?5 `* J
- </div>
& ~) D# T: C! R" m - : M' r ~) r' O, J# r ~% n
- <script>
$ L6 L* T9 b. s+ Z3 D! V: N! l& N: s: g - Vue.component('button-counter', { F, G% s! |6 l5 I0 k
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',! I$ l; O6 b& l& D- |0 G5 { o
- data: function () {6 ~" k* H/ N0 e% X! m x
- return {
e8 R$ r2 K$ ^ - counter: 0: ^" M4 N5 ]( p" ?% w2 g$ t
- }5 u% v1 |4 d& E* @
- },1 [) U/ _7 |- _( F) ]
- methods: {
- S# @* M# K) ~- n% }* l( L H' D7 t! K - incrementHandler: function () {
4 u$ t% T# n( X4 D/ ^ - this.counter += 1( C# `0 H8 E; e; I. s
- this.$emit('increment')6 @9 D# K5 t# @* ]5 T5 Z2 U: l1 T
- }3 h P: `$ t# v/ P" J
- },) E3 ]4 a3 G8 D- K! x
- })
! n) C( S( ?% Z+ _ - new Vue({
( T3 n0 F v& C. t - el: '#counter-event-example',. H- Y, d2 x2 ?1 L c7 x
- data: {: U+ f! Y7 T' x' L
- total: 0
/ _' ]6 I8 F5 t# c8 m. H! w - },! \. | E, o5 a) B8 {( J
- methods: {
) _# t# Y+ B5 p. D+ F' `4 y - incrementTotal: function () {
( x% m S0 h Z' l2 z- s' ~" w - this.total += 1! u/ V- y# H- N9 L, [# B- R
- }
3 ~- u3 _: c( v p# F% q - }, A( d( @) Q! z
- })& |9 |6 q$ N8 |
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
2 z. K7 H& h; H$ I9 Q/ O& u% c9 H. |+ t - Vue.component('child', {- |; K: l/ w$ j; U; K5 z5 Z* m
- // 声明 props& j- Y$ K( k& ~3 @' u4 V( a' r, g
- props: ['message'],; N! N$ i6 T: e* f# Q# k, K7 b$ \
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
Z8 \) E# M! g7 {8 L) u% a - template: '<span>{{ message }}</span>'
* _8 [3 }5 e6 W" ^" F( @! G8 l - })' Y, D- h) ~) @
- // 创建根实例
/ a( Y# z; C* m - new Vue({
0 [( X5 t0 I/ j- z V1 @. m1 D& v - el: '#app',
( C, K7 c0 U% J& L/ E5 F0 A - data:{# a' e+ u, s1 i
- message:"hello",
: Y& m d m* r' l: j- ~3 ^ ] - }
4 _: Q7 A8 W; Z! }4 Q( P - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {- R' X2 |' T) [7 ?& a" f
- incrementHandler: function (v) {
; O7 k; y2 N8 i I: `4 s$ T - if(v==1){3 P5 a6 ?' r/ k) \' v" v9 ^1 r' h
- this.counter -= 1
! a' I: }* X# Y. L4 a - this.$emit('increment',[1])
1 J1 w$ z9 Z- {4 {9 U - }else{
" _# y! z5 a! `+ I- K - this.counter += 1
3 b0 R3 k( z2 [# w- R0 U - this.$emit('increment',[2])/ X8 F6 f/ B0 @7 P* Z# q/ |9 {
- }
! k* F" R3 V+ F% i2 F - }, R1 S, [8 Q( }! N
- }
复制代码
6 `7 S0 q/ L+ z8 P" T0 ?) Q9 J6 {# S" Y
|