|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: % R% ~* {6 z' l# {5 g" N
- <div id="app">/ c1 H7 A3 Y8 P+ Z) O1 Q
- <runoob></runoob>
- A9 V7 X, G4 Y% { - </div>& J! E0 P# D$ a0 N% G/ \) @, p8 C
-
: Q( D4 i2 v$ e% b - <script>
8 C5 g$ x# Q; j# S5 c0 z - // 注册
( d- W. h& g& |& d, @% r7 r* D - Vue.component('runoob', {: I" E2 ^; X9 P6 i; x0 F u2 q
- template: '<h1>自定义组件!</h1>'
; C, C% D- A5 C8 G - })' X$ y5 H& v/ |/ L! {- K7 O
- // 创建根实例2 t# s$ ?7 E" n
- new Vue({
: n$ S! i G' c! S - el: '#app'' z, r7 Y- ^' c/ l3 ~0 K# Y8 K
- })
& v: h# }. Y% s* H* R! a% P8 O/ v - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
1 c8 Q- R1 w* c6 H+ m- <div id="app">) B" B" ^* @- ^1 h$ R5 t/ a& f
- <runoob></runoob>
- k) B# N0 u, `7 h) w3 k# y - </div>
- [1 z* q1 f; } b - ' F$ j. B9 w/ H% h& A+ e) W( q
- <script>
* Z- j2 [9 r* x - var Child = {
8 [+ o% y4 _) q4 d& r& c# X% F - template: '<h1>自定义组件!</h1>'
* C$ `4 X3 `+ C U - }
* u$ N5 B5 r/ a# D5 G1 j -
4 J# d) K0 W0 }/ a - // 创建根实例. p* c4 c4 |" A1 t
- new Vue({
& R, Y; R, h1 ?* V+ l7 k+ r - el: '#app',( |" c% @, ?4 y q
- components: {
( q! e. [ F3 w! s - // <runoob> 将只在父模板可用; @* a/ ]9 p# C8 u/ c
- 'runoob': Child
$ x/ d/ w. x& ~6 ` - }
2 \& p: p/ y; J) V: ?, o - })
& u; }. W6 p6 h+ ~% L - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
4 b$ N% g' m4 T! X- G7 L6 L- <div id="app">
) g9 w) b5 E6 [, N4 e2 Z - <child message="hello!"></child>
& j! @( H7 k3 |. @3 g+ \, A$ b$ g - </div>- v _/ ?( O; I: m" d
- 5 X8 N0 `. V+ w8 n- U- R+ q h( S2 o& m' ?0 _
- <script>
5 N4 b; r! W$ n' V, v - // 注册
! t$ K9 |/ o, Z3 q - Vue.component('child', {
: X% Y% j" [0 [5 G8 j f - // 声明 props* m% `, o+ Y$ i) K/ \" t/ b
- props: ['message'],
6 e- u+ Z1 D% S% E - // 同样也可以在 vm 实例中像 "this.message" 这样使用
7 |) n' ^9 s9 X - template: '<span>{{ message }}</span>'& R/ ?! f2 m# Q0 h9 l# k
- })! J9 r( Y* L" ^5 X
- // 创建根实例
! b3 d# m; |2 O6 u O: r. o - new Vue({% i. i7 S/ U( V o& Q
- el: '#app'
. G1 g6 a8 U$ S8 C* ]% P* L! F - })
: E! m( p# d! v" x) h - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例) G: A# H4 `5 f4 X$ z3 |
- <div id="app">! S$ ?) o8 q* a1 c
- <div>
" G( ~! X. C; A, p; q5 E - <input v-model="parentMsg">
4 \% g' D- C7 N+ r1 n1 n& d; U! }1 U" Z - <br>
- W+ f0 u4 N6 n! f4 ^; y U. ?6 k - <child v-bind:message="parentMsg"></child>9 x' `6 v' ^7 |$ d
- </div>$ D) R+ Z( ~( H4 A
- </div>! `( J' m# }$ x0 }& K+ o0 L7 q
-
4 S" ^# w' h3 G5 P0 h: k - <script>
. G6 O/ }4 E" U& t C. U7 m - // 注册
( B" J4 Y6 E- A2 f: E! t - Vue.component('child', {
# [3 z& r/ t8 X, \- E. R# ] - // 声明 props7 X0 _6 H) y9 x: n
- props: ['message']," v7 }$ z3 E# p3 y
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
- r5 e4 W, }) G: d. {, R1 d - template: '<span>{{ message }}</span>'
9 J/ L% B5 q( f4 t - })7 `& a( Y! m: E$ z) T
- // 创建根实例
$ }. i7 {2 o' j2 b& d - new Vue({
6 q! k. n( B, O! {3 ~ - el: '#app',& p9 @& g; j0 V
- data: {" k6 j) j4 k& p" m( r) v1 _4 x
- parentMsg: '父组件内容'
8 r+ r. M2 w8 O$ a) G. k( o1 ] - }
9 ]( }1 [8 q- u/ j$ x) W& | _ - })
5 m; Q( ]- l+ N) L* N5 K - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
6 x2 T9 k( S b0 X3 u: W' K- <div id="app">
9 R5 m7 e; W$ ^- I - <ol>
& X3 a' F) g2 Y7 r1 T, P - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
% z% ?( n6 h3 U; P h. T" W - </ol>
' U0 U& K: }5 q) U1 Q& M! _1 ~1 f - </div>
: w0 k1 S2 F3 ^ -
# i& x! V6 J- u1 j1 [ - <script>
( }( b8 D4 D6 D - Vue.component('todo-item', {1 w( V% [3 ^. ]# q- E# f, O7 _% g
- props: ['todo'],
* R3 \4 _- K* y! U - template: '<li>{{ todo.text }}</li>'9 u! r* ~" R7 ]+ w6 }
- }). j3 `7 W8 K0 ^2 o" f
- new Vue({) q3 U8 ^+ i: Z& W& l# {
- el: '#app',
# Z( |& {+ M! P& `3 \3 Z - data: {# X0 e; }& K9 d$ c
- sites: [
3 e3 O5 I+ P/ l& r Z d) B - { text: 'Runoob' },
4 E& f0 f! F1 K& _% d/ s - { text: 'Google' }, b, H* |; S" l3 f, y
- { text: 'Taobao' }
0 a4 m" K( R3 W4 R - ]
; W- j a! z4 N( e - }
7 I. U) `4 w" x9 d: i C% k - })) O1 a6 |% M j$ a- k* d
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {7 O: j1 `/ x/ `! g3 q d
- props: {" j& @" ~8 u! w; v
- // 基础类型检测 (`null` 意思是任何类型都可以)
# w# B6 P8 L3 D1 J - propA: Number,
; W* r F. T* H- Y \( |* z - // 多种类型( W0 [/ G; |. I: Z' O
- propB: [String, Number],
% _3 Y+ l! L9 T$ _+ d/ O* ] - // 必传且是字符串# l# v) |1 w2 \
- propC: {
. Q" A- d- h8 Q; O! x8 \; g - type: String,9 h* @2 u6 w6 P5 [1 C7 f( w) |
- required: true; j# ^6 _ l% X. n4 g( T7 q6 K
- },
6 B. e) l- E* K* X: K - // 数字,有默认值
" }, m( @3 ?. e - propD: {& z) E0 I. J: f+ @2 Z, X
- type: Number,* S0 ~/ x( I/ Z% H$ ]: W$ c9 y
- default: 100
# Q' H1 X7 r( G% k' l - },$ Q% I1 U/ @$ M
- // 数组/对象的默认值应当由一个工厂函数返回7 s6 j+ C# `4 u
- propE: {1 K! ]) @, Q' l4 v8 Y s
- type: Object,
3 D; J5 F5 E$ D) j/ c+ o+ ^' w- } - default: function () {
: Y) A' T' s: T7 y& U# v - return { message: 'hello' }9 c* `* S5 D4 U) s b$ D2 I
- }4 w! U. M6 h6 V2 J. s
- },/ V: a( ]4 I* x3 H5 n, r
- // 自定义验证函数! M; V* h+ i! k! T# }
- propF: {
6 w; Z ^! U, N* [; }$ w1 L! z; ~ - validator: function (value) {6 n; w' V, F- a' Q v" p N V- K9 N
- return value > 10
& C; G9 E# G2 P - }/ o3 J; d( ]3 ]1 f2 q
- }
: T0 {* i: s2 b& ]; B - }- p9 R5 y8 c' N3 b4 q- G
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array- K) q. [% Y1 q* m' z
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件; W# \( x8 D0 i* S. b- B+ N
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例 t9 r! x' }8 I
- <div id="app">
! B6 [8 H& T3 l/ N& k - <div id="counter-event-example">( Z3 ? p% ~( ?* Y
- <p>{{ total }}</p>5 O( R' `* e* r. z
- <button-counter v-on:increment="incrementTotal"></button-counter>1 h; o' O, b" E( U' g7 q3 D
- <button-counter v-on:increment="incrementTotal"></button-counter>
( d1 B1 ?0 }) d! L/ j# ] c" k9 Z9 x - </div>& L" _& h3 H/ ]2 ]% C% `: V- T
- </div>
+ X* {2 i- D+ ^ S, A -
( b1 O, }& A2 a- ?& f - <script>% Z& t8 ~3 i8 V" T( U& S
- Vue.component('button-counter', {
- m; t" M8 D& Y1 W - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',+ o: {0 @+ g. K: T
- data: function () {
( I8 z' c# d5 G$ N* o* _2 ? - return {
- V2 C7 K8 c Y& C/ W( [0 a f# U* D( r2 l - counter: 0. |) _" X7 T, ^6 E, j
- }/ E& d0 T0 [0 W
- },
3 b5 K& p4 e* d - methods: {+ W, V$ t" r* t: b
- incrementHandler: function () {. {2 L% p2 I8 l5 L) i* U* {0 J
- this.counter += 1
' V& }0 W6 T2 W$ T4 T$ U - this.$emit('increment')
: P/ d- i$ \3 w+ Q - }
7 A' C7 ~4 W4 u# Q: r5 Z - },
6 J& Q8 z1 T- U% r* \! q- C - })
! d z# @! B1 _3 o2 L* G) U - new Vue({( Q. H$ H- C7 f+ H0 \
- el: '#counter-event-example',
) A% T0 ]: {; W* W/ D6 f: K - data: {. p' x+ p- s* i8 L
- total: 0
- T. A7 R1 T+ s; G5 A+ P7 o - },
( K5 v* B) w: E. P( v - methods: {, H7 x% h5 w x" r% U$ O! T
- incrementTotal: function () {, K3 X5 a6 v( _. x% f, X3 m
- this.total += 1: ~: c* p4 y3 [
- }& x, l' _4 v7 Y8 K) S
- }
% c: w! z; S" C$ }9 p/ C - })
* C) P8 V* c2 ?3 d7 C - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
6 f$ ?. u, e3 }$ C. q - Vue.component('child', {
8 c& ^, \: V# Y' z - // 声明 props( C/ f! N) Y4 `1 C( N
- props: ['message'],
* ^) s: W& H& z; D" \+ R - // 同样也可以在 vm 实例中像 "this.message" 这样使用
, N8 S2 s8 M7 t! o - template: '<span>{{ message }}</span>'+ L" ^( g1 t( s. v, E/ N
- })
2 R0 B, N) l$ R. t% J* _2 s" N - // 创建根实例
4 s1 S' d, k( q9 _' _, Y; T) f: ~* y - new Vue({
# P7 o3 Q5 x& G2 M$ m - el: '#app',
! @+ O5 o. |. D( [1 O - data:{0 |: z! k1 @0 a) x
- message:"hello",! ~6 u. E, }; r0 l
- }' G8 t) V7 n, C) p" Z5 d1 z. b
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {9 \$ w- @* d" g- H; |
- incrementHandler: function (v) {
7 D( Q7 k$ ?. e9 C! _4 I9 r - if(v==1){9 ^- C' W" T* Z3 [7 f% d( a
- this.counter -= 1
0 b/ D8 @" U# y - this.$emit('increment',[1])8 A/ E z( _0 J
- }else{
3 l9 P8 r1 ~ E9 Y( s. i$ z9 `% ]! q - this.counter += 1
; a/ x3 Z# R; ?; \' i+ v% I4 [% d - this.$emit('increment',[2])
/ q. h. a/ A- X# R' o - }
, g0 Q- o: u# N5 I2 ?% K - }
y' Q; I8 q- R" B. k; i. l- j* ~ - }
复制代码
4 ?1 n, J- D- j/ E% }. s) c* c+ Z. Z' }3 t8 a; R6 _
|