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,并使用它:
' a( u5 y3 E) v! O. {5 Y: {
  1. <div id="app">
    ! K% n' g3 F( m3 z9 Z) C
  2.     <runoob></runoob>
    5 p' U3 K: c- V5 Z8 Y0 b1 `
  3. </div>/ d" P; {1 Q3 Z

  4. - ]( O, a/ P  z8 r
  5. <script>
    / D3 Q$ f9 M1 Y
  6. // 注册$ u4 B, z$ Q( L' l5 \/ r* j+ s
  7. Vue.component('runoob', {% l% @. v' c, y: A3 T# \
  8.   template: '<h1>自定义组件!</h1>'& ?- `' p+ ]" m+ N$ M3 o& Y4 l
  9. })1 v) w0 A  M5 ^7 @0 x2 h9 \3 j: @' i, L7 H
  10. // 创建根实例8 ~7 q' r0 ^# n  V" e) @
  11. new Vue({; [# W& D* Q" J3 S5 Z! s6 O
  12.   el: '#app'8 ?" _" `& w6 R0 H+ S1 i4 M) e
  13. })* G' |6 C5 C! E) R
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:
# k/ T- h5 h. F7 ]* W4 f# Z
  1. <div id="app">
    & b4 Q+ a3 P) g# X+ }9 l& y6 e
  2.     <runoob></runoob>
    & f$ D# e7 n/ x# E
  3. </div>
    2 }& ]9 ?4 L& n& o  t
  4. ' Z, S( X: T$ q; J+ h& O4 F$ l" f; y
  5. <script>
    & i1 t& M7 y8 T0 S& W2 b
  6. var Child = {2 h1 A  o6 e: d! b! [- @# a
  7.   template: '<h1>自定义组件!</h1>'
    * e# b: A% s! S) u
  8. }
    ! l; Y6 q% n; w# u0 f9 y2 p

  9. - _/ C9 ?- w) N6 Z4 G. U
  10. // 创建根实例
    7 _( }# }9 j/ w- _' P& D
  11. new Vue({
    - v$ k! Q/ b; |3 x6 [, A
  12.   el: '#app',
    ! U. X) H0 V$ H
  13.   components: {
    ; E& n5 @1 V% I# O$ ]& `( g: l
  14.     // <runoob> 将只在父模板可用7 n* Z" U9 `3 D" B
  15.     'runoob': Child
    3 O6 E' h7 n' {0 m( N
  16.   }
    - R1 x; H, o! x
  17. })
    0 W- J2 o! Q0 K3 n. E. a  z
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例; W# L# w1 {  D0 O! J
  1. <div id="app">8 N. W! n: S+ e# p. ], ]
  2.     <child message="hello!"></child>5 r0 H0 j  r8 P; u* V, U7 |3 N: g
  3. </div>/ Y/ w# Z6 y" B' W0 \

  4. 8 ~; ?  Y+ P' t3 M- W8 e# A: ?: W
  5. <script>' n3 G. `& T" ~, N5 P0 Z- r4 n' C$ |
  6. // 注册
    % }5 N3 @3 h$ e
  7. Vue.component('child', {
    ( ?4 `# u4 F% y9 r7 V( O
  8.   // 声明 props
    0 x7 s3 N" X7 [( q" \2 ~
  9.   props: ['message'],
    , P8 @$ a8 k. D2 \% E
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    + K( t" i  B( w
  11.   template: '<span>{{ message }}</span>'1 u) x) u- n5 r
  12. })) ]- c8 T7 o1 e* B% V) }
  13. // 创建根实例
    % a9 F8 Y! D# |. _
  14. new Vue({; o0 o: M) \) b& ?# T+ Z
  15.   el: '#app'3 W/ Q# [' B% U" f1 l
  16. })+ K# D6 I( F- `! W
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例- O: L+ t0 q! L
  1. <div id="app">
      Q! l- s% Y# k( \" k0 b
  2.     <div>( U: J" E$ J# b/ a
  3.       <input v-model="parentMsg">! ?2 ]( b  u% A# {5 p& I' \
  4.       <br>- G6 n  W" I  ]0 J/ ~9 P1 ?. S
  5.       <child v-bind:message="parentMsg"></child>
    4 ]2 H  S: e. O, \" x* ~
  6.     </div>/ a3 _0 [2 d: e
  7. </div>
    0 L0 V4 }* W9 F8 a
  8. 6 H' I3 ~9 |: h( b
  9. <script>
    9 R* D- y5 L7 \) g
  10. // 注册
    0 N) d/ H# L; c# U( e$ D- M; S
  11. Vue.component('child', {' f9 g4 Y/ E% s2 P6 V# C0 C7 F/ Q
  12.   // 声明 props
    . j1 {+ ~: Z& [
  13.   props: ['message'],. N  z5 b/ x. U
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    ) l6 N7 D& t# x" j: v
  15.   template: '<span>{{ message }}</span>'
    " C; l" {0 P* [, ~& I$ l
  16. })2 d" R* e5 b) N8 k8 s' B9 y( C
  17. // 创建根实例
    & i0 A! V; l; v. G* @  `
  18. new Vue({
    ; f  C8 F( r3 \" V
  19.   el: '#app',
    " o6 V0 t$ _; m+ ^' x. {
  20.   data: {
    + N2 _# o3 z5 B' J4 ], {. I
  21.     parentMsg: '父组件内容'
    4 ?6 p6 F; G5 }/ ?
  22.   }
    5 ?0 c# `. M  k+ Y  U! w+ l' X
  23. })
    + m# o' E/ a+ Y! L& I/ t& z
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
; ]) |: f9 N0 m' T4 n
  1. <div id="app">/ e! U' h# j) h5 q1 {2 A* \! J+ D. x: x
  2.     <ol>* i" {0 {. u7 [0 S0 t' b
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>7 |  x( F* V! W1 G6 E' T
  4.       </ol>
    9 v7 R9 I* V( n7 S. x
  5. </div>
    , e4 j. s1 N5 ]$ c& |0 m1 n

  6. . Q0 d) k! O  E  _4 a$ M+ Y* G
  7. <script>! A7 B% o8 L& ~
  8. Vue.component('todo-item', {
    ; H- R  a6 x2 a) C/ M& u
  9.   props: ['todo'],
      m& x% q/ b0 D; N2 _, c0 _; w$ K
  10.   template: '<li>{{ todo.text }}</li>'
    - p0 _8 u" G. Q( F
  11. })7 ^9 u$ d% q2 ]3 Z$ s
  12. new Vue({. u2 N7 `4 ~2 I/ e* T
  13.   el: '#app',
    # X4 X2 p( }& W) R- n6 w
  14.   data: {6 @: }6 X  v8 ^- ~9 V0 \
  15.     sites: [) p4 {; s" x% n) v4 e
  16.       { text: 'Runoob' },+ h+ R. e' H! v, k$ R5 w
  17.       { text: 'Google' },2 p" m& M, n' [/ W  Y
  18.       { text: 'Taobao' }, h- d/ H$ q/ e
  19.     ]4 _6 i. U+ P! S- O/ _3 \2 s! m
  20.   }/ i& a! u& E3 e  R' Q
  21. })0 f5 B. f7 x% L/ A7 R) d
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {* y  i% t! U& x& \0 [! V
  2.   props: {
    ! X  D+ g/ W9 q% }: s- }. W- a
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)* F0 \- L; P4 D" r$ v( S1 N
  4.     propA: Number,
    - o1 ^( w3 w2 `& L) g
  5.     // 多种类型, |  b1 Q# d, W! @, P, _
  6.     propB: [String, Number],& T+ C3 D4 y6 Y8 `  O
  7.     // 必传且是字符串5 F' O3 V7 R6 J8 h/ s
  8.     propC: {, H& d- i4 m! H2 Y: d; h& M2 W
  9.       type: String,. d7 N* |, O  {
  10.       required: true
    7 G% t; r- N! ^: I
  11.     },/ A! F( x" o$ F5 Y$ `
  12.     // 数字,有默认值
    + w: r" [8 u8 d4 D' E2 }% n
  13.     propD: {2 r/ w. b7 s3 G# L7 Z
  14.       type: Number,
    6 D& @+ ^: G/ V0 @
  15.       default: 100
    ! a+ e# w/ a' z& J* \0 ~
  16.     },
      F% l; k( h) y& [& Y" K+ a: t
  17.     // 数组/对象的默认值应当由一个工厂函数返回( I4 `6 \5 i. s, c- [) g1 R% u
  18.     propE: {& l6 e. W8 q/ j: g
  19.       type: Object,
    * k" U+ Q& J5 q; ?
  20.       default: function () {
    & e1 t7 R+ {+ l
  21.         return { message: 'hello' }' y9 t4 p% X: f
  22.       }% O( c* e' s" T6 u: d( I  }9 T
  23.     },
    : r6 w1 R. }8 A+ ]4 X
  24.     // 自定义验证函数$ p1 b0 C2 I4 g& p! K: }' E& ]
  25.     propF: {- w* g" `- z9 k/ ^
  26.       validator: function (value) {$ W2 f3 c4 C- b1 l  T
  27.         return value > 10$ t. C1 {9 O9 Q" `( J; X9 @8 {
  28.       }
    % b3 w) W9 {# I+ S
  29.     }
    3 M1 z3 m7 F0 D4 ~% c9 |
  30.   }/ T' f  O$ l: J; h
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
  B4 S, u4 t! p, h" z  M# a
  1. <div id="app">
    * m0 A( [$ W) c, ^: O+ R
  2.     <div id="counter-event-example">
    0 w2 I; w* Y6 G/ F* Q
  3.       <p>{{ total }}</p>
      f) c" _5 p9 |
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>8 l, D: c7 I1 `: Y
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>+ L1 r, W% ^4 ~! }: J+ u* ^
  6.     </div>' x" |/ K; _9 K& u, E
  7. </div>
    5 e- V, _; ?6 _

  8. : r: e+ v  O* Y" ~* [
  9. <script>
    & {8 ~7 b: L* h# t( `* l% i
  10. Vue.component('button-counter', {
    & a% T0 g1 e# q( z" u5 [) l2 z
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    3 W( a! G" Z4 A( P8 B' T
  12.   data: function () {" t4 g% G3 Y/ Y- e; J7 X9 X
  13.     return {: p# H# Y1 k) E
  14.       counter: 0& ], {* e3 ]  @7 s8 n# T
  15.     }
    / p3 b! D' u! f) Z
  16.   },
    3 H' p6 j; ~. Y7 C& l$ ^; I2 K
  17.   methods: {
    * o3 }: q! T) H  \! D
  18.     incrementHandler: function () {( t; |* P# P7 i
  19.       this.counter += 1; }# ?* I. y/ ?' F: D
  20.       this.$emit('increment')
    4 U+ j+ T( s+ E2 C9 R! @' ?: b
  21.     }
      }  \; U  `/ f( h, ^, b& d  S
  22.   },' \" Z: l. J- m; w
  23. })6 r* Y8 A/ Z. D5 C
  24. new Vue({  }3 A; u; y7 G, R' r6 Y
  25.   el: '#counter-event-example',
    5 N8 Q0 a  z  m0 [0 G" B* U9 P! G
  26.   data: {* P! e& c' K$ v
  27.     total: 0
    ) ~7 @8 L/ [& n5 _
  28.   },
    8 X# o2 w  o5 V+ \' J$ W
  29.   methods: {* K3 e% g  S2 x1 t: N( y* ]3 m
  30.     incrementTotal: function () {9 C. F9 q1 Y) ]$ j8 b
  31.       this.total += 1
    & j0 [% {+ m9 J8 P& E: _
  32.     }: Z! ?  Z: t4 p9 U) C
  33.   }& V& s* p; m% P, ?/ s0 i, K+ {
  34. })4 d$ g5 D5 o6 J- j
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册3 w( R3 h" l  ~7 U' C$ w- D
  2. Vue.component('child', {* p- Q4 F9 n0 B+ l' [) M
  3.   // 声明 props1 m' u/ p8 j6 y: q
  4.   props: ['message'],
    * w3 Y3 ^9 v: ^/ n7 ?& d- B
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用9 m; A0 b2 k; n) j
  6.   template: '<span>{{ message }}</span>'6 y6 @0 L* ]3 |# a  y2 U. b
  7. })
    # O, l: e; `/ d; j6 ~& r
  8. // 创建根实例5 S! R) Y1 s; _2 w% r: X4 d* p* o
  9. new Vue({
    ( T$ y' P* W$ t8 ]! `1 d
  10.   el: '#app',
    , O3 A& m" ]* ]4 v! f
  11.   data:{
    # K: B5 P/ ^% u) P) M2 k: X' `7 F
  12.     message:"hello",
    2 Q! a9 g6 J3 l+ `; r2 r1 F
  13.   }- z% z/ _) W; z- w% }% A& h
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {$ }0 X% C$ f$ c9 }  t3 ?& I1 b
  2.     incrementHandler: function (v) {. n! O) p! k4 u0 n' o3 `- v" W5 Z
  3.         if(v==1){
    : V  N( ~8 ^- j. E
  4.             this.counter -= 1
    3 _0 p. I0 v8 u& I3 n" l$ G
  5.             this.$emit('increment',[1])
    5 H0 V. v. E" L) H9 u! _. h
  6.         }else{' j. u: m+ `" x
  7.             this.counter += 1
    + M3 [) b+ y- _5 H1 l
  8.             this.$emit('increment',[2])
    * }+ H! O4 J7 p# S: Z
  9.         }  I1 v- Q6 l+ x5 N' c. V5 ^
  10.     }. j+ f1 Y6 {0 o/ q2 n* p4 Q% q
  11. }
复制代码
3 O' U, s" f+ T( [, s6 S8 R2 i
( W+ p8 y: v+ l& r2 ~- ^+ \, X  ^. h





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