cncml手绘网

标题: Vue.js 组件 [打印本页]

作者: admin    时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
  1. Vue.component(tagName, options)
复制代码
tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
  1. <tagName></tagName>
复制代码
全局组件
所有实例都能用全局组件。
全局组件实例
注册一个简单的全局组件 runoob,并使用它:

. E1 ^9 T/ T* ], h3 X
  1. <div id="app">
    + G3 o, l1 k4 u3 S5 u$ A; G" l
  2.     <runoob></runoob>
    . i3 p3 p; I- `8 D, y
  3. </div>
    - G) W: I& {" L( R7 g

  4. 2 I' z$ V& O$ l# o6 Z+ I) r. O
  5. <script>+ U% s) {# n$ |% V( L
  6. // 注册
    0 Z4 \+ u7 z& F9 ?  ~
  7. Vue.component('runoob', {
      I: {/ H& Y' J) l0 J+ D& S
  8.   template: '<h1>自定义组件!</h1>'& t# M' t  b! R- S
  9. }). P; T' L0 r! C! `0 H( a6 o
  10. // 创建根实例
    / X' f+ ?# a4 g. @
  11. new Vue({
    ! g5 H( A8 \% _' i
  12.   el: '#app'
    % G; I, \9 v) ]" L+ f0 F
  13. })* K! E7 e  a& I
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:

1 y' [6 P( C9 o
  1. <div id="app">$ @' f) J, Y- v
  2.     <runoob></runoob>; S' g$ g8 j4 \  w: X+ k
  3. </div>. V+ ?$ ^2 v( A  K' X4 _* S1 E7 X
  4. # D! k# _( y/ |, G- g; r3 _0 _
  5. <script>, Z/ b% ^* {, _3 d5 l$ U4 P+ x7 O2 j
  6. var Child = {
    7 v6 k5 o2 ~4 T" c8 F  `7 _6 P  V
  7.   template: '<h1>自定义组件!</h1>'
    ! W2 o* n5 h. ]  H, o" Y0 `8 J
  8. }# o  ~3 ?1 F( K1 B6 Z6 }1 r

  9. ( m  F1 t7 v: R; R& L5 p
  10. // 创建根实例% V) h: i! a6 d5 ^( I
  11. new Vue({
    ; v. l) M% R, g/ q: l* e" ^2 c
  12.   el: '#app',, R! Z& [" _7 ?2 d" I7 k
  13.   components: {
    - E' U8 J- d* B. q' G0 {  K
  14.     // <runoob> 将只在父模板可用% o7 L: A3 l1 \/ {6 m
  15.     'runoob': Child
    * _3 Y+ n9 W9 s0 h* x8 Q
  16.   }
    , B( D9 y0 c. \8 e' A
  17. })3 s% b  z# H  F7 `
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
0 W6 l/ M0 R% G% D/ W
  1. <div id="app">! n0 D7 a) T. l
  2.     <child message="hello!"></child>5 ]# k; W0 k9 k2 Q
  3. </div>
    ' b* M) v1 x8 n/ t4 i( [8 c/ j# o
  4. 1 q* A  ?: F$ x" |  X+ U! |- Q" y* q4 `
  5. <script>
    : I! C: }% h0 a9 Q3 e! b8 q3 f0 C
  6. // 注册: U9 A' L- s9 d4 M( T
  7. Vue.component('child', {! O5 P; c3 V  k0 Z0 R
  8.   // 声明 props/ N1 C, X1 A5 l5 S* h) M. Z/ L. `
  9.   props: ['message'],2 |% L' u0 B( R
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用1 ~' j$ w# R7 n5 T3 W" \/ F
  11.   template: '<span>{{ message }}</span>'1 C# |' v, V% J) G- g
  12. })
    9 W0 c5 k$ Q' J: B5 n
  13. // 创建根实例: V( h8 I1 L  b# v4 `2 a9 z
  14. new Vue({
    5 H, `# I$ w' U2 [- u
  15.   el: '#app'
    4 q1 \/ U; ^; C4 N. _/ ^) g0 _$ d
  16. })
    8 B( I# ?4 }* }* a! n) y( X2 t
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
& X3 D; g0 U" ?/ H
  1. <div id="app">1 e& C0 _8 \' Q" z
  2.     <div>
    1 S$ ?: e$ ]9 m" Y
  3.       <input v-model="parentMsg">& z" c1 t  L+ _
  4.       <br>4 g( X! @; e) z8 D% P
  5.       <child v-bind:message="parentMsg"></child>9 W+ i" v% ^% Z! b- k2 h: X
  6.     </div>4 x  m* E' _( f; b# B
  7. </div>
    & E' b0 a/ F0 {9 h+ U( j
  8. ' d' g7 h- f0 q* u/ Q$ I6 I4 \6 [
  9. <script>6 Q+ ^2 |& p" W* c  u$ ^) ~
  10. // 注册
    1 S, i* i; i- A% @, V: w7 G
  11. Vue.component('child', {7 w( ]( f6 m- W3 y  M# x
  12.   // 声明 props3 C% q  h1 |% ~0 f, ]1 ^! V- b
  13.   props: ['message'],
    : R" z* }% X  u5 @
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用% o. X# I  m4 b
  15.   template: '<span>{{ message }}</span>'$ r) @- J$ X0 w$ B( D5 y9 v7 j* `
  16. })" a& H  _% c+ m* [! r) x
  17. // 创建根实例
    8 k7 _/ I" Q: j( V  q
  18. new Vue({
    9 r6 n- i: P. l) Q
  19.   el: '#app',4 }7 s: b3 I) {+ y* l3 Y
  20.   data: {' A" r, t/ h" C- g3 T6 L
  21.     parentMsg: '父组件内容'( l+ J5 }  X1 n. X* W) N# X
  22.   }' K; C+ n# j- b+ r
  23. })$ @8 o5 p( j1 z3 s( D2 q" r1 k
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例) I, G+ D: {6 V
  1. <div id="app">0 x/ R7 o" s: |1 {3 v, H
  2.     <ol>
    4 `, j) _* z* l/ C& R1 L- b
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    3 s! }) m! z6 n: _0 y" q" Y" \
  4.       </ol>
    - A1 m5 h6 a+ }7 K7 R9 m+ ~
  5. </div>& \8 s1 k5 m3 T4 t3 G

  6. / A, h6 ?7 B& ~5 G/ e& }
  7. <script>
    : {0 {3 O& n: t! a9 m
  8. Vue.component('todo-item', {; v0 I) Z0 U$ a: s8 |: p: I8 D
  9.   props: ['todo'],- D9 Y' r+ g  U! s7 J" Z
  10.   template: '<li>{{ todo.text }}</li>'
    $ d" O; P" n0 _" K& r0 g
  11. })& O/ y& z6 v% Y% q# S
  12. new Vue({
    5 o' c% \/ @6 b  p2 S* F8 R$ s) u
  13.   el: '#app',
    7 W7 K* a3 _* a' \& D3 |
  14.   data: {% l3 I' U7 ^' V- T
  15.     sites: [
    # T0 o4 {8 [5 R  T: ~
  16.       { text: 'Runoob' },5 S5 R. f; O# h5 `! c% ]& S
  17.       { text: 'Google' },
    0 T9 W- r0 s2 N5 @, @
  18.       { text: 'Taobao' }4 q6 o# [# |' c6 y7 Q/ s) I" a
  19.     ]
    8 G0 w! ~+ R! m5 k- Z
  20.   }
    $ L  |( B: h: n
  21. })
    ! s$ J7 Z- q, i6 \
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {
    # p4 c4 a4 u' ~6 o! S9 ~
  2.   props: {* Y8 L, b$ S1 d8 @5 D+ P3 A& C
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)
    0 _( x/ e3 E' D7 b6 Q9 ^
  4.     propA: Number,' R0 H) p7 J0 f0 q! H+ L) L
  5.     // 多种类型
    , g+ Y! \( V7 @1 O/ G
  6.     propB: [String, Number],
    , W* A+ S+ z0 E( }; s" R3 n) i
  7.     // 必传且是字符串
    5 Y( m. \/ l' L. ]( V
  8.     propC: {9 ?( Z# n. [* n; i/ O3 ?3 X* f
  9.       type: String,- R+ E0 F& `$ ?" X
  10.       required: true
    9 v; t! q' R+ N' E7 x+ q
  11.     },# ?+ v, Z6 _% w& d+ x( y; T
  12.     // 数字,有默认值' V. I  s0 y4 f5 ^) F/ b/ x
  13.     propD: {
    " @$ r3 C# I  V
  14.       type: Number,+ d  S6 c/ o, @* I& z# a0 _; P
  15.       default: 100) L% M1 i3 L. y' W/ }
  16.     },
    5 E8 A5 H2 o$ A6 n( ~
  17.     // 数组/对象的默认值应当由一个工厂函数返回
    0 W/ R9 f  ^* R- B% t5 ]; x' q
  18.     propE: {1 I4 G0 a" s( y" Q
  19.       type: Object,$ I* X9 f- Y: |2 Q& t, g% Z! y
  20.       default: function () {
    0 W3 O3 ?% y1 `  o
  21.         return { message: 'hello' }4 r* y5 X# r% r& K( ]! |
  22.       }* T8 c5 m; ~) g  u$ B* o3 r
  23.     },. |( @: [9 J. g" I2 u
  24.     // 自定义验证函数8 o" q, e: O0 P' I
  25.     propF: {, T2 |0 @  P* ?4 q" }# e& i
  26.       validator: function (value) {; ~* j% I; Z0 b' L2 C1 |
  27.         return value > 100 L% m6 h4 m! Y, A4 ^/ ^1 {
  28.       }+ F. T) q( z2 M8 W# n# @- `) E
  29.     }% L/ u  z7 j% k6 ?" ?
  30.   }
    $ [. N9 C! N- ^% h5 r0 E9 ~( o7 G
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例& g$ n# a/ \( I& n# n- U* V/ I
  1. <div id="app">
    5 J/ h! k) u2 o) t1 k) L7 P
  2.     <div id="counter-event-example">
    2 `( i0 x- V; O9 J" `% D
  3.       <p>{{ total }}</p>
    % T5 }# I8 V" W- n! `
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>
    % Y, V& m2 d0 c
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>/ v7 P: ]4 H8 Z( H- `3 I
  6.     </div>
    ! d0 T/ [/ H7 X) L
  7. </div>
    ; C' d3 {0 S$ ^/ R5 c7 }! u* E1 ~

  8. 3 c  B# O: _2 Z7 H1 S  r. ]0 S3 c
  9. <script>
    0 C$ |! r3 m. M* x
  10. Vue.component('button-counter', {/ k; D! Z4 Z4 H% t3 d% H# O
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',, j1 z$ A% W' p, A7 Q9 b
  12.   data: function () {5 g/ v. O" N, @9 R5 ?4 P# t0 m9 y
  13.     return {0 {0 r+ G5 u* g# J7 |
  14.       counter: 05 P  \% c. x# P7 K/ O+ o
  15.     }# }( ]+ ~8 Y6 T% o& C4 L0 b$ T% o! O
  16.   },
    # m3 T5 h% R2 Z% r0 C
  17.   methods: {0 Q4 x1 I1 [( U
  18.     incrementHandler: function () {
    / r0 U& T8 \; ?. v. q) L6 `
  19.       this.counter += 1/ G' L; s+ \7 p  V) V4 c
  20.       this.$emit('increment')
    ) v6 O" K: c2 \5 F$ z- ^1 i" s
  21.     }* `8 T1 D* {1 @3 {, y3 w3 A( V
  22.   },
    " U) R, v0 ]9 u8 m
  23. })
    # }6 Y% w( c/ S5 @3 T$ f, m
  24. new Vue({
    6 V6 E( X+ u1 a6 N. }, g
  25.   el: '#counter-event-example',: z$ F, J; L( n" [, t% u
  26.   data: {+ n% X0 r& m; a: W
  27.     total: 0
    2 C9 _8 C2 h! e9 T" l! ]
  28.   },! g0 i$ a( W; i9 {# ]
  29.   methods: {! H$ x) K- X$ y
  30.     incrementTotal: function () {
    6 H7 I+ o4 ?, p$ a5 f4 I
  31.       this.total += 1
    8 [/ C& e: ]- \
  32.     }
    % G" {6 R" e3 w" I  q
  33.   }
    . z) i. k4 |7 x  a! H; o
  34. })" \* ^6 W: r7 U" U6 ]
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册
    ; K1 ]0 ?6 E6 q' _: K
  2. Vue.component('child', {) n1 Y0 C1 c4 J" G( k' Q
  3.   // 声明 props+ D7 s; A+ I' x. O0 x
  4.   props: ['message'],/ \8 Z/ d: V) k0 D, h
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用5 v1 `+ D9 q- M5 T
  6.   template: '<span>{{ message }}</span>'* G( O3 [: Y; ]$ m; l: O( L. ^
  7. })
    # _+ C* T4 n* k2 G9 u7 t& o
  8. // 创建根实例
    / _4 c9 Q: M7 h8 e# |
  9. new Vue({
    $ Z- O/ E* G7 O3 [) Q3 Q) `
  10.   el: '#app',! f0 X1 u) I! A- b4 c' h
  11.   data:{" _5 u; Q) q" d" @( `
  12.     message:"hello",- g- `; s2 i4 H( M! D) N3 s. R
  13.   }' G% p/ s) h  T1 [; R! v: B
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {" Q7 g% k, H4 M
  2.     incrementHandler: function (v) {* I; E0 o# ?( z# w" ]+ ~" F. t
  3.         if(v==1){
    7 c! L/ Q. l/ d; M5 k
  4.             this.counter -= 1
    % {; k7 t. x' g: H$ F0 W; q
  5.             this.$emit('increment',[1])
    ( L' M1 @8 i( V9 {
  6.         }else{
    5 d) u* Q( K1 G7 @% ^" s: ]$ ~
  7.             this.counter += 1
    4 z& o# m, B" L) J. R
  8.             this.$emit('increment',[2])9 ~( R2 Y% j' K( A8 y4 n5 R: H% a
  9.         }$ p9 Z5 ^% Z$ u8 B9 {+ d
  10.     }' X2 Y  t- F  P8 Y' }* F
  11. }
复制代码
! ~, I3 G& [1 B) p6 c  H
% q" u4 a5 H  `: i





欢迎光临 cncml手绘网 (http://www.cncml.com/) Powered by Discuz! X3.2