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,并使用它:
- p3 i/ K/ }, |; O" k
  1. <div id="app">
    " b- T" C2 L' c" Z# S5 g
  2.     <runoob></runoob>
    5 H: T) D9 @- X) s+ h
  3. </div>3 X' e! _# w, V9 C
  4. 1 u0 f, n6 W1 v/ r6 K- J0 T
  5. <script>
    ! T; J2 H. o7 n( u4 m5 Q
  6. // 注册$ i+ W: S# E# k5 K$ [5 g) W( c; W0 H
  7. Vue.component('runoob', {
    ) B# X6 \# }6 {! A( T
  8.   template: '<h1>自定义组件!</h1>'
    ! ~+ }9 X9 C1 S3 p- L9 L% P( b
  9. }), S0 _5 y5 o' y3 h  [6 S" n3 E( Z& \: h
  10. // 创建根实例* ?8 r& l* C3 w, ~+ V' x
  11. new Vue({
    9 n! {  a- w+ [6 F3 L
  12.   el: '#app'7 q0 A+ J* g! f, H% l9 {
  13. })
    ) X! n- u( X. h8 R5 v
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:
) p7 @6 S9 z: u  K. n6 h
  1. <div id="app">
    ! q6 e0 P$ I% n; J  Q
  2.     <runoob></runoob>8 Z4 U0 n( O  n- A3 N5 P
  3. </div>
    # o6 u3 N5 L7 @; c5 L: v) U4 H
  4. , h" ?8 z  H% N. M  p
  5. <script>* q- |% W) v2 g6 x+ o- q/ Y( T3 ?
  6. var Child = {$ x# ~" U9 y7 ?7 l5 O; d
  7.   template: '<h1>自定义组件!</h1>'3 w0 Y5 s- D* }; m9 E4 Q! C
  8. }& y. H8 \* b" [& q  s$ G
  9. 4 z! }- E" M! R+ B
  10. // 创建根实例
    7 L: h4 G3 G. X# }# @
  11. new Vue({1 H3 ~4 H3 P4 `+ Z' I
  12.   el: '#app',
    % O) ^- d! p; q7 y
  13.   components: {
    * c+ B/ e1 r; J! p; \
  14.     // <runoob> 将只在父模板可用
    - S/ Y4 |" v# C* l2 k9 T) ^
  15.     'runoob': Child
    - D8 f5 Z: Y: _8 Q  o, ?# j! @
  16.   }
    + Q6 f" g; V5 B- i& l" j
  17. })6 e$ a% b# K  m1 x
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
& w" e4 A( {: r+ s* ]1 e! ~6 f
  1. <div id="app">* x9 o, u3 z3 f; C6 S: p) Y* H
  2.     <child message="hello!"></child>
    ; G' M. O& w- D
  3. </div>
    - w; t" Z6 S, M3 J! `2 c% }- J

  4. 8 ]  b; S& F7 k' m' S" {
  5. <script>
    ' U- X2 d0 u. G: i
  6. // 注册
    " r$ D6 H% f& H# u2 T2 E9 c+ h
  7. Vue.component('child', {
    $ ]9 n$ X% _8 v
  8.   // 声明 props7 R! r% a  z) U
  9.   props: ['message'],' G/ |- Y$ x" F" C
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    & q0 {9 W- I, c) |+ d* A* V  v. X- H* o
  11.   template: '<span>{{ message }}</span>'
    3 L2 |$ l$ B" ~+ K9 b5 J
  12. })7 [- r( @0 j7 I) W9 e- M
  13. // 创建根实例
    , w: S) B3 a; I
  14. new Vue({
    ' D' G2 D% O0 a. {# S/ u1 F5 {9 D) Z1 M
  15.   el: '#app'# @/ |6 R2 z4 f: \0 C
  16. })
    # p' x7 `- P, K/ F! c# ~
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例/ o+ k1 B5 {" Z" r* H1 a
  1. <div id="app">/ o' H! X1 J' _9 h5 ?; ?+ Z
  2.     <div>
    6 I: c3 m0 u6 V1 L
  3.       <input v-model="parentMsg">3 s% Z5 Q* U7 N- ^
  4.       <br>
    9 L1 K2 n: ^" q& N6 ]- Z
  5.       <child v-bind:message="parentMsg"></child>
    ( {! D2 n$ b4 R
  6.     </div>
    - D9 w  n  a3 P# [8 @9 s
  7. </div>1 s$ l( R, e" \/ R1 Q9 h

  8. * k. ^6 P3 K+ e+ I0 S& Q
  9. <script>
    0 Z( u1 Q% A8 J% {" R, R
  10. // 注册
    . W7 d1 ~3 D& ~: A- Z, ?9 o2 @6 n
  11. Vue.component('child', {; v, E8 [8 c) L, G7 p8 I7 Y
  12.   // 声明 props
    - Y( ?# |' _) A. B$ [6 o5 R
  13.   props: ['message'],4 t* D- A! V, z, O
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    - u: ?! o* v. b0 d
  15.   template: '<span>{{ message }}</span>'
    * D1 D" o% R2 \% ^
  16. })2 X4 @+ ]5 j2 k- K
  17. // 创建根实例
    + }) G' N) x! i( x5 k
  18. new Vue({: D1 n5 x1 `, @2 W8 I# @) R
  19.   el: '#app',+ [8 q4 J9 z) c# o$ O
  20.   data: {
    3 F  E+ k4 `" [$ k7 L
  21.     parentMsg: '父组件内容'
    5 l( G. ]9 L3 N, S( }
  22.   }4 J5 @1 r8 z, ], Y
  23. })
    2 O; b3 R7 O: X. q) ]& p
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例) Q: Y6 h# y, l+ g, o
  1. <div id="app">
    ) Q9 I' m" F/ A: b( ~& P
  2.     <ol>
    + _3 Z+ I3 A# Q/ @
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    " P  j  F  X  d! F6 O; G( [  {
  4.       </ol>& \1 [0 w  D$ K& i( h
  5. </div>
    7 }! X$ `. K4 m' k9 q$ r7 Y$ Y9 Q' Q

  6. . [$ a% B% j0 R% m+ t: E9 K, V
  7. <script>
    , Q7 C& @5 e& Q1 |' c+ g: @
  8. Vue.component('todo-item', {- G7 G7 P) ^% G- x8 k4 m  A
  9.   props: ['todo'],. O8 E, B2 |1 I& O- G
  10.   template: '<li>{{ todo.text }}</li>'- @5 @& d  p3 R1 E
  11. })
    ( X$ ]! [  b9 C4 x9 ~
  12. new Vue({
    5 W* r! G# h' m3 {7 D
  13.   el: '#app',
    6 T% i2 W) ?! f0 h" `
  14.   data: {- L4 n7 K' H* |9 {) s0 x5 a
  15.     sites: [
    ; g/ @6 i, l0 N7 s
  16.       { text: 'Runoob' },
    $ [/ r* l2 J. [' q; G
  17.       { text: 'Google' },3 K9 s  R, c: W' C: B& w& @
  18.       { text: 'Taobao' }
      L0 P$ E: |0 M* B" t2 ^
  19.     ]
    - A: S+ C1 l2 b! U+ w' A
  20.   }" p  H- h* g7 d5 T4 ^
  21. })
    " ~0 [# h. y5 o' y  t
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {
    9 L2 i& U- f, \# B" |; e
  2.   props: {
      d% l9 f0 o- t, R. r4 G- w
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)
    5 x8 u+ @3 \' Z  F3 D
  4.     propA: Number,4 J2 A& Z* f3 A7 Z& e3 }: q
  5.     // 多种类型
    1 o8 R. y$ P" o: @3 r' A
  6.     propB: [String, Number],& n/ F. D& J+ E0 r% i. r4 h
  7.     // 必传且是字符串
    % m3 A, z" A6 T% V) r! @- }
  8.     propC: {
    - Z# w$ q- R# t
  9.       type: String,
    + k- q2 X+ |' m; m
  10.       required: true4 }  S/ h" ?# h
  11.     },
    ) n2 P# ]  e6 r
  12.     // 数字,有默认值! Z! m6 p4 ]/ n- B# G  _! f7 i% q: m
  13.     propD: {7 |7 M5 A) r3 H; h
  14.       type: Number,$ k1 s) P% d* Z( _! j: h
  15.       default: 100
    9 q# N: z1 C) f% G
  16.     },
    . m# V4 _2 Y( u; H1 `& z! f
  17.     // 数组/对象的默认值应当由一个工厂函数返回  i* S% R8 Q, {% U/ y# Q
  18.     propE: {
    3 m7 u" a$ _6 g4 ?9 b2 p
  19.       type: Object,
    # N1 ?" G0 B* p! _$ h+ K
  20.       default: function () {
    2 s7 e7 T, f2 j* V' N
  21.         return { message: 'hello' }! O5 \$ Y8 t5 m- S5 U% X" u
  22.       }0 `/ x! _9 y; m. _
  23.     },
    1 ?( w9 \1 C' g9 W, |
  24.     // 自定义验证函数
    / i$ {2 r$ r/ P  e/ O5 T
  25.     propF: {
    ) V$ r6 b0 g* r3 h( u: A
  26.       validator: function (value) {
    9 c! k; _! o! l& B* U: V
  27.         return value > 10
    ' m5 e7 R& V; g) v, a5 F
  28.       }# N: u" }, e- o  a. H' {0 f( n$ n
  29.     }* m& n- O1 i5 T- C4 Z1 Z
  30.   }
    7 t# v, F! t: E* [1 G2 n$ p
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
+ o3 s( A1 s2 T# |) Y) D
  1. <div id="app">
    ! P- m& f1 r8 V( T
  2.     <div id="counter-event-example">
    - w) c& m5 y: k9 @4 [$ q) s
  3.       <p>{{ total }}</p>+ C: g3 h' K4 c* k. n. q0 R
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>
    : ?, u- k# \5 n  r! `7 |* y, ~; E
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>. k3 t3 [6 S& K  n7 p0 n' w
  6.     </div>
    # ?) p5 u9 e; ]8 U5 G
  7. </div>/ w5 c8 D8 V4 [0 M3 d+ q+ ?

  8. ' l$ X# v; U3 M
  9. <script>
    . t0 y& j8 b- o( G' @1 r
  10. Vue.component('button-counter', {! @* \4 h. x* `6 f# p5 k8 y
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    8 l$ ^" {) T. l4 M
  12.   data: function () {
    , u1 c" F# V: [: w
  13.     return {
    8 J  h+ A9 h5 m$ r$ r
  14.       counter: 0! v4 @* d$ P/ r
  15.     }
    ; h6 D5 i- e6 P! u2 U6 [8 D2 ]
  16.   },
    $ Y. d  i, S& \7 i9 C
  17.   methods: {8 @2 ]0 j& c' s; Z; X1 x9 |6 p
  18.     incrementHandler: function () {
    & E( d; u: J5 `" ?# j2 P( G0 g
  19.       this.counter += 1
    3 y  k. n7 X" W6 e
  20.       this.$emit('increment')  i2 V2 \# A+ n% G% c8 A8 ]
  21.     }
    - s" L8 R) I& Y& A
  22.   },
    6 w% N3 [' {# q' z4 `
  23. })  A4 q0 Y" p! s4 l! l4 w9 }
  24. new Vue({
    ) Y+ I$ a7 b/ H: V2 d" y" A. \
  25.   el: '#counter-event-example',
    ' [" t+ k" `' L8 U* @
  26.   data: {& s* x% l. C3 Q! a: z& j/ o
  27.     total: 0
    / c& Y2 V+ g8 ^6 d0 K) q. Q- z
  28.   },0 w9 @+ Q2 W3 S. I
  29.   methods: {. F' {7 w9 [: H* n. m' Y# ~
  30.     incrementTotal: function () {' F/ b- d/ \1 i7 w7 Z6 h" w8 E
  31.       this.total += 1
    ' t3 \0 h9 @/ K6 v5 s9 ?, k
  32.     }; b) P; A& S3 ]& ^, x- P
  33.   }$ a) e  [# j. H. P; F: d. N8 X
  34. })
    : M& [" F2 w  _3 d/ Z
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册' X: U, ?+ F0 j  V/ C: j
  2. Vue.component('child', {
    ) R$ p# R- M8 c' E3 |  _- f& p
  3.   // 声明 props
    $ r1 ], X5 ?' x& H5 u; \
  4.   props: ['message'],
    3 x, F( ^+ A% g6 c' U) Q  |
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用* x  `3 M. d) Q' n- t' r$ d
  6.   template: '<span>{{ message }}</span>'" o; \( A: v0 t6 Q$ c0 I
  7. })
    8 t$ v0 F) B( y6 L3 ~; b/ z! f
  8. // 创建根实例
    6 f- b3 }' m5 {
  9. new Vue({
    # ?3 V$ C' Y5 J( j
  10.   el: '#app',6 a; m$ L8 B6 ~4 h$ N7 N! ]
  11.   data:{, S/ F' L# T, s
  12.     message:"hello",
    % @: o) b% h+ D$ E- P7 x' t
  13.   }8 E  M+ q- `4 `  j8 ]7 u1 s& |& E
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {
    - Q0 U/ X; \" w( T
  2.     incrementHandler: function (v) {
    6 ^! J: [* k" K4 Q
  3.         if(v==1){
    2 _# x( {7 H9 p% {* v5 u
  4.             this.counter -= 1
    ! W& F, D3 ^7 |, M5 A
  5.             this.$emit('increment',[1])
    5 t3 i7 d) T0 R. J9 @
  6.         }else{/ R" Q: @+ [6 ^) u9 K& T4 C+ G
  7.             this.counter += 1
    8 A! l. o% E! Y$ Y' D
  8.             this.$emit('increment',[2])- H- \0 a3 j7 Y/ l6 ]2 f
  9.         }
    - a6 M, P$ W% h5 Z6 }
  10.     }
    ) z3 n0 ~( ]; O+ \
  11. }
复制代码
( s. _) m  k  H/ R2 S8 u

9 k! z& D& T( d' ~; `+ e' T, _8 ?




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