|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
6 h4 o8 Z; U2 L- <div id="app">: H( f$ ]0 H% H! F& R' R) s
- <runoob></runoob>
2 e3 d# f& u) Q, @ - </div>0 G. O1 `2 U R2 @ A2 v1 G
- - u |( ]9 d+ e( t
- <script>& l0 T) A; [: P
- // 注册
* O$ \+ q4 U% w6 d/ P. I - Vue.component('runoob', {3 j$ o& n' n6 a. p s4 c6 Z
- template: '<h1>自定义组件!</h1>'
. y) Y% ?4 z0 E2 V4 H3 z - })5 i" ] d( e% z# ]
- // 创建根实例; F V0 q3 L# t/ z: A0 n. X
- new Vue({
1 S/ `1 v2 r' S2 x - el: '#app'7 a4 }( G( j, l. t
- })
6 H4 S! V; k t$ t( d2 ]* H - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: ) `# K- m$ u( F: L9 P4 @
- <div id="app">
7 v: T1 M* P; r - <runoob></runoob>& S6 O8 s) i( q: c- f4 W- X' D {
- </div>
6 m* ^& }+ I/ x* [5 b e -
0 q: U. F, w# `& m" s - <script>" _' @2 M) B; p, C9 s3 v
- var Child = {
0 h& E- l* [: [) L; O& B$ [9 X- l - template: '<h1>自定义组件!</h1>'
6 d6 \, E' D3 Y. R: l, L; q - }( G/ h3 \4 k {) j2 H2 J( k2 R
- " G- Z6 x B: s) [- }8 A
- // 创建根实例
! L X" S" I* b7 \& ^ - new Vue({( a- U6 ?1 ~4 E' J! V
- el: '#app',. h" [3 G, @7 C9 R8 d. p9 k0 R
- components: {
) Z: P: L& z5 i - // <runoob> 将只在父模板可用, c0 [! Y0 c- {
- 'runoob': Child! T4 M2 f) g* z
- }
3 `4 C: K" ^0 [8 i - })6 {$ J. u6 @. K& q/ m
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
1 X2 c$ \! X4 S* M, }& m; f- <div id="app">6 g/ p. I* R/ d- t
- <child message="hello!"></child>
- ]" A0 w& ^ q' Q9 Y - </div>
- p" v$ O( T: Z! C v a) M6 m6 a, U1 E -
) i3 s$ H4 ]$ s% S2 Z3 j - <script>6 B0 H/ N& S- F" Y4 M; D) h$ L6 j
- // 注册6 M+ D( x# u: ~! m0 y
- Vue.component('child', {
: S+ \2 ~9 z% H h$ T& _ - // 声明 props
2 @+ N0 g( d$ e! ^& T - props: ['message'],
8 z- ?& w) o D+ p* X& j9 y% U' { - // 同样也可以在 vm 实例中像 "this.message" 这样使用
" W$ J" W& R# i, x6 g - template: '<span>{{ message }}</span>'/ Y6 v- k" ]9 X# T
- })- S0 t: e8 Y0 J7 Y! O
- // 创建根实例, u- L. G6 o! i8 `& v' W+ o
- new Vue({
8 o/ ?) A* P9 z1 y P - el: '#app'$ O' f2 P3 Z) D) q5 b C/ I
- })
7 g/ u) J, A! _. N7 l# g - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例. o& B! P4 \- W2 s# j
- <div id="app"># J2 S/ Q, ~9 t4 w
- <div># j3 ], }8 U$ R0 D! w# V
- <input v-model="parentMsg">
q: E3 k% u% D Z4 t - <br>" m6 I% N! x/ @1 T
- <child v-bind:message="parentMsg"></child>
7 m/ I% v4 } J - </div>6 Z' Y. V2 c) X+ k; A& T6 g8 A* s* F
- </div>7 A: O6 E/ Z* j8 _3 I: n. \
-
, V, u/ H5 f$ l7 m0 \ - <script>4 N8 C6 t; l0 y( R
- // 注册
" b p8 p1 `& p$ w" j: f - Vue.component('child', {* Z1 P2 B1 l2 I! g$ O2 ~
- // 声明 props
: p. I: o3 H% z" A8 b$ K- | - props: ['message'],
8 N2 v# Z& H$ z0 ]2 f( U - // 同样也可以在 vm 实例中像 "this.message" 这样使用8 S1 G' n" {0 V! O0 _ Z/ m) L
- template: '<span>{{ message }}</span>'+ E3 \1 b* E8 m. I
- })8 _" J) Z. j7 N! R& z
- // 创建根实例5 j$ ?+ v6 v* v/ x
- new Vue({
( S0 R& h) _' o/ s - el: '#app',; h& }! D* c+ a1 E8 h) \2 t6 ^ A* K
- data: {
; P5 J8 ]1 W0 B Z; \4 O, \ - parentMsg: '父组件内容'
, u `$ g& _% p% a1 ~) c - }
& O5 s6 c5 V3 {( T$ }1 o9 A0 b! R - }), I; _2 K) [, C
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
4 M- t6 m: c% { a( s1 Q- <div id="app">+ ?9 z5 y! x0 j$ f
- <ol>6 F; f' X9 K) R; S- u1 b
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>& y3 b! f, h( t8 F! ]
- </ol>
- A5 |' t: K ~( s7 e$ @0 k - </div>0 ?& v3 L$ B1 r; z
-
" T; w" @9 C" _# A1 o: K" i - <script>
6 l+ u4 t6 F% O. K( |( Q - Vue.component('todo-item', {
4 M5 Y' C l" h( ^3 O7 _0 W - props: ['todo'],
' b2 g: f% o# s* p5 P' e - template: '<li>{{ todo.text }}</li>'
, v% x' A: s0 D$ ? F) U/ j - })
1 J3 [3 l, t. d0 q5 {1 {1 E - new Vue({ }; p& P" J# V7 {
- el: '#app',3 [* \! ~1 q0 i) }8 l ^8 {7 y
- data: {
# z( b- `# d" N0 l( a - sites: [
: ?% i- \& l: b - { text: 'Runoob' },& E8 L9 ^& U/ K3 w' b8 `4 {- t2 Q+ W
- { text: 'Google' },
- a2 U4 D. ]% t: a) E - { text: 'Taobao' }
8 V' m& I# F1 |& c+ \; o; |$ K - ]& E& j9 z. k- Q7 F$ E! B7 @
- }
& f7 d$ L2 n9 E' X& {; b" ^. U) A7 f - })/ r5 M" T Z0 y6 t' U
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
6 F* C: V/ R I. N - props: {9 b8 ~+ T) Y( C* n9 {- N0 N
- // 基础类型检测 (`null` 意思是任何类型都可以)7 c% c* N+ J2 w* j9 A7 p+ \
- propA: Number,+ D9 s" m+ f# f" [8 S0 }' m3 s
- // 多种类型
" v7 V/ a9 p, a j- Z - propB: [String, Number],: C: n; H6 v9 ^
- // 必传且是字符串: k V; R' ?, r! N
- propC: {
5 D3 c8 ^' F/ w! ^6 ^ - type: String,
7 y1 j5 y5 `8 l) z! v: T - required: true
! s, _9 J* L2 l - }," `8 h F) d4 z9 ^( }+ `# \+ Z
- // 数字,有默认值
. \& f1 V, P6 s5 y4 [! Z: F4 j - propD: {) C: b; f) ^+ }: o2 Z
- type: Number,
! v/ f2 f8 D5 Y, E/ ~ - default: 100
# d9 p& G5 }. e, P - },& K9 g3 S( A/ D+ l6 Q: ^3 M
- // 数组/对象的默认值应当由一个工厂函数返回
y* \. O6 p3 q7 v: I0 j - propE: {9 Z* f/ M- E$ U; u" u* l
- type: Object,
5 O% O5 g6 F' J: V# g! N - default: function () {; i0 d* n* c, X# q9 P6 l7 X4 E
- return { message: 'hello' }
& h- s1 u4 R8 O( O0 ^9 M - }
! c$ d) O. ~: U3 b5 ~ - },: t1 t9 r% a4 M& |& B
- // 自定义验证函数" |/ {7 l* u+ `4 S" r
- propF: {
1 h9 E# ?# j4 F9 E6 a' _- } - validator: function (value) {. @( ?* C2 l+ Q! D% K- _
- return value > 10
# L D5 z. K4 K T& t( u - }
( Q4 L d- `& L' K/ i* p - }3 R8 H7 d6 a; e$ O" W$ h4 W
- }: K8 }. q. o+ w* w
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
, L7 H! w* t( r$ {3 z
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
* V! _8 ]$ B- h4 b/ z1 O; E& k1 i3 E2 [
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例# b+ |7 ~7 o" p
- <div id="app">
: i% @8 c! C5 k5 q0 _! ]7 n3 g - <div id="counter-event-example">3 ]& Z, A4 P2 O- ~8 R
- <p>{{ total }}</p>
/ H2 J# _ B* l- L l - <button-counter v-on:increment="incrementTotal"></button-counter>. ]; ]5 P" ]! d3 [
- <button-counter v-on:increment="incrementTotal"></button-counter>: j% e- {& @0 K$ Z8 K, a
- </div>: L% E# X/ l) l2 q" |4 g' y8 Q3 w
- </div>
, |5 l& f; a" c: U; ~ - ; [3 y, @ p6 |4 z( m
- <script>
* x: f& X0 W n - Vue.component('button-counter', {% S# m6 s1 O$ B3 q3 V. u
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',- x8 N) [ k/ |+ b7 V0 h+ C; L
- data: function () {/ s# n; e" q W+ s* ~1 ?' w
- return {. m$ W0 a/ p2 t' _2 L
- counter: 0
% @$ ?' p- t7 B' t& r - }0 ^0 ?. V! I" x" W% D
- },+ P( W, R* Q) K' k6 i
- methods: {' Q1 l0 N& N8 {- A$ c* x. v
- incrementHandler: function () {
* a. z* m4 N- J0 F/ {: J - this.counter += 1+ s! {2 _" |. d
- this.$emit('increment')
. n+ G; t) ~% Z9 y: x( F - }
+ _% N p6 u: L s; s% B - },6 U ]& O2 B- j& y% P6 M( M
- })
& ~3 ]" G Y! `( \& b2 M0 }+ a - new Vue({% {" g3 ^2 `+ F# r& g5 B. T
- el: '#counter-event-example',7 Q+ [" t5 ^8 v' r- b
- data: {, p. m# R! x }$ w
- total: 0
0 B2 s: w4 ~0 H, q% y' r Q* S - },
6 }! ]" E. j8 Y" ` l9 }9 p - methods: {
. Y! ?& H: P1 V/ c- f% e" `2 G) n - incrementTotal: function () {) `0 P# _9 @! v7 f* |* z
- this.total += 1
! ?, Q/ {# W/ C/ _2 G7 J# g: f0 f/ G - }4 H; x( K; d7 y# @
- }7 l5 s. Z4 Z0 g: D+ j+ I% m
- })
) {5 G4 d& A7 B& T5 g - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册5 h" X; U: n% a \# l1 `
- Vue.component('child', {
5 K$ q. P7 W6 k; C* f! M - // 声明 props( ?" j! D; s" d
- props: ['message'],
' p+ V T; R! w- F, B3 b+ Y - // 同样也可以在 vm 实例中像 "this.message" 这样使用
! y* B# A P" |2 C2 S - template: '<span>{{ message }}</span>'
7 I0 t+ m# N& e# v - })
0 }* j/ X4 l: }) E: Y2 \$ e - // 创建根实例$ v4 b$ G% S" F
- new Vue({
! c: b( m5 m$ o! G - el: '#app',
9 A8 ^: t/ `4 M0 A$ V+ A - data:{- @( }1 j% ]' j* v% D' D
- message:"hello",8 `" U2 M! Z0 i
- }7 I) ^% w. h5 ]) I
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
) E" |6 M7 F# {+ |6 g - incrementHandler: function (v) {
# {6 Z9 }" Q6 \; l( ~ - if(v==1){+ I" `5 K7 ~- w8 c& ]2 ?) h, D! ]* e
- this.counter -= 1
+ n% l- u& N# a4 m; M0 ^ - this.$emit('increment',[1])
3 w( l( z8 w1 a) _2 {5 b - }else{: J& B+ d, B' L
- this.counter += 1
: W- O3 V8 J# n8 M - this.$emit('increment',[2])2 d; n$ u3 g. H3 \2 W {5 h
- }: x( v- {0 M! k J, D
- }% i* [4 l% I0 D& M# r
- }
复制代码 6 g- e' V* z6 i0 f% _
. o( [, p c9 S |