|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
% m/ O9 s1 d5 L7 F- <div id="app">
2 R( D1 ^- [6 ?: c6 c5 W - <runoob></runoob>
& D) L+ h/ O/ L/ M, y - </div>
+ K& P- p. ?) X0 c; L' p8 M -
9 r9 h7 U8 O9 b; x3 f: i - <script>
9 |+ _; w3 Z% F1 p. V7 o - // 注册4 i1 s( Y' I$ s4 O4 R* P
- Vue.component('runoob', {% q7 t! r) V- u& K4 O
- template: '<h1>自定义组件!</h1>'/ x1 J2 X* ^4 ?+ Z$ W' R9 ?
- })# V! |6 T) v2 f2 b+ e( U8 @3 I
- // 创建根实例
& y0 _8 _; _5 V3 R - new Vue({
7 s/ j V3 L7 l+ U - el: '#app'9 L5 H6 p1 h3 }) ]4 o
- })
2 Z) S9 P; R1 Z1 Q5 t4 j - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: / o: e1 J4 m1 l$ T* Z0 L( V
- <div id="app">
. K; k" J5 @! G) k - <runoob></runoob>/ `- z: Q* s$ O$ r$ |
- </div>1 k: i2 u. H& T8 g7 x$ h
- 6 k% e$ Y, q# c9 H
- <script>5 r6 ?! S8 Y/ j; D
- var Child = {
) b, S4 } {9 `; U+ t- g. P - template: '<h1>自定义组件!</h1>'( p8 p; o5 v0 d7 [* U
- }* ?8 T+ ^: S: c& `" _
-
; y' S# e9 l& w, y; a! _4 b0 B& Z - // 创建根实例
6 v' W! m$ g$ e" E) h, P2 M - new Vue({
0 y0 S0 B, y+ p& Q - el: '#app',/ u" a, Y- `% Z1 Z3 U7 {( a
- components: {8 a. H/ I4 o1 x5 f# m# G0 f
- // <runoob> 将只在父模板可用. X6 K8 `' }" S. f
- 'runoob': Child6 Y& F7 i) |. o" F6 `
- }
7 j; j8 N0 l$ L' L- F3 V: A - })
$ q8 v; q) n9 L9 t4 ? - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例7 C' o# U% G, e
- <div id="app">; n! ^2 c# o2 E5 }1 o3 _
- <child message="hello!"></child>
8 }2 l$ i5 l0 U: l6 p - </div>
% ?/ G, [7 l: }! S: E, a" ^ - * S+ h5 R5 d- {/ t: o+ c, J9 K- H
- <script>
0 D1 ?5 O6 r( }6 C0 o2 n- q, V3 ^ - // 注册4 h1 L, o$ D8 M1 Q
- Vue.component('child', {; S6 d/ z/ Y; V* m/ w. x* g: Y
- // 声明 props
0 O' _0 X& c7 l% e" T* b, |7 l - props: ['message'],
7 A t- ], K4 m: d1 a% {0 s; U - // 同样也可以在 vm 实例中像 "this.message" 这样使用
7 Z4 h6 Q' _8 N+ X7 d$ t1 ? - template: '<span>{{ message }}</span>'
. K7 g$ {' r- z1 v - })( B; q4 Y% S( p# j8 p! H
- // 创建根实例% T; z5 q k7 M% M C& y# {
- new Vue({
* m2 e) W* f b( b1 W7 w: P; ]( V - el: '#app'9 s9 E3 C) v! [) [8 C
- })/ b, |) }) g# q3 Y6 ^% c, N$ `
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例0 A3 K0 s0 @5 v) g4 `+ w
- <div id="app">
/ X: ]8 F1 P( G - <div>3 v+ Q2 L8 }7 P/ ]
- <input v-model="parentMsg">& @2 e. S& N! n3 j+ o6 {- b. W4 X3 z
- <br>; Q4 E2 W2 s( ^7 a/ @+ h }
- <child v-bind:message="parentMsg"></child>$ G$ _/ Z6 C F% ?! k! p
- </div># F. c* v2 c0 l; u+ c q
- </div>: n* o$ C3 j7 C/ @
-
4 L* p; A- O8 Q9 f( f - <script>
3 u. U$ ^# I% E1 H' O0 Z# E& d - // 注册
8 _, W9 W, D/ M' n - Vue.component('child', {2 A# v8 G) `' h, E" _
- // 声明 props& o: a7 W2 N- E+ J$ u% N) |
- props: ['message'],
" W; q" t: p6 f; k* D - // 同样也可以在 vm 实例中像 "this.message" 这样使用6 n1 i; [* p: L6 f
- template: '<span>{{ message }}</span>'
7 X. ]3 d; x) u: ~+ H* q - })
5 j- e( ?" b* C8 C; G8 L - // 创建根实例8 D# K+ j6 V& D$ s8 q! Z+ V
- new Vue({# y0 I# M& z9 O
- el: '#app',- |* x' U: x6 }1 {& U# y" S7 p+ E. q
- data: {9 [* f& L+ D& I9 {; q3 N' {; G7 q
- parentMsg: '父组件内容'
+ f, r a; f1 H' t - }
, U" M6 L0 u( a& T - })6 a' j' r( O. D$ o6 i& X' j
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
1 u' i& [% S: \# O {( q- <div id="app">
" m* L% n5 r- v1 h' j - <ol>
0 w) y0 B3 Z7 j }, t3 j - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>1 X+ Q" I8 h6 s, Z
- </ol>6 |! I, o1 b9 L( ^- J: ~, Y
- </div>
6 v. Q' x# ]1 ]' D8 |! s - : z( n ~( f( {/ C r& N3 Q
- <script>% H) ~) g1 u& Y- H8 O# L2 u
- Vue.component('todo-item', {* D5 M1 W. g3 j6 r$ b
- props: ['todo'],, }' ^ v) n7 D1 v$ Q7 A7 d# S
- template: '<li>{{ todo.text }}</li>'/ ?7 x& C- O+ i( N% [' ~' e0 }
- })
. u/ |" x/ X- E - new Vue({
$ [7 E( J1 ~6 d6 L- L - el: '#app',, R P5 r$ U- l
- data: {! l: `' V- b" e
- sites: [
8 {) Z1 o; _9 J; F0 U2 t% u - { text: 'Runoob' },
' T( Y/ s7 {# \( b) J5 O - { text: 'Google' },$ d. H8 k/ A2 t) ]; e3 B
- { text: 'Taobao' }+ k- u! v3 D" ?! C: V7 O
- ]
6 y% w6 S4 v% [! Q& @5 s A - }
8 a# v1 v* |4 T) p: o! X0 o5 J - })
+ ?3 b$ M8 k" G7 Z* M- S6 R - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
% ]: {! e! e8 N$ y6 { - props: {
: B+ i) j% ?7 e* }4 b" W! \ ^3 x - // 基础类型检测 (`null` 意思是任何类型都可以)4 F4 W5 q$ z& s
- propA: Number,1 j( s; t, W/ g6 E
- // 多种类型 m& L2 b: ]& ]3 v3 y
- propB: [String, Number],7 i4 h+ A: u0 v+ q2 B9 I
- // 必传且是字符串
: z* e# V& K* T" l$ [5 E& t - propC: {
) n6 B4 ]" F/ p9 g, C# z - type: String,
- c: J" f( P8 n - required: true
4 [" e, S) f T9 H, d - }, x& J1 Q& _2 e! ^
- // 数字,有默认值
g' K; r1 C, W - propD: {' X. T- `" p! R- `, b" Q" E
- type: Number,1 I) Y0 `8 z6 C4 O8 s5 E
- default: 100
% \- O7 G9 X' v( _9 J( @( U7 M R& P - },
9 Q" v6 k; [ {4 G7 E - // 数组/对象的默认值应当由一个工厂函数返回
' e( Z. m- g: B, }0 q1 x - propE: {
6 M9 r X- s5 ~" V( c2 S6 U - type: Object,$ J6 p- u1 Q' U, `8 k
- default: function () {6 M% ?2 J3 Y# R6 n
- return { message: 'hello' }$ r# p5 t% i5 P" F0 F: q
- }
, [. ?6 L/ N C$ q9 Z - }," k# i; {' ]' B, b; }9 v V
- // 自定义验证函数
6 y. J, p; y$ ?+ k5 {5 f+ N - propF: {
" y/ i/ M" `) W* X- h - validator: function (value) {; a; q, o2 `; c! `
- return value > 10# y( w8 |! Z1 V% g4 ?% o
- }" L# b& Q+ i! n V: ]/ Y
- }
5 E2 v' ?9 K' E6 F; B8 v1 ]* M( d - }
' M2 M( T! n4 A: s$ o4 R - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array3 g2 ]2 l6 l3 P, @
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件0 q1 x0 e9 D- w9 O
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例: J! }. h. S6 U2 D& T+ [
- <div id="app">
" U: S1 o# m( J4 |) C1 R - <div id="counter-event-example">
* ]1 T, U% @9 H0 P+ t. {/ K& C- N - <p>{{ total }}</p>" V3 u0 M9 Q8 G, `9 i$ K" \/ P' E
- <button-counter v-on:increment="incrementTotal"></button-counter>
+ }5 {' q# n0 ^ L, a+ I3 h - <button-counter v-on:increment="incrementTotal"></button-counter>+ @" Q' z L: K! c9 K
- </div># W! c3 \2 W0 F3 D0 n
- </div>' Y) A @7 H" ~0 u: G
-
% W# Q) N0 \! N( X/ ^ s! _- d8 ] - <script>+ ^. X( n; `; z0 L( @4 Z
- Vue.component('button-counter', {) B& h9 L( Q+ b5 n" E( }
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',$ P& H" J& y, }% W) k9 C2 L+ \
- data: function () {" O( N7 O5 r/ j+ [' g, R% v; P
- return {9 c7 b5 \& E$ l, d0 f" j/ \1 ?
- counter: 0
- V" w0 x. V9 { - }3 K: g& P) T* H* N# `( P1 u
- },/ ]1 i) K! A* y1 W
- methods: {; `3 I% r$ Z" |' S) S1 L: g
- incrementHandler: function () {
) i l* F7 b5 ?1 [ - this.counter += 1
& f* j. A. Q4 [% k+ e4 l$ [+ o3 b - this.$emit('increment')5 ^2 ?/ k% y$ J& n4 E
- }, K- J6 u0 l; }; e: o
- }," J3 k# F- Z+ V6 |. }$ f9 P/ a5 F( {
- })
K7 J3 ^0 B {0 c: U - new Vue({
Y" o* l" A, x, |. W - el: '#counter-event-example',
' @0 E* ^( h5 l r9 x4 A8 v - data: {4 Z4 `$ Z" Z. e2 C/ q& P) k
- total: 0
( _ B" y+ c( E6 Z- y - },1 R( z$ F& o/ C3 D+ v
- methods: {$ @' c$ i8 W3 O/ _; s- q* }2 J
- incrementTotal: function () {
! q0 _; |5 Y3 `0 q9 }) f+ j: ` - this.total += 17 R0 @' q* {+ S5 o: K
- }
. i: E4 k' }1 B6 e0 L5 \3 y - }4 S: G% a7 Y0 Y
- })
/ W9 O0 l7 c$ C1 a" A$ g3 G/ i - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
$ L) R+ S$ v$ C& P& I$ t/ e9 } - Vue.component('child', {: p, ]6 {- t! A
- // 声明 props
9 L) D2 c$ `3 f% v- M - props: ['message'],) n- x# u) t# K" W
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
; Y. A( }3 n, x" H% z - template: '<span>{{ message }}</span>'
$ V* g( s4 s& e6 n1 ]" h - })* j" a: r9 X. Z) \6 Z
- // 创建根实例
+ P _; T. h3 u. ]- \/ ~# Q - new Vue({; l7 y: H1 I# Z& O
- el: '#app',- `) w' C8 q8 l/ P4 A, f2 i
- data:{% c4 o; v* |, q5 S! |6 D1 O
- message:"hello",
7 e/ @; a. r1 [7 J+ B J - }
7 b6 K* _" {5 o1 T" M# L2 }3 ? - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
) |6 F0 _" D+ D) l/ V! F8 H$ b - incrementHandler: function (v) { g% D4 G5 Z9 [' N0 }5 Z
- if(v==1){9 w6 \ i! _6 m8 R! i9 J
- this.counter -= 1
" j" K' f3 K( |& N; m% P - this.$emit('increment',[1])1 v# W4 S) H, c2 L
- }else{
: e& ]4 r) u( R1 g% t& h1 @ - this.counter += 1
6 E' l* V0 j9 [6 V - this.$emit('increment',[2]); L4 z o' h! X$ F$ i9 u: R' x
- }7 K+ [- j c, f, i/ N \
- }$ l; @3 Q# F; y) f& R, x
- }
复制代码
4 v$ F; B' h! }: z) E* m7 p6 ?/ k( l f, R$ A
|