|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它: Q! c# [& [3 _* e% v2 |
- <div id="app">
" ^2 F; C% K% y/ r8 Q1 w+ @ - <runoob></runoob>
3 ?1 U; `. w2 O! a* Z3 c+ ^# H# w! {; a - </div>* i E+ ]- O% r# O' ]6 ~0 V' ^
-
" _6 S: y% n" { ~' R7 Q& c, g) l - <script>& ~# g$ Z& E2 D# P7 ^+ s
- // 注册
Q! P' ~ B0 m$ W# b$ d( C/ Q - Vue.component('runoob', {
: M( Z5 N% B' q' A6 K* i' G - template: '<h1>自定义组件!</h1>'
9 w7 V8 ]6 ?- a# S6 Q; h' ^. Q - })
4 R1 O, R6 N% R) u: L9 P - // 创建根实例
( B+ _5 X8 m: x$ Y - new Vue({
0 B: O; g5 R* `9 y4 [% a/ q/ m - el: '#app'
9 }0 E; Q3 X6 Y$ I( l7 _ - })
$ V7 p3 y& F/ b. E e! N% k - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
. ]) X9 r6 r; }- <div id="app">
" _* L: i) Q5 o ~ - <runoob></runoob>
& q' F5 B ^" b9 d6 |2 h) E8 t - </div>7 _0 Q6 m' y& Q i4 `% y i
-
9 p4 t2 k1 g6 B7 H4 M& C7 e - <script>
- D/ w+ H5 P1 K: K, E! y W - var Child = {
" \& j1 i/ L9 w6 N; N E - template: '<h1>自定义组件!</h1>'
: C. E5 B0 V$ L8 R+ v - }3 S5 ~! p" ]# i% ] v3 s% d7 a
-
) z! q/ _1 r0 [& A, ` - // 创建根实例
1 _5 q1 R" h h2 B - new Vue({
" y {8 {! y" D& H. ?8 c - el: '#app',) Y& }% {6 S7 [& j
- components: {. z1 R8 [, h# W5 A! Y c, q; l
- // <runoob> 将只在父模板可用 S9 i) k0 D8 E* J$ {* i1 b
- 'runoob': Child9 W9 H( X4 F8 G) c
- }$ t4 z. S' V$ Z9 ?; k1 Q
- })) a) V5 p2 ~3 D
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例. A' `+ c1 Z- c2 P/ p2 y, d8 R
- <div id="app">
. _* ~6 {- E4 p) V8 V4 ]$ Y - <child message="hello!"></child>$ P9 l6 P; [! o# d5 a6 B
- </div>2 d$ a$ r2 D8 a3 \
-
$ Q+ a6 N2 @4 H7 l8 o. k3 M - <script>
& T6 R5 d& S0 Z I. [ } - // 注册% W$ H% |- c8 V& J# Y6 v! V
- Vue.component('child', {
; L. F, a8 K) n ~1 {+ Y - // 声明 props
+ M1 N; r$ Q3 K; U @ - props: ['message'],
0 X! v/ O9 j$ }9 K3 S& `$ F( J - // 同样也可以在 vm 实例中像 "this.message" 这样使用6 X' o( c! \4 Z( r+ O9 p" T6 C1 o
- template: '<span>{{ message }}</span>'
. w4 D9 {/ k" h0 Z# | n4 b' ?! g - })
, S4 `3 h1 k! {: R. x5 v* { - // 创建根实例' p& e; g$ K5 c: A- S3 `' ?
- new Vue({, e! k- P0 \- g# |! D& s+ l
- el: '#app'
1 b4 ]9 w: b) N/ n! p$ J: u6 E1 { - }); {/ L" ^) y( S( W/ u _
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例0 d6 z& g0 A: e v* [+ U, T! F3 l
- <div id="app">$ n, j$ y5 x# \. O1 T
- <div>2 I* O k+ J1 i& u8 \
- <input v-model="parentMsg">
: B$ O. J, n i$ H8 d - <br>( }, ?$ W/ ~( V# ~" @$ m+ \
- <child v-bind:message="parentMsg"></child>
- s+ |8 x& [: M4 W" V8 i+ C - </div>) S9 Q' f' R( g
- </div>
1 \$ U( U9 x6 U% }" D5 |$ {+ | - 6 X7 e. g9 a5 t
- <script>% V0 w/ G% u$ w/ V. c% a
- // 注册' [6 b3 V; `8 g) t3 z# c
- Vue.component('child', {
+ ~( V& w: I, {8 o - // 声明 props
: w$ U5 y+ R/ I - props: ['message'],
: U0 N$ l; q2 u' ` - // 同样也可以在 vm 实例中像 "this.message" 这样使用! [7 c' F/ U, V$ B% x
- template: '<span>{{ message }}</span>'
6 L+ s4 N) f! F9 X5 `. L0 s - })
5 T1 m# ~+ I( u5 \ - // 创建根实例
' q2 I" V2 d. B) Z - new Vue({# n4 q# N. J6 N0 m
- el: '#app',
" g+ B* A/ Z' G) |* w$ S+ | - data: {: H6 P4 J% b0 n: ^/ @# E, u- A/ n
- parentMsg: '父组件内容'
3 `( Z) H: h% M2 g# d# w7 B% C9 l# a# J - }
7 ^$ {9 f: l. S+ W" i! b9 D @ - })
+ v% ~# k- S7 Z# v! B - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例8 b2 {3 f Y6 F, B1 A1 ^4 \
- <div id="app">1 |& F: E. @7 h& o* N) c5 M) z
- <ol>/ D1 }/ i; _1 y q
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
4 x+ ^. ~ Z% q6 ~ - </ol>: `# D8 |% [; N$ y( G( |0 ^4 M a
- </div>
0 s0 \! M- w5 R - 7 `" x1 P* S m: n. z |
- <script>% h+ G/ l2 }+ X8 ~
- Vue.component('todo-item', {
0 q. }4 f* H0 j- N - props: ['todo'],
1 p" i0 p! m6 \, I5 J9 [& k - template: '<li>{{ todo.text }}</li>': E& B. Q) Y8 V8 P
- })
* A7 ]3 K) v" d. V' X - new Vue({
4 S7 g2 i" O+ o6 f& j6 F - el: '#app',7 {! A) n8 ?, N; |: l$ r. }$ v
- data: {
! a. X9 Z" [4 D7 b) C - sites: [
8 p# L8 D5 V; ~: w/ X& n- H - { text: 'Runoob' },) _8 ]' {; V" ~/ S
- { text: 'Google' },
! A# P3 G, e( @ - { text: 'Taobao' }/ i; b/ T6 M/ _% z/ h1 B- |
- ]
/ n( i+ L$ P# c( y* U6 }- F - }
6 I$ u' `/ c; B$ l( ]! ~* P6 L - })
1 M: P$ W/ E) q, [9 H' p, t - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
- S+ b' L7 g8 |, U9 H% }+ B - props: {3 {/ P4 E! Q& j& n' R- F
- // 基础类型检测 (`null` 意思是任何类型都可以)
& v- ]5 s; ~9 C# W - propA: Number,
2 B; g% \7 G" @! D4 G0 N - // 多种类型' ]. y) A( C' @5 q C( r9 F
- propB: [String, Number],
6 |" s+ u0 ^/ a) C7 Z3 b8 U - // 必传且是字符串) s. I1 w/ F, u# C3 y5 s
- propC: {2 b' \7 F, T# m0 y3 K1 A
- type: String,
- i |. J8 n+ ~ - required: true/ P) D9 _9 ?# p. V
- },
0 E* o$ v( G5 v1 e - // 数字,有默认值1 M/ N- p0 ? v( o/ J
- propD: {' N2 [* }+ y+ e4 p; a, ^! E) r4 q
- type: Number,( `( w' z1 ~' }: I' v' I: f/ |
- default: 1004 X5 {1 v6 Q; \3 k( W3 \8 E
- },; i9 p( \0 D0 s1 \2 m2 t2 X
- // 数组/对象的默认值应当由一个工厂函数返回1 @* p/ S8 ]& F5 M) e: T% f
- propE: {
0 U5 E/ m z7 Y - type: Object,% [# v/ K: c9 }+ o9 p7 F
- default: function () {
5 |8 d1 W" T4 l# y1 q/ x - return { message: 'hello' }
' q8 x" E, p4 L e9 F6 o - }! \% B6 n: W3 {9 _( g# `
- },* K8 w! s9 L6 q) b+ F! n
- // 自定义验证函数
! O. h, C# F! p: S$ n, Q! @ ? - propF: {
0 b1 v/ g# e* s7 u0 } - validator: function (value) {
! x' c- n. o7 ^4 i% K* y$ g$ Y; g - return value > 10
) q1 T2 R! H9 ^$ S' W - }
7 [, {, A" g0 \ S+ q - }% F6 O7 J9 C/ h2 R
- }
5 ~6 T5 t" x4 e8 ?0 ^6 I0 Y0 M$ p - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
6 y7 V5 I% J6 l, x a+ \; [
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件/ k/ a3 a! v. h
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
; a, ^& o9 T( P! T' T3 I+ L- <div id="app">, A# w( n% O: _. |/ G
- <div id="counter-event-example">; N `1 F5 { s5 S
- <p>{{ total }}</p>
- F! e" c$ _# |3 M" V5 B - <button-counter v-on:increment="incrementTotal"></button-counter>4 p8 f& [: w( A7 I J6 }9 y. `
- <button-counter v-on:increment="incrementTotal"></button-counter>
' u1 H9 D' K( F$ P - </div>1 H) _9 T% _0 t8 E3 F8 S
- </div>5 \2 Q5 R1 g3 l0 ]# x
-
+ U3 |) k/ }4 F `9 q - <script>
- g9 B: q" e3 L1 j j - Vue.component('button-counter', {$ n! k" ~6 w) P; z
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
- I, v* i. {! o' s) C - data: function () {4 b3 I+ X) ]0 r+ Y' D' n; B3 N
- return {- l) P2 z8 F& ~. p3 d
- counter: 01 _* [2 G( g9 a" w% U1 Q* R3 Y
- }2 B7 i. h% D! p8 s( c# i: |9 _" A6 r
- },
0 \: V k6 }' ]5 L/ \% o8 f7 F - methods: {
& h% |' G% @( e; w+ O2 ?. ~ - incrementHandler: function () {) a. j- p4 s. C7 A E# j, W+ M
- this.counter += 1. A, b6 u& c9 U3 D# u
- this.$emit('increment')
( c: i# q# w, a - }
: j9 \ M7 S) R# t' L - },
: e7 h$ [ g1 Y5 l, I$ O+ E - })* I; }+ H' r: \- n' \
- new Vue({5 G0 u/ ^/ x) Y1 N, O4 x
- el: '#counter-event-example',& w% B- G7 @- I% l
- data: {
) l% U5 j, L6 I/ ~# \; D4 o: d+ ? - total: 0+ v+ O2 o, V$ A7 Q4 J, N# D* L
- },$ R& T. v4 p* t# V+ t, _% ?7 f& ~8 S1 N
- methods: {% o [. Z0 f7 J( }
- incrementTotal: function () {0 \: c# E3 C4 ?
- this.total += 1
- {* a v( `0 Q8 m - }: I- ] i% Y1 }& `; c
- }
6 J8 X1 F1 D' U# _2 J x6 U1 B - })& Q$ r: X' Y' L; s+ J
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
" n6 J& }, T& v5 O0 u' Y - Vue.component('child', { ?. f! d. j$ A* c' d+ S3 |
- // 声明 props; d! z9 V$ ?! ?) E; D0 `$ f! p$ ^
- props: ['message'],
& Z, d! h8 w& m. z* I1 o9 |, Z - // 同样也可以在 vm 实例中像 "this.message" 这样使用$ }0 M+ e' l0 y6 s1 S
- template: '<span>{{ message }}</span>'" k( w" J" u+ z# m& e
- })
0 k3 M, ]# }2 F f4 q5 G/ v" N - // 创建根实例
2 R R4 G6 E6 x - new Vue({# R( R# F ?4 L# H" b5 U
- el: '#app',
u S9 U% {( c! x2 Z - data:{" ~& Z# u) d. z! J7 {
- message:"hello",5 p" ~: W7 t c1 _! n
- }
7 c+ D& C- }" M - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
# M5 {1 ?% w) y8 N - incrementHandler: function (v) {* H. z+ l" L: Y& s# I/ P0 g
- if(v==1){
9 h, k, x. B/ R& b3 {0 x+ L6 _ - this.counter -= 1' T: o1 P4 V! ]" M! g9 F. Q
- this.$emit('increment',[1])
! {8 q8 @$ A" H6 _ - }else{
6 D' W9 @/ z( t+ N- S9 o - this.counter += 1- S \3 b0 N4 z! M' ~& _
- this.$emit('increment',[2])1 X5 C+ c5 a! ?8 w$ {4 \
- }
! E4 m. ]" Y; d8 \! k! ] - }
6 J" a* w- A/ {' }1 @/ M - }
复制代码
8 j# N6 [6 h; o2 P6 C5 L: Y. W/ Q) ?: g( m$ v, J- r$ f
|