|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
. h/ N, X/ e6 M9 W$ J' w- <div id="app">* K/ W3 i& M" P2 _4 E" Z
- <runoob></runoob>: y* i6 h4 |) j9 @
- </div>6 d2 Y, E) j; v, J3 _/ H
-
e# D6 a( `# l& d1 ~$ M0 {4 h - <script>' {3 @- W) ?8 x3 J9 R% |
- // 注册
- R$ q9 j/ `0 O% z P$ A - Vue.component('runoob', {
2 r. D" t3 w* G p# | - template: '<h1>自定义组件!</h1>'6 c6 ]; t& Z" H. h( n- W# ]
- })& u3 \1 {. ~: Z
- // 创建根实例
0 ~6 d. o L: M* f& } - new Vue({4 {0 z2 D: k' P1 y
- el: '#app'
& |' y! U, N* Q* x3 s - })9 Z- `" J3 F6 \0 O- d Y" i& p& l
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: ( y1 B5 }2 R. W# D/ H/ n5 j
- <div id="app">2 P2 A6 ~" L% G; D7 b) T& r
- <runoob></runoob> w A. V6 B* a2 J! Z
- </div>
. D7 [8 |8 H& q2 ~6 v7 V - / D, B( L& f1 H. {7 L
- <script>
$ E/ ~. s7 w; o8 j - var Child = {
1 C/ z5 x7 X: K7 E# O* l+ K0 D - template: '<h1>自定义组件!</h1>'. S% c& Y+ I5 a% |
- }+ z7 Z( e2 `) A) W% C
-
4 J( o; P2 p1 D2 h - // 创建根实例5 p( [6 P& |# Y6 @
- new Vue({
0 Q: K* b5 \9 [, b5 s1 I1 e - el: '#app',
2 F ?1 N! l6 M; v. R( H0 Q - components: {
" u) r d( \# w r: f0 R - // <runoob> 将只在父模板可用" `/ a; \# z9 X6 r o
- 'runoob': Child. K1 A. m5 F& x! d% h b6 ^7 k
- }* |5 }% e' T" B& J
- })
: x6 M |9 @5 h; w7 ?5 b# y - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
+ W% S/ E, j) N9 N/ b4 X2 c9 a; j- <div id="app">8 r4 g' Z' ^1 f. o3 j3 Q, U5 U3 T
- <child message="hello!"></child>* V% i* V- v1 ?, K ~
- </div>
+ h3 j& x# @$ E -
& q' e' _$ X" f0 `7 @ - <script>
- }4 B+ S: g: R! t6 L0 D - // 注册' {2 R. [* ?6 R6 |. V( F. L0 x
- Vue.component('child', {
+ w+ g2 }& X; ^- t9 \+ b - // 声明 props, S# A% `% o u
- props: ['message'],4 c- C0 L9 u5 E; ?
- // 同样也可以在 vm 实例中像 "this.message" 这样使用' v+ W0 q3 F* L: R! R* ?3 R1 l9 Q
- template: '<span>{{ message }}</span>'" n+ {1 U% f9 a- M' w
- })
) m' T' E2 U! s3 P4 k1 B3 K - // 创建根实例
) A# e- L. }4 s- y4 i3 I - new Vue({
% d4 T% y( C" U6 [ - el: '#app'
$ u7 m; v3 C' C) S! J - })
, }, ^; @. `7 V3 b9 I - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例
9 H- S+ D4 c. o- <div id="app">4 Q, ~* N( c. f: g( B0 m
- <div>2 z8 e! [ y" I2 a' B: w
- <input v-model="parentMsg">
1 ^% R0 ?& p Y6 J - <br>& }9 l: R, \' p g3 i
- <child v-bind:message="parentMsg"></child>
- U6 \: c3 }) j5 h - </div>( e! r! r9 Y( c$ M% e# z
- </div>+ A- p8 q* j( F! }7 d0 U
- 8 ]: i# h# ]* {' m: \7 i$ L
- <script>
5 Q5 n" r5 o( O% F/ k4 M: v9 A - // 注册
& A* ~( s& I( C0 N% b! \1 d9 C - Vue.component('child', {0 |9 c- O1 q G" ?& P
- // 声明 props
4 h4 L( ^( A5 b4 I+ y4 h) P - props: ['message'],
5 C; m, a) H; a, V - // 同样也可以在 vm 实例中像 "this.message" 这样使用1 u2 U5 o) ]& G! ^4 h
- template: '<span>{{ message }}</span>'& c& d9 ?; }% G U# _
- })5 _+ O4 W, I9 I8 t% W$ k: ?
- // 创建根实例, j) A; T! R6 }
- new Vue({ M4 `; Q4 C7 H: \1 z! R$ ?9 N
- el: '#app',8 J3 R; ]" G/ b" n' D* f& w
- data: {, H. z1 h& j5 f& [' d
- parentMsg: '父组件内容'; }9 k; k! }8 ]; `$ T
- }
% X. y3 E( i1 w* f# @ - })( v) r* s' {4 x" a4 n
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
+ \5 b* J( V$ @, T- <div id="app">
; M5 r9 f% J7 G9 V4 E - <ol>
- K1 }4 i$ `' {+ \ - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
/ v+ B; N7 m9 e - </ol>5 P. v9 I* X" s2 J
- </div>
! m9 N9 n% P$ c ]) L -
- b; I7 v& K- Z Q; r* P - <script>2 m* {; B1 k. i# ~7 F- G
- Vue.component('todo-item', {2 t R3 _7 v$ t, D; m
- props: ['todo'],$ N4 w O0 G% L4 _4 v/ f
- template: '<li>{{ todo.text }}</li>'
6 C6 g* h. F7 K7 L2 e0 R B4 K - })8 h6 p" m1 T2 n2 i. q, [3 q' i
- new Vue({
3 {9 N9 l t9 v$ A4 l$ J1 S1 Y - el: '#app',# X1 J" l' _) [9 b
- data: {
/ b9 ^# h& m; i" x9 q: o - sites: [
* u4 B+ j# H4 Y$ z - { text: 'Runoob' },
/ q. H0 ^6 ]7 c5 c2 d - { text: 'Google' },1 `# [' F% y( l7 v3 S$ X; y* \
- { text: 'Taobao' }
+ C# l. d+ C) G- P; \: h; C - ]
1 J% H3 d# ^: J3 d7 K - }
1 a }. v. c |: x7 m9 ~6 O$ w - })
# [" M# V& M6 Z - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
: Q/ x9 ^) v2 U6 f" [: i/ S! t$ J - props: {' a1 e1 C* f: [7 w W4 y
- // 基础类型检测 (`null` 意思是任何类型都可以)
% u3 m' a) i& j" i( I* y - propA: Number,$ N% O1 A/ n: E5 D: D) u% n* C
- // 多种类型
5 G( p/ f: f0 V) A - propB: [String, Number],
; V# c7 |, `/ O& \ - // 必传且是字符串
5 d3 F7 L: Z# F+ q y - propC: {
& \+ y& g, H) h - type: String,. h- \! N, p8 r* ?4 V: {
- required: true$ M5 S Q6 M. Y0 X8 h
- },
; l+ y0 w( e; ?" c - // 数字,有默认值
9 t. f4 N, h4 t0 A) a6 y - propD: {% c, c/ `/ h% J$ z; w5 ^& H' l( ]% B
- type: Number,, a7 V* `( f' D% L1 M
- default: 100) P; m3 @2 ^; X! T
- },9 n4 ^# i7 L& U
- // 数组/对象的默认值应当由一个工厂函数返回! c$ _( I# g! O9 b' t
- propE: {
3 [/ r; d; C4 U; \: v - type: Object,4 {1 A8 p1 Q2 b! Z
- default: function () {
( c9 x. V8 i7 I' L! m - return { message: 'hello' }( l# P+ d2 {/ N3 L5 ]' }
- }
; k2 |2 v8 N; p" Z# w: y - },3 x3 w$ F' ]$ {
- // 自定义验证函数
|7 Q9 L4 p3 Z" H" U - propF: {, ~, G/ e+ P8 ?& _2 H
- validator: function (value) {8 X. h6 O0 p$ {
- return value > 105 f7 d" A3 o+ N. M% j
- } r6 r0 ^& C4 {( w% L
- }
& D/ K+ ?' V3 C: J! v/ [ - }$ a2 {# C: z, w! q/ |# P( b5 p
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
7 L0 ]- U; o2 f/ S5 N" {8 X
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件+ ]" _4 V2 b" ]
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例% V3 z: t5 Z( o e
- <div id="app">
. v+ \$ W& V: N3 o8 u0 } - <div id="counter-event-example">0 a2 G% V# U' Q4 s( w
- <p>{{ total }}</p>
) N5 l$ h d1 _# D - <button-counter v-on:increment="incrementTotal"></button-counter>
1 ^) R7 n- k6 ? - <button-counter v-on:increment="incrementTotal"></button-counter>
! W2 J# C3 S$ ?5 e" B3 T - </div>) a7 a, |- k( ^
- </div>( m3 t& z2 a; ^
- ; w' e; q2 X$ t1 b
- <script>" h2 R5 a. @4 q0 g* r5 h) E
- Vue.component('button-counter', {
2 b g& ?4 ?$ L$ g" V2 s5 p - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
: d5 E/ i" t+ [9 l4 Y( \ - data: function () {; b5 K; M$ x$ _, g a
- return {
* S( v1 F6 z' J; Y* k& J& t - counter: 0
% ^2 f( q' L7 w( X6 B - }$ g3 S. f; |& h- ]
- },
& l9 G/ E; B1 d$ Y! H$ J - methods: {- x. ?8 Q$ D1 t: p' o
- incrementHandler: function () {
! \/ n/ k. C* w+ f& H - this.counter += 1
G6 C0 W6 r5 R; A; F: B' p0 k( Z - this.$emit('increment')5 F) V0 S; q, |* J5 Z
- }$ W v1 ~# k/ b- K9 w5 Q. e
- },7 o- @, m: z9 l4 Q2 R* b0 V5 t
- })8 T! Z# `" D6 S
- new Vue({2 R; S4 l8 Y0 [, o6 b
- el: '#counter-event-example',; H3 t8 D d" F* E
- data: {$ q! ~0 f2 Q* @2 a$ r( \/ k
- total: 0
2 U! w# r2 d9 F x& q2 @3 p& _ - },( w4 m4 K5 T% E* o
- methods: {2 `: y, _* ?1 x
- incrementTotal: function () {
) f3 {0 n% @5 Z) X! N - this.total += 19 x: | A& x) t' p
- }6 z0 R. Q; T4 \. O/ z; k8 a4 `1 d
- }$ z0 `' e4 u( ?: ~/ |
- })
5 w' M. R% m% g0 w; N7 _ - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
* d: h# b5 q5 k7 g% g7 p; Y - Vue.component('child', {- O# h/ [8 `- p% j3 A8 `" T
- // 声明 props$ }+ h0 z; `$ y& i
- props: ['message'],
! g* b9 v! w5 Y7 y) S3 ? - // 同样也可以在 vm 实例中像 "this.message" 这样使用* o/ m+ L3 e. I$ P
- template: '<span>{{ message }}</span>'
5 w2 A. h+ B' U& u& _6 a1 L - })9 q: ?6 D; i% {! m3 X
- // 创建根实例
: ^* t$ x! i+ K - new Vue({/ ~; ^+ p8 o' A
- el: '#app',
. A* Q f$ B, E* G3 D0 B - data:{, D; ?: v. J- _; N$ M
- message:"hello",- h8 u: t/ L3 j% K5 F" j, w! Z
- }
: ]( `4 R% D @0 P, G - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {0 s" k0 Z& N6 Y& {5 H6 @% f
- incrementHandler: function (v) {8 c/ q+ x- J* O1 D1 B. L
- if(v==1){
/ c$ @7 a; V; L& x$ g0 G9 b - this.counter -= 1
0 G( n- h/ g# j, X9 |$ d8 X \ - this.$emit('increment',[1])
+ V8 {3 F" l' R8 h$ [$ x - }else{' @( X- ?% |# k3 \
- this.counter += 1
. f D/ G- T0 b3 e - this.$emit('increment',[2])
% K' X) b8 A1 c2 u. ~ - }
9 t: J: k5 q6 G+ ?9 t+ S - }
; t' M9 e6 k! F6 u - }
复制代码
2 O$ u, ^* I1 D. F! u) }0 b+ {% z. L1 a9 F5 X9 q
|