组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
" Z. r$ `1 z/ I* W- |7 K) }$ F6 d- <div id="app">
; h1 W) X6 [6 g. I - <runoob></runoob>1 L$ \% C! O4 l3 Z4 w% G, j4 a, H
- </div>
! h: L" P/ p7 X: o- F/ Q: O( U -
( S9 Z, y! g$ c# |2 N2 {( o5 b% { - <script>
5 ]) y, `6 n* y$ }' T$ ~/ { - // 注册
7 G% U; W2 V7 b9 r8 b - Vue.component('runoob', {2 ~* H4 H, r7 ]7 [
- template: '<h1>自定义组件!</h1>'
% Z+ m0 U. @) `. f. v - })8 g0 o8 U; F/ F9 U- X% h0 A
- // 创建根实例3 D& A$ `: H% B& M( N+ k2 q
- new Vue({! L9 h+ v) }9 |
- el: '#app'
* R1 j7 _" A- u5 [0 ?/ A- j - })
: ^6 {* | |+ d% c5 h - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
; R1 E z: ^ e1 {9 f2 h- <div id="app">. n/ X" ]; t2 |: w
- <runoob></runoob>
, E. }* M$ Q* y" f; s8 ]: W - </div>
, {# k) _& a% e7 D -
! s" R% n6 j; t - <script>
, G9 H o" O- d: P$ T - var Child = {
( p6 g/ W5 @6 P - template: '<h1>自定义组件!</h1>'; ?) ^+ R0 K3 _8 {5 Q; |
- }
6 l" r) W+ p" H% _. w5 k - 5 J+ r' g8 v$ n% N
- // 创建根实例% ~8 i. T, ], d, o* |8 b7 R
- new Vue({8 }: R; Q) F u9 r) F
- el: '#app',2 @8 e* H; F- i4 m/ C
- components: {* E0 _) S; b$ J) ~
- // <runoob> 将只在父模板可用
6 ~( i2 F' ^: @1 j9 o) C4 L - 'runoob': Child
, N0 O! L% M9 ^: a/ g, O) f - }
5 C4 d1 i" n$ S# l5 i: B1 L) J0 v - })
( K& }. Y4 X& e8 Y9 q% V3 I% C - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
7 ?+ Y0 [; T+ ?7 A- <div id="app">
8 S# o$ I [9 W2 c1 [ - <child message="hello!"></child>
. v0 O, P0 e. k - </div>
( v/ G' _' m9 S' L5 y - 1 M% p* [5 n2 {& X0 U" J& h5 u
- <script>
# X3 Y$ w1 A" T/ w: o - // 注册4 g0 O& |" j9 x
- Vue.component('child', {9 H+ c# L0 o& Z+ c3 K2 ?6 @% [ C* e
- // 声明 props8 Y3 ~" h/ u/ @% k3 Y* B9 \( b
- props: ['message'],
6 D1 l# J9 a' g5 }9 V - // 同样也可以在 vm 实例中像 "this.message" 这样使用
% k3 g/ e) z3 v8 j! U9 A' F" M, D - template: '<span>{{ message }}</span>'/ {" u, q2 `+ h7 @6 c
- })
1 z5 W. p0 j4 k - // 创建根实例) V" m- w' r% i8 s, E: F
- new Vue({' [ N2 H' ~" @# [8 U5 Z
- el: '#app'$ c4 d# J( D; W2 f8 ~5 i& ?$ R! P
- })
( @ C- v. i, {: v a. E" H$ i$ i) ?7 P - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
$ B! k% o* F5 A- <div id="app">
4 A6 { M% f/ O - <div>1 D1 T- [, X# H" M3 U
- <input v-model="parentMsg">
9 F* D3 _) R( ]$ j - <br>
- [4 I" H8 H; |% y' g7 p8 @6 Q - <child v-bind:message="parentMsg"></child>
- X8 J" N- Z0 E6 P8 g - </div>; t) {- L" r' m6 u
- </div>
0 u7 K/ I* j5 ^, _( d' p -
* K* p0 A7 d! s0 n' Y# s: B - <script>
" J) q$ y: o6 M7 l - // 注册
, P$ o* ^+ Y5 g2 Q - Vue.component('child', {' a( \1 @0 c" s$ @, w% I6 u8 ]
- // 声明 props [9 W, n5 F+ n- ^8 Q
- props: ['message'],
5 ^. K+ J' {2 J( E" e! H9 s - // 同样也可以在 vm 实例中像 "this.message" 这样使用 y, t1 K1 F3 O1 }! W
- template: '<span>{{ message }}</span>'* P4 @1 T1 d& i" S' j
- })
, n. ^) x4 R& Z4 X% M/ | - // 创建根实例
' n; M& @, | Q* r6 D - new Vue({3 m4 y2 K6 r( G8 T1 Q
- el: '#app',# ]8 O6 c1 W- u: P+ i# X4 }
- data: {
" T' Q+ K% l. S. {, u - parentMsg: '父组件内容' @: y3 G; \4 c' S- J* M+ V" d
- }
/ V! G( ^8 _/ ^1 p, v - })
2 K+ \; Y ~7 L" \: L - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例5 E- t4 V( h( n6 N- u8 z* b
- <div id="app">
6 X+ @. D; Q1 R3 l - <ol>
4 ]8 }! N' w2 A2 S) _$ [ - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>4 u9 ]# R! e: }6 Z
- </ol>
, k6 \9 I, b! ` - </div>
) z, }% r. x0 x) h4 p -
, Z; E! \( D3 B& i: ?6 ]- [ - <script>( g- q8 H9 s% X! C
- Vue.component('todo-item', {
6 W8 y$ p' }* n' u: y- I6 d \: x( h - props: ['todo'],
0 P4 l( h6 I# @1 x+ G4 W - template: '<li>{{ todo.text }}</li>'
8 [6 T* G9 x2 w/ |$ `- d# I - })
" M- S N8 ?7 x6 n' f9 J3 D - new Vue({1 X( f8 d* B) N. h R* E+ q
- el: '#app',
1 H) r+ p$ z( w - data: {
7 z8 {9 h: a7 Q* e* ] - sites: [; c! C* d( d0 d& [
- { text: 'Runoob' },% l0 c( r7 t. O
- { text: 'Google' },
7 ~4 q4 h1 w2 k7 k" n: I1 ]+ | - { text: 'Taobao' }- d( Z3 g" R2 j, P
- ]
0 X/ I |# v9 F - }. G! E6 [1 p$ ~: g7 a
- }) W6 u, a8 w1 `0 F9 q6 `% `# p
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
4 D+ `, o0 U6 O - props: {# A4 ]7 j2 G# C% {' B( n/ |! a
- // 基础类型检测 (`null` 意思是任何类型都可以)( C( O& q. O# t% }- ?
- propA: Number,8 U; O' I5 `1 P7 k& n/ U2 _
- // 多种类型
4 J' Y" K/ j2 L8 w) L - propB: [String, Number],
# \( O1 b+ [% n- K- l; w - // 必传且是字符串
" j% j) D# ~0 L: V9 H' r' G' `+ i - propC: {& H& r$ l& f: D
- type: String," J" }7 m) N8 s
- required: true3 M1 ~/ x: ^9 D6 h* V
- },$ o; S6 C* K- w: F
- // 数字,有默认值8 a8 M8 x& ? e/ h
- propD: {
+ S }- s* f* D. }: G. i - type: Number,
" k! _; m: O" M# E - default: 1009 k# o" w' t/ Z# i
- },
0 U# `3 D' s. `- V @7 b2 ^ - // 数组/对象的默认值应当由一个工厂函数返回
3 X, Y2 i* ]6 V/ F' K1 u- ` - propE: {
- }* H' t o7 `. p# y/ B4 y - type: Object,' u7 j, o( C% \+ f
- default: function () {$ H5 }) ^0 j) d$ q4 k
- return { message: 'hello' }
5 F: y! A+ p2 p" R5 k' M) }% [6 N - }
6 R5 |% z! x' C! K - },, L* z G8 l4 h8 {( s! V; k
- // 自定义验证函数
5 d3 Q% b+ T8 [* h - propF: {
/ j6 Z1 ]! p9 q" ?# d7 N7 Y* b2 I7 O4 o - validator: function (value) {
$ f) p! O1 L/ ]9 L" T @8 w - return value > 10
( H/ [' i) b1 `: o% K2 M' o - }
7 L0 J: Z0 K/ E. @ - }
$ O% O7 S7 f3 U - }' K. ?& V# D7 A. ^8 ^
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array8 ]+ W. x+ d$ h# W" |5 w2 X+ Y" k
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件2 a: m: ?& v9 A
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
( c5 `, E5 i% D3 U) r( |9 m8 G' D- <div id="app">0 }# d, Y! o" u# X, x3 u5 r, t( a
- <div id="counter-event-example">
! n' M a9 A% A% `3 P* [ - <p>{{ total }}</p>
: ]2 T( l M4 P4 s6 m - <button-counter v-on:increment="incrementTotal"></button-counter>( U3 C" b) n4 K2 G* G; B+ O
- <button-counter v-on:increment="incrementTotal"></button-counter>" o+ F( \' L5 X. |. J6 @
- </div>
4 R4 r0 n7 }5 @8 ?) _3 p6 o" A - </div>2 Y |: b2 T% o6 P+ K3 L
- , C4 t8 L5 ?& J) U6 K
- <script> d6 I' B# B+ N4 N1 \$ H& c
- Vue.component('button-counter', {1 P( _; u- l5 k% R+ V1 P7 ]6 H# Z
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',2 D+ y( d% t( o$ j
- data: function () {
4 }5 X/ z. H7 k - return {
5 n4 G. E- { p3 C) S# G - counter: 0
% b' O A8 {* R8 W/ I& v# c2 E - }0 C v; J! l/ x4 L0 l, T
- },
: f0 r! E- n, i7 X% p. s# L$ D. ~ - methods: {# j: `: m2 g" ]
- incrementHandler: function () {
( t4 O' n. k; J9 f& `- J" W9 c1 b - this.counter += 1
' I# l( z3 G" ?% d - this.$emit('increment')
, E( {: C: G+ x& w. m - }3 c& W. n$ r# [, _1 B" |
- },
' z1 A X3 Y0 A+ u/ W) C - })
9 c, t, E N3 F! W' H1 `$ c: ] - new Vue({
- X A7 s! A% L7 \, {1 y - el: '#counter-event-example',
; L/ N/ K$ H+ e - data: {
' x* j9 `% g& o+ W0 w - total: 0
! U3 N8 c+ O0 ?; p( A( s* T - },7 J/ ]' @1 ~; v& Y% N! c' f
- methods: {
& i! O8 o9 t" } - incrementTotal: function () {
7 }) H! E! w7 { - this.total += 1
: e0 e) v; u& ~0 r: s$ b1 t8 b - }
8 ?* R3 M6 ^; ^7 b' a - }
@% p* C8 q$ W2 v' P9 V7 j - })! f4 z, {2 Q4 o) m6 H6 _
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册2 e$ ] s: {5 |
- Vue.component('child', {
+ ^; Y4 g' N, W; Q3 V. v - // 声明 props: _2 J+ y4 ?" T% p/ O- U5 a5 Y" b
- props: ['message'],! \& O/ s, V* S7 M3 C. E5 ]
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
6 `+ U, A. g) ? - template: '<span>{{ message }}</span>': p5 `) @% [4 f- @/ e/ B
- })+ O+ f' I) z- { G+ A7 Y( @
- // 创建根实例. B$ U$ s" N/ V( Z5 j% ]
- new Vue({
; |: u- j/ U* S( x" z6 P - el: '#app',
. }% @: l. z- m! G2 w - data:{
( Y' F% t- S1 ~7 r0 N- P - message:"hello",
9 W# e1 W6 y) a% S - }' n$ C8 v O1 R9 f7 F. B+ z9 u
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {; a% k; k+ G9 {
- incrementHandler: function (v) {
# P4 p! e" q g" Z - if(v==1){
4 \. o* h( C: r - this.counter -= 1: O# Q" [3 w! O; C x$ |: i4 i
- this.$emit('increment',[1])% ?4 t8 ~' d/ h) x, M4 |
- }else{
- K6 @/ _; S. ?& P - this.counter += 1
9 g, K/ z' h7 l8 S, ~! e, c - this.$emit('increment',[2])% o1 A4 X" V, C" D% v" H
- }
5 A8 i- H( X# S- j, P - }
0 r Y9 q4 H9 F- g - }
复制代码
- x6 w$ X( R. U9 Q# [6 ~/ p, d& ]9 |4 ~
|