|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: ! a2 @" q; z! ]/ }' K0 R
- <div id="app">
/ c v7 o9 [! N' k: S% w - <runoob></runoob>% Z1 P- n$ P& _3 \* o
- </div>
6 e8 C- n2 R% |, u% O- t1 s7 h W -
& E" D i* A$ P9 D' d - <script>
/ z3 z6 W% r7 G5 N3 _8 G- Z) o+ s+ w - // 注册
- Z7 q7 W) P' W }6 p; q$ T - Vue.component('runoob', {
. {7 Z$ x, s) K4 c. e* @ - template: '<h1>自定义组件!</h1>'" b' r S# y1 _
- })
$ p% n& R3 u4 |0 w$ a - // 创建根实例
& ^, X) n6 ]. f0 G" x# c5 N - new Vue({6 C4 _! j" J% ]& T) u+ e
- el: '#app'
, I- A4 t' d& g - })
7 r9 \8 U% ^- L! F6 q: ]* \ - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: 5 ?/ A* j p, n( f6 U. T. W
- <div id="app">
8 o& [! I' Z. y x. W - <runoob></runoob>
2 F( f" R' |1 m a9 M; u - </div>% m: R2 K+ N* w
- . B- P9 g$ X7 i0 V5 j
- <script>
& s: f O) W& c6 ]6 N/ @ - var Child = {
/ S0 ]: y& N( X- L" @- O - template: '<h1>自定义组件!</h1>'
2 x2 @# U/ |+ f+ \, F - }+ D* E6 i0 l4 {' ?# P; W0 C/ [$ l
- t8 p4 v4 g) |5 c
- // 创建根实例
6 f) ?* g% t% V - new Vue({( C' O: _7 d% o1 {
- el: '#app',
" j. R* s; P c/ ~$ a! }% { - components: {4 D+ R# w8 G# Y+ k2 e3 @4 U6 O7 z* `; R; c
- // <runoob> 将只在父模板可用: G, \+ }2 c: W
- 'runoob': Child
! G* u V( ?. n! W - }- i3 E# x2 s, v; g' {5 F
- })
1 r; Z& u. J- F - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例8 m; y! m7 X/ }* ^0 n
- <div id="app">
3 J; H. @" B1 V% D/ s - <child message="hello!"></child>! n0 w3 C3 V8 z& V4 ]7 \" T
- </div>
- S2 l4 d+ h$ r3 v% f$ @ - 5 @ ~/ G- ~# Z8 v2 n4 g% J
- <script>
+ r% L' @0 ]. F( b7 o2 G - // 注册/ p+ h" F6 r, `% K n- I% [
- Vue.component('child', {
- T* |' o3 T2 J: [ - // 声明 props
' s# j- e9 \3 }+ j% ~ - props: ['message'],
( I% i+ G) O! _0 F - // 同样也可以在 vm 实例中像 "this.message" 这样使用/ d3 D3 Q5 l* L1 R4 w. r
- template: '<span>{{ message }}</span>'
5 z- `% @* `& |5 i" u - })+ ^9 K' i" g. @9 [5 Q
- // 创建根实例( _0 o* O* E- u x
- new Vue({8 C8 T! c$ r1 d; |7 r; M, p
- el: '#app'
- j5 r' L) A, V0 ^ - })1 X6 A* ]; X; X2 `; W4 ~
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例* a; g6 x" H7 y, f
- <div id="app">
3 c0 u3 n1 j: T/ i# l' r- p; W - <div>; _$ g2 j6 z# F+ S' v/ L8 r0 h8 b8 @
- <input v-model="parentMsg">
6 W, b/ V( }: J' G/ T2 ~ - <br>% y$ B& n/ p, I# l) T
- <child v-bind:message="parentMsg"></child>- ~/ V: I' M% E* X
- </div>) P- I' G$ e$ W1 \: N
- </div>
* r- o w6 P! q& | - $ h6 g. @2 a$ \% Z' p" M
- <script>
1 a7 T5 p7 o7 e+ V - // 注册
7 I* c I. d$ R7 F1 u' s J) F9 Z - Vue.component('child', {1 [0 x G* c0 U
- // 声明 props
9 }+ Y. G* F5 [7 P+ f. k - props: ['message'],& P) S0 [+ r3 T# W6 ^
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
3 W8 h% B( L* I$ U% _, Z! ^% r; B9 C - template: '<span>{{ message }}</span>'% L+ L+ Y- T0 a/ s3 Q
- })
/ R: t; L' d( G o8 x7 M6 G0 C# P A - // 创建根实例, o+ T$ a% p/ H# v
- new Vue({2 t* o$ j: k q( H( H! p
- el: '#app',
7 D R* G* q% e - data: {1 K7 ]* h& v& J% r+ w g) }
- parentMsg: '父组件内容') Y0 h# [) k) T% M1 ]& |/ w
- }! _- x) o" B$ x, u& B7 W
- })
/ a! ?; [& ?* j. o9 |7 L* q - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例8 Y4 v9 X+ n7 h' \6 S& @% P
- <div id="app">/ ?, ^' m& }" d6 x& @
- <ol>5 P' `5 d, p& ~( ?7 Q
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>) z, N7 O8 q9 i4 d% i2 }$ T0 V; a
- </ol>
& N2 f! ~; L8 m6 ~: X& t: a - </div>' W: `7 C6 }$ c* V! c/ J$ k, X
- " w9 n0 l/ v% o' ^4 t5 \- y
- <script>
f# z8 k* p' j2 F# R - Vue.component('todo-item', {" t7 v# \' E9 q' a! k! Z
- props: ['todo'],
( s% L# w+ }7 e8 O6 W - template: '<li>{{ todo.text }}</li>'
% I1 U; a, w$ _ z - })1 ]: X2 l; \! V6 J* i m7 ^5 v e
- new Vue({
" G7 X6 x- P* j; F1 z& M - el: '#app',
! u j0 o: ]9 n8 j' k - data: {8 S% d' w. s, v, D* G
- sites: [
7 r- G9 ~4 z |4 O' e - { text: 'Runoob' },
! ?0 c6 A8 A7 @/ b - { text: 'Google' },
2 l) @/ S1 m. A$ L w, B - { text: 'Taobao' }* A: y# K, V7 F8 @% H
- ]6 ^2 d+ s; Z* [- [# b- t: ~
- }
6 c, v: r7 a+ ^( G - })% {1 v( F' i1 [; M |3 [& e
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
9 }3 p- ?# @' k9 L+ ~) A - props: {' T- ~. Q: e- a
- // 基础类型检测 (`null` 意思是任何类型都可以)
% B( A% E3 w) q - propA: Number,8 K' S, I: \5 @! I, c
- // 多种类型
4 g# d: r9 W) f' H - propB: [String, Number],. b7 |. E# s. |, l2 H2 m6 | s
- // 必传且是字符串9 O+ p1 T q4 K* D# H) G$ X
- propC: {
" {( Z' n E7 {' a, I( h1 L - type: String,8 C7 m8 E( W+ n/ M& Z% j2 x# l
- required: true
8 t5 q5 q+ V' B- Q - },1 C- R: F0 R; k+ b7 K
- // 数字,有默认值/ S, K, e1 r" }+ N1 z: p
- propD: {
. i) J3 q2 P2 z5 w3 b - type: Number,
+ T$ S0 o. x* e. H! L) s - default: 1002 p( @! T9 d& d* u5 b* E: ~, r% h
- },
9 s+ p0 y3 v: q7 a: `2 | Z3 k - // 数组/对象的默认值应当由一个工厂函数返回# c. E' l' K* a4 U
- propE: {
) g* W% v- f+ z8 \0 V# h - type: Object,
! g& Q$ e9 ?5 o - default: function () {
4 ^; _/ l& U9 y) s9 N - return { message: 'hello' }
4 h$ k0 f7 \4 h5 M- | - }
+ S, }; ^1 O3 J; r - },4 R# f k& S# ?6 [, J/ N
- // 自定义验证函数
) [: `7 e1 W7 b - propF: {
( L7 g( ?. h O8 T7 N - validator: function (value) {
0 {8 q! H7 G' | - return value > 10+ c1 y, _- ?7 S
- }
2 L, p. h. w( }, z - }
/ ^( S; z0 J; ?% B( m - }8 a: O6 q- H$ V' h
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array3 ]0 e3 A/ k) r
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
* a* W! m8 D7 ?0 p
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
2 J# U0 m( i5 q, ^* u- ^8 t- <div id="app">
! i' o }. T0 c& j# E - <div id="counter-event-example">9 c) z/ t7 m' `7 P) u/ P# ]
- <p>{{ total }}</p>7 l$ A6 i& Q* p3 n
- <button-counter v-on:increment="incrementTotal"></button-counter>& q: j7 ]) P: A" D8 M( C
- <button-counter v-on:increment="incrementTotal"></button-counter>
5 V" {3 S8 C0 Y; i! Y8 L: p - </div>
5 _; I; @1 J( i' ` u$ v - </div>
! W( @1 ^) U# |, J -
' v7 O7 A( b% t2 y8 D - <script>
7 H4 K$ |7 R, l+ P - Vue.component('button-counter', {
/ g7 H; H _; O- t; b - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',1 n' h6 y: y# j
- data: function () {
' s# m% p- r8 V5 R - return {
/ s- D& m+ l0 L3 w0 H$ h+ W" Y - counter: 0
$ {# x j0 O0 r- C1 s/ H9 f - }7 K8 U- L# o1 f9 e. }/ N* N- Q; H" H
- },% s. T) D* s8 b
- methods: {
' ~+ [0 C* E) `1 R2 W4 y$ \' \ - incrementHandler: function () {; E# o' Q' x' p
- this.counter += 1
3 _. ]! e) n% z/ R$ \3 u - this.$emit('increment')
" j7 M- N X1 n, V. U( @ - }# R o3 O# C F
- },
3 k2 d! H1 J5 b& O& s4 E - })
3 Z+ T4 f6 {% m. A0 w: \# { - new Vue({% G; y( u; B) X8 s
- el: '#counter-event-example',# _1 ^2 I8 O8 ?& R+ M) l6 F
- data: {2 }' C( S3 Q' h. u6 m/ K! y* i" T" p
- total: 0
* c1 r: y( x. K3 I" c - },; B z4 ~. O$ x" R
- methods: {9 t) m" C4 C: D1 A. K
- incrementTotal: function () {
9 E2 N4 W7 y0 M# G - this.total += 1: z: B; J$ M5 L8 @( w. X/ T
- }
; p" c4 X/ v6 D6 ? - }0 B) @% y- X8 C$ ]8 K8 J
- })' ?" x+ L3 y! K' p% {# {( L! ?+ @
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册3 z7 O7 z4 w+ Z5 |
- Vue.component('child', {" X' ]. K6 }+ k9 ]6 q
- // 声明 props
6 p' v4 W& p a: k# ? - props: ['message'],& P \; @$ z o$ x7 y! V
- // 同样也可以在 vm 实例中像 "this.message" 这样使用, o8 e. r5 y: i3 @( X/ ]; \
- template: '<span>{{ message }}</span>'- j9 ^4 ]& t$ J1 h+ P4 Q) r
- })
& {9 T' X3 `# p; B; k7 V* C - // 创建根实例
" o/ u& C4 [$ `5 y% ? k - new Vue({( K: w9 O3 [- \* R7 n( h
- el: '#app', s: D3 `3 H% F% G }6 S% T! ]
- data:{6 w* b- {- c+ J3 F
- message:"hello",
+ n) I0 g6 x j' s0 j - }
! a0 r9 f/ p' Q/ V! |) T! U9 a+ { - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {* K, d! c# ? x
- incrementHandler: function (v) {. ~: M- j- F# w. Z4 D
- if(v==1){
" Z1 j2 f6 o' z& Z0 R7 U - this.counter -= 1! j7 t# A% f5 \& D+ `
- this.$emit('increment',[1])
' z& I* y C- o; G" H8 ?5 } m2 M - }else{
; G* n; R% p k& a- w/ V/ ~ - this.counter += 1: _9 i6 _% s$ v/ T% [4 J% l
- this.$emit('increment',[2])
+ q. Y+ m/ R5 p - }; k5 k7 J) s1 L6 z( R1 n
- }
8 _- a7 [3 C' ]$ L' k# a0 U - }
复制代码
5 \( q8 D# ^! B: J3 f
8 e. {" K# x2 ^- o |