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,并使用它:
% K1 R$ E1 f* m# M
  1. <div id="app">4 V- F2 s0 D* L
  2.     <runoob></runoob>% N2 _1 o0 v8 H- l. V: g
  3. </div>* |2 m. u# N7 ?
  4. 2 ]6 `" R5 C: k$ I$ Q
  5. <script>/ C& H9 j' O, g' V+ c1 z
  6. // 注册
    / F. q1 `* V6 S8 U5 M
  7. Vue.component('runoob', {' c4 z3 G4 g6 G
  8.   template: '<h1>自定义组件!</h1>': T8 r# a* }  S5 ~
  9. }): E* r# b7 o( Y: K. p0 q
  10. // 创建根实例0 A2 D9 ?8 D' g4 k& V
  11. new Vue({
    * y2 k# n% [6 e2 v3 G" Z/ Y
  12.   el: '#app'
    1 e6 r# N5 S) i1 i$ Q4 Y( ?4 k
  13. })' ~2 ~3 M0 }. ~* D/ h- d5 U
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:
1 A- _* v" n2 f5 g9 P
  1. <div id="app">
    ! t0 C8 c. @5 H4 \* g3 U% k' }
  2.     <runoob></runoob>
    ! g7 e0 j- l# V" X
  3. </div>
    4 a- e+ e4 u( G
  4. $ b5 y) A2 h' s9 J/ x
  5. <script>
    2 g9 ?! H" }1 H1 H. _. C3 s
  6. var Child = {. _( D" Z5 g; Z! B5 X7 |- S3 x/ Z
  7.   template: '<h1>自定义组件!</h1>'. \1 }# m, F3 S5 S4 K
  8. }
    ( Q; U$ }8 l+ |- B; o* w; f

  9. - j% ?! E; o5 s: x& P/ z( U; h+ {
  10. // 创建根实例
    9 B. _* i3 Z/ T! ]
  11. new Vue({' a; I! e" S5 |& r& u/ G
  12.   el: '#app',
    1 @! D9 T6 p5 ~4 B. A3 t
  13.   components: {7 ^) e. O) s# C% I1 C
  14.     // <runoob> 将只在父模板可用
    + ~0 _" Q7 s1 f5 b/ l. i
  15.     'runoob': Child2 G* ~. o0 c6 ^: e" T" ^/ G
  16.   }
      `: _6 z, _# k& `0 q: w
  17. })
    ) T& t; c* C$ J: Y, _, T
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
' Z. Z# B+ f" u1 h
  1. <div id="app">; h: k7 E$ e/ }! Q5 Z
  2.     <child message="hello!"></child>
    & r) V5 k; H" g* n! W) @* o
  3. </div>: d' C" `* c/ P$ G0 t9 r0 A3 T

  4. # o7 t& s2 f# |/ H& S; G
  5. <script>6 s# t9 I$ u, ]" n$ z
  6. // 注册; N+ H6 N5 Y1 Q( c8 {0 t0 f
  7. Vue.component('child', {
    9 n) E, v! U$ i% g& I4 h1 k
  8.   // 声明 props3 u" p* e7 k4 A% I, w1 H
  9.   props: ['message'],  W3 ]. F$ L# i- J
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    / E4 \/ B" B7 @- }% e* m3 V- ~9 c
  11.   template: '<span>{{ message }}</span>'" Q( k0 c4 U' k1 X$ j
  12. })  m9 D- \- {, Z1 g" [1 V/ I
  13. // 创建根实例. M6 |- i- g" R  G0 I# e
  14. new Vue({
    " Z2 {0 p" v8 \: T$ m4 `# {* g* @3 K+ u
  15.   el: '#app'
    1 r2 ]# Y5 M* {( X* F) h) ~
  16. })
    & c+ ~; S  J( n- p, {3 r, m) ?$ T
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
' T4 {/ H- T0 k9 R  \* {
  1. <div id="app">( S* d- u' g8 ~7 P: {) @/ A" ?7 C( G
  2.     <div>
    7 L" L, D  K5 y- z1 W
  3.       <input v-model="parentMsg">
    ; g) b" l+ @& B
  4.       <br>
    ; r" `$ I7 V3 E, f
  5.       <child v-bind:message="parentMsg"></child>
    8 K2 x# `. r& R9 `' R: [5 |8 d/ d. X: B
  6.     </div>8 D  [/ j6 g3 |
  7. </div>
    ; X* @- K$ h9 f4 |
  8. ; b' O1 ]- m- j7 ~
  9. <script>
    " V3 f/ {; ?3 y! D* l# m( U
  10. // 注册! I' F% K( W0 l
  11. Vue.component('child', {
    1 U8 r/ }, R) S2 _9 _) {: K0 v1 I+ k: M
  12.   // 声明 props
    ; c. _# f' O; U3 L2 Y
  13.   props: ['message'],
    ) a( r7 w$ \. h! a" X7 d% t+ ~
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    + B. a' h; ~# ^: d" ^' Y* X9 R
  15.   template: '<span>{{ message }}</span>'
    " @# _6 t, p6 h- W: I
  16. })
      O5 k* ~9 C; {  R
  17. // 创建根实例
    % p$ q- B; W4 u2 A3 n% a7 P
  18. new Vue({3 K0 I7 a# e  c7 F0 P) o/ |5 H; A
  19.   el: '#app',
    " ]( j& }5 I3 P2 I$ D% B; k
  20.   data: {" ^2 [2 z# \+ ~  |
  21.     parentMsg: '父组件内容'# p4 `1 a" B- a3 n- p/ {
  22.   }- g7 t  i* Q8 F/ \' ^3 G
  23. })
    / L1 u# p% r( R' g
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例7 A# k4 `) c  `# c! K
  1. <div id="app">& L; Z: I8 m6 t1 ^
  2.     <ol>$ u' v3 h+ p+ o4 E7 S
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    5 {" @8 R5 ~: ]- z0 M5 R9 R
  4.       </ol>) k( a. s/ s  O& l) A+ O
  5. </div>2 q3 k# s; P5 r- ~0 n. H/ X2 g  U5 b

  6. 2 @1 G6 L! a- k+ |- J' [6 d* k' w  Q
  7. <script>; U* ~; x, @* \  n
  8. Vue.component('todo-item', {. J: |( p2 B0 N3 }
  9.   props: ['todo'],
    + h. b& c6 P' ^+ x  q
  10.   template: '<li>{{ todo.text }}</li>'
    ; {1 O" `/ W8 H6 ~! U
  11. })
    + X* N, z9 X0 {) i6 n3 A$ Z2 X
  12. new Vue({4 Z; g5 `& I$ |+ @# c9 }! d
  13.   el: '#app',* G4 I9 M, f* }8 M9 L3 r0 n3 Z
  14.   data: {
    / I/ y, m% N: q7 b& T0 d) p
  15.     sites: [4 f, P9 F: u% p+ E1 i8 p
  16.       { text: 'Runoob' },; `# E/ G8 L8 B
  17.       { text: 'Google' },& O8 O' W( A" b# ]1 O6 t
  18.       { text: 'Taobao' }0 l: p9 K! Y4 d
  19.     ]6 i6 e& @& h7 K; F9 q
  20.   }
    8 n" V2 U2 ?1 T4 Y, o9 s8 _
  21. })4 v  G- O8 X' _
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {6 w, d3 M% p3 r! N3 }
  2.   props: {& \) k, v/ g5 L8 C: C; W& B
  3.     // 基础类型检测 (`null` 意思是任何类型都可以). d0 s- d( r3 w6 P+ a/ Z) Y- \8 A
  4.     propA: Number,0 u8 Y. h5 e7 y) w. t% G, G
  5.     // 多种类型
    $ v' a+ d3 ~7 a5 N
  6.     propB: [String, Number],  e/ s1 |) k! W
  7.     // 必传且是字符串
    ' j6 T! k: e" N& q0 Y4 }0 d8 K
  8.     propC: {
    # Y. G  E: J+ q
  9.       type: String,9 i4 T2 E. r% N" U  r: K3 z9 F! n4 h
  10.       required: true
    1 A2 x! A6 z, M9 r6 `% p  h
  11.     },
    6 P: d6 L% g0 x9 r4 m
  12.     // 数字,有默认值2 k8 z/ [0 Q1 V" @7 o2 [( r6 X
  13.     propD: {
    - D2 o% ^  X$ {5 \2 O* q7 h3 L7 ?
  14.       type: Number,# @" b0 C' C" P2 z. n
  15.       default: 1007 a! K* [) l  u! U5 {
  16.     },
    ; Q1 S  S1 _$ _, }( f5 ~3 _3 E
  17.     // 数组/对象的默认值应当由一个工厂函数返回4 A% i! Y% M7 ?2 j% l
  18.     propE: {2 W$ Q4 t* k3 [" H+ M! d
  19.       type: Object,
    / |  q% M4 |5 l1 j) \
  20.       default: function () {
    ( B. l5 Y$ t4 T: K
  21.         return { message: 'hello' }5 q# w6 c3 ~9 t7 \8 I* t$ [0 u
  22.       }+ g% i* \2 S, P
  23.     },+ y- P1 y% Q+ `: g: Z
  24.     // 自定义验证函数
    7 k" Z; |$ o9 _. Y
  25.     propF: {
    ' {& E7 m( U" ]* D4 s2 q
  26.       validator: function (value) {
    / ^% ~5 D# j$ m6 w6 v/ s
  27.         return value > 10' h6 c% y' P: r0 `0 u5 e
  28.       }
    8 f: s4 P! R9 y# l  T
  29.     }
    0 p& i; \% G. R! J% m  x
  30.   }$ c* D3 [( F  T) E
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
# m3 R: d8 V% i, Q0 A
  1. <div id="app">
    : T: I; c7 J/ D/ o
  2.     <div id="counter-event-example">( w6 p" S! [2 G$ q' I/ }4 j
  3.       <p>{{ total }}</p>
    : d$ v3 L8 j: L" `6 ?, S( s
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>1 s+ E( O+ y; x0 q
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>
    . I, a+ u$ Z0 G+ K
  6.     </div>
    8 F* j) n1 x6 h" ^8 z
  7. </div>
    : V4 C2 i1 F# k4 g; k" H9 i
  8. / u; U* Z  y9 _5 K5 T* ?
  9. <script>
    ' N3 p  {; R% J7 }  o7 F; W, ]! H& \
  10. Vue.component('button-counter', {! I0 b9 ?" g2 k, S
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    3 k  ^3 v% e6 ~5 I
  12.   data: function () {/ s6 E! S" T+ J1 I8 x" v- w
  13.     return {
    4 C& q% ]4 N$ P- e% i9 `$ e6 Q* I
  14.       counter: 0
    5 X8 B1 N1 S' \5 |4 m$ ^
  15.     }, v7 {1 I. r8 T; p  \8 n5 C4 n2 X
  16.   },( \7 D' q, s/ Z8 W' W3 P# v2 s( L1 W
  17.   methods: {
    8 f9 W  s& m8 `* m, R
  18.     incrementHandler: function () {
    7 v1 v3 y* e2 [
  19.       this.counter += 1
    ) u7 U& ?7 M, _  P& N& o4 S
  20.       this.$emit('increment')
    & J9 _& d# n* m& M$ M6 k
  21.     }5 ]! N9 ~% I$ `7 W: U
  22.   },
    & p" S" u2 @9 E8 ~' H# }; c
  23. })
    ) G9 ?4 N4 ^; j
  24. new Vue({
    0 w7 F$ J- j- M0 ^
  25.   el: '#counter-event-example',% c8 J% r* c0 S) k9 R
  26.   data: {5 r& W! w- c  j* O6 l; p$ q2 b
  27.     total: 0% F( x! I- x+ I: o
  28.   },' N4 A  Q; x( N3 l% o* \
  29.   methods: {
    : j5 l1 e' g: W2 n# t( f
  30.     incrementTotal: function () {$ e# X: x  o% y  m
  31.       this.total += 1- a1 Y* Y. p, b0 h6 _; S
  32.     }7 U9 @1 h3 ?, c8 }2 H' W
  33.   }, Q2 i1 R& G0 g' A# z: T2 ?: C
  34. })
    $ B) r0 N" P. A: T7 }
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册$ d) ]' g3 i& H( ?" L; Y4 b
  2. Vue.component('child', {
    0 b4 `2 B3 k" ^* ]9 C) |
  3.   // 声明 props  v( a7 s$ F1 S- R2 _9 V" c8 U# Y) G
  4.   props: ['message'],
    4 y' G% o3 F3 o) }4 D; c( m5 O4 _
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用  c. _  w8 S# r) }1 L3 \
  6.   template: '<span>{{ message }}</span>'4 t  x$ l& E1 J+ Z$ r% N+ b
  7. })+ Z0 ]) ], }- _& x
  8. // 创建根实例
    ; e3 F7 {* m. Y: k- i( K: J
  9. new Vue({
    # e2 H9 x4 w( ]
  10.   el: '#app',
    , R; c* S, [: d; i5 [
  11.   data:{
    ! g4 H- ~/ \* ], {
  12.     message:"hello",, S  U2 w% c% }0 n% R
  13.   }
    7 I  T6 t1 N% m3 g5 s% j
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {' Q' d# D3 U2 J! X6 |$ r* c
  2.     incrementHandler: function (v) {
    , {8 F/ Z$ y' |) q& C
  3.         if(v==1){
    5 `4 `& p5 O  x' o, C
  4.             this.counter -= 16 _) r+ O: y, C5 U+ t! a8 `% U, l. h
  5.             this.$emit('increment',[1])
    * x; ^2 H' b* W
  6.         }else{) Y: B% c0 y$ b- m
  7.             this.counter += 1; d& t" [$ H) i) ]* [# G$ f
  8.             this.$emit('increment',[2])
    / A1 I; j3 {  R: I- [% _( e; N. W: B
  9.         }! t) R  l$ y0 ~, E
  10.     }! R& h& y1 L* }* w: f" B; l6 \- s
  11. }
复制代码

3 c/ d, T; ]5 R3 r
  B6 j# s; n2 n, W& S9 P




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