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,并使用它:
4 c* N, |2 D  Q' D
  1. <div id="app">: ^7 O: C% l9 W$ R( \
  2.     <runoob></runoob>
    & Q! j& `# H3 q3 P
  3. </div>. ?, u7 F# \- ^. v; B
  4. ' ]) p; y6 y% |( R! }
  5. <script>
    % O1 z" g6 P' F4 _
  6. // 注册
    ; E- Q( d& T( B$ B
  7. Vue.component('runoob', {
    1 W" X' N4 Z, r8 f
  8.   template: '<h1>自定义组件!</h1>'% y" `' K- H' W8 k
  9. })( w; X+ u1 I, z, N
  10. // 创建根实例
    + A2 \/ P% x" v  `4 ]
  11. new Vue({8 m3 ?- Y$ \) ~! D' p5 g+ t+ ^# S
  12.   el: '#app'
    / x" g5 B0 E3 d" s4 V
  13. })
    # Q, b( C1 y. t& A! j
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:

0 J7 M+ v# a+ z- A+ p" D& e
  1. <div id="app">
    * [8 [1 B2 G# c
  2.     <runoob></runoob># q$ p4 \6 n4 `7 T9 H
  3. </div>
    $ x9 |; X( U, c0 O
  4. + `1 d- N$ L+ I  q, G
  5. <script>2 U( F( W: |8 R& ]2 r; S6 k
  6. var Child = {& {. g8 A  {5 h! y: S, e% s
  7.   template: '<h1>自定义组件!</h1>'
    / M  F1 i. U2 o  B0 w% B
  8. }" `- j" \1 e6 E& E% H

  9.   |1 L9 p  U- g
  10. // 创建根实例
    3 Q1 s! q0 n" n$ r' P
  11. new Vue({
    , h# ~) A* ~1 }6 S  t% Q
  12.   el: '#app',
    2 h+ B# V3 ~( V- ~% T
  13.   components: {$ U, F6 Z+ v' ^9 P; q
  14.     // <runoob> 将只在父模板可用7 d0 u  F: U1 a( [7 ^# E8 _
  15.     'runoob': Child7 @( B$ z- O: f
  16.   }
    $ Z% P( Y9 Y8 I
  17. })
    + L3 R. j8 o: U2 j4 K6 L
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
4 m" m- C+ ?9 Z6 S! M0 S
  1. <div id="app">" h2 q3 z# m! b
  2.     <child message="hello!"></child>
    ; h: E7 s8 q* c" y8 ^; @
  3. </div>
    3 H3 t. g5 o0 K4 Y2 L$ Y! z

  4. + p' J5 T* ~# S$ Q
  5. <script>
    0 n2 Z) O& W$ x" M3 i
  6. // 注册3 ~! z9 Q: Z7 |0 M8 F) |
  7. Vue.component('child', {! M; Z# p% g& m& Y
  8.   // 声明 props3 \) }$ M/ {8 p* N2 I" L
  9.   props: ['message'],
    $ t9 C+ g2 {7 z/ S. y3 p) q1 h
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用) u/ I2 }. Y1 a* ]9 L; d/ v
  11.   template: '<span>{{ message }}</span>'9 l# o9 b9 p( v8 K9 L
  12. })* w! b+ r+ P/ {& p" R2 W( a
  13. // 创建根实例
    / E/ w* r$ n! }* i4 t4 _
  14. new Vue({) Q6 M/ k8 ^0 f2 @
  15.   el: '#app'
    % ]  m, W" ]; b. c& I
  16. })
    8 C( ~/ c  J( j. S+ j. q0 c
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
( A6 i+ I6 c% M. `9 u3 }  `
  1. <div id="app">" e: w& y+ D3 p; N7 f5 s
  2.     <div>/ l! F# [) C( T* `# n+ {
  3.       <input v-model="parentMsg">
    3 ^- `, Q; v$ j4 r8 U
  4.       <br>
    ) x, T7 J8 N  Z( {  t% k
  5.       <child v-bind:message="parentMsg"></child>
    * `" V9 b) g' t' C3 o
  6.     </div>3 P& k/ {4 j2 O, ]$ l. ?  b
  7. </div>; B! d. x' T7 }3 ?
  8. ) j$ i0 y$ R) ]/ c: p1 A' S
  9. <script>
    1 L1 |' s: k3 O1 Y) {. @
  10. // 注册& Q; b6 T; T, J! y
  11. Vue.component('child', {
    . G% Z6 e  V  ?5 N! y$ h, H% Y
  12.   // 声明 props
    ) t  u4 C3 o. V
  13.   props: ['message'],) B% O6 j& t0 N/ ^
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    " ?2 W+ [* g0 N  u2 f6 P8 M
  15.   template: '<span>{{ message }}</span>'
    " _' C( \5 z4 t. b6 |
  16. })% Q9 d& A0 j6 {! m1 W
  17. // 创建根实例8 Q, ^! f6 C' D# X  `
  18. new Vue({
    # y+ j! m- v6 {( K+ Q2 |
  19.   el: '#app',7 A5 t0 w/ e! V, T$ `# V
  20.   data: {
      F2 S  \& [4 c$ K! J
  21.     parentMsg: '父组件内容'4 s( F" i% m# G, R
  22.   }
    ' p$ J' C7 Z& l
  23. })! @' c' t- w4 n! o  h1 a
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例* Z6 J/ M3 r7 Z) o5 c
  1. <div id="app">( v0 M8 c7 l4 v: V* w
  2.     <ol>
    ' q; O6 j: x. K# X3 f
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    ' ]4 i( F# k/ T4 ^4 c; F: D9 E
  4.       </ol>
      _$ P% ^! ~' d6 \& K# K
  5. </div>  s. \" H: q6 _" x2 \4 X
  6. - F! P  h: Z6 r4 C* \# ]
  7. <script>
    1 {0 V0 `7 d3 m* Y  t
  8. Vue.component('todo-item', {& e$ n% s4 N! X  T6 B
  9.   props: ['todo'],* B- t! ?- c, _# g  P
  10.   template: '<li>{{ todo.text }}</li>'
      `: a' w* z. l# j$ p( i
  11. })
    , K* i( R% T( H, Y% P1 n
  12. new Vue({
      e, B9 F4 F( k% h9 }
  13.   el: '#app',6 z! O7 I6 R  ~0 M! d: C* f4 ~/ n
  14.   data: {; Q! m# u2 j8 [2 F8 X6 w" e5 ?
  15.     sites: [* `, Q2 i' l; q# W" {; w
  16.       { text: 'Runoob' },! w7 b& v: R* e
  17.       { text: 'Google' },
    ; l' K# P6 H9 P& w& r1 l# M. O
  18.       { text: 'Taobao' }
    8 p. g, j! y( G% l/ A6 P
  19.     ]
      F0 q0 {; J( \3 a& x- O' C# K
  20.   }- D  _- O) u1 N& ]8 z" Q
  21. })2 I& }2 O3 b' |  R% I; ^/ I
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {
    $ v3 ]; ]; _% s/ I% H
  2.   props: {. \  B. c2 |, i0 T- X! h
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)  Z2 [' `  y6 S# x/ v
  4.     propA: Number,7 j2 \+ Z4 b) F& K& {
  5.     // 多种类型% M& |& @( o9 {  Y* j
  6.     propB: [String, Number],& h% r! o( Q2 d- ]" ~
  7.     // 必传且是字符串! S6 ~, m; l7 W8 Q; _# L$ _9 w9 d
  8.     propC: {- L- b$ Q) l8 |
  9.       type: String,
    8 R/ H" Z6 D1 }8 y8 \- n
  10.       required: true5 c, E8 c% g# g/ f3 y
  11.     },
    " l* o$ k* N4 F3 Z  d" K
  12.     // 数字,有默认值+ i! X: P7 m' g6 n
  13.     propD: {
    5 J& P" \4 `+ ]5 I" ~3 y
  14.       type: Number,
    ! w: `  \# E+ p" d$ \
  15.       default: 1003 t% ^3 T5 ~( Z! s; B/ t
  16.     },
    - x- [( U% a8 u# U
  17.     // 数组/对象的默认值应当由一个工厂函数返回1 d% ]; ]9 [( q* Q/ `5 S& |1 }' _
  18.     propE: {
    7 f! c0 Y0 I; e  }6 \) r) b
  19.       type: Object,
    ' ^3 [/ c" K" I8 l
  20.       default: function () {* q, r: P9 O+ B$ a& {) e$ T
  21.         return { message: 'hello' }5 t* M$ W3 E' b  [. v- r  Z
  22.       }$ U- i8 f& k! m
  23.     },, |0 w: O$ Q4 W& k% F
  24.     // 自定义验证函数
    7 o; f( w4 G/ ?% \+ r7 `8 Z
  25.     propF: {
    # ?2 N$ s4 V. X$ M1 d* q8 y- V
  26.       validator: function (value) {: \' Q8 o* M, l5 W, ]( q; e. S/ R  W
  27.         return value > 10% V5 A/ h! E" L
  28.       }
    . l& f' m" `7 G# g4 ~
  29.     }
    8 ?1 E% o, [5 d3 i
  30.   }" `; n. s& f0 U6 e
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例, e3 y6 {# J% `, _; l
  1. <div id="app">: c7 m# p$ M) S9 b0 ?9 n& c. R
  2.     <div id="counter-event-example">
    . S: Y0 g! A( u3 B! s% z3 j
  3.       <p>{{ total }}</p>1 i* K( V* _# z+ W
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>3 D/ l/ P$ p, }" r. u4 ]
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>
      i2 E% U( c! B
  6.     </div>, x1 g/ ], I; w) {4 C: q& L
  7. </div>
    0 e7 X. Q5 N" g1 J8 L; ]
  8. ( v. g' U: ^2 h( G  t
  9. <script>: W: o: Q- Y2 p* F9 D/ _: s0 @
  10. Vue.component('button-counter', {
    8 n9 }/ c6 Z8 s3 ^
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',6 z) P$ i* ~" I2 W; G
  12.   data: function () {
    . m( z  }1 @9 a
  13.     return {0 |7 [1 Y7 L  e/ J
  14.       counter: 0
    / a- k/ B9 K1 ]* H5 k
  15.     }
    ' Z' B9 S  r2 P5 Q' D$ J$ \, u
  16.   },2 X9 k6 r% j  g) M
  17.   methods: {
    : Y% X1 ~+ }: j+ [5 }
  18.     incrementHandler: function () {
    - R( i" T4 |9 {6 A
  19.       this.counter += 1
    : Y! O6 T: \% u- F/ I
  20.       this.$emit('increment'). ]9 l" F. K" n3 x
  21.     }; ~" l; I5 L/ x+ `: e7 B* M, N
  22.   },
    ' K; p; p) A  j3 D8 |$ \$ a3 _
  23. })3 e9 d! ^3 @: w2 {
  24. new Vue({
    ' e3 r: d) G: `: G# Q+ Z  E6 w
  25.   el: '#counter-event-example',- B4 k% c: D2 q( w
  26.   data: {! K& }* x4 B. q/ K
  27.     total: 0
    ' h- O3 G) M& w# Z6 p
  28.   },
    : o; E. y" X- c) T/ C4 `& n
  29.   methods: {
    0 O5 j* j4 ~. z( d
  30.     incrementTotal: function () {
    $ p) a% U5 w8 p; q
  31.       this.total += 1. c2 y2 _) X' H: Q
  32.     }
    4 B$ n7 @: E" f/ k6 |
  33.   }
    4 y! A; \; X1 G% H% X& ]
  34. })) a& i- Y0 k& M+ \
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册$ W% F1 B' e# O* C
  2. Vue.component('child', {
    * ]) y2 }. ]0 P
  3.   // 声明 props
    % I8 T6 k) J7 z1 n0 U% k
  4.   props: ['message'],% P4 n, s0 N3 k* y. @8 V
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用0 V: ?+ k6 {, z* V& c4 q4 H
  6.   template: '<span>{{ message }}</span>'% Q" `+ W) U/ K; X3 K
  7. })
    $ p1 M2 ^( v& r
  8. // 创建根实例
    1 o6 Q  t/ y$ ~3 q2 d$ F- p
  9. new Vue({" E! y# [+ _$ I; f3 D3 l
  10.   el: '#app',/ Y6 F- r5 n/ E/ |, j
  11.   data:{
    & @$ b4 k0 D) t3 U
  12.     message:"hello",
    ! r5 W* @3 P) \2 `* ~* Y3 `
  13.   }8 }1 G5 l( R6 v* C8 c' q' ]) n
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {
    5 z+ h! W3 @' m+ X
  2.     incrementHandler: function (v) {
    + A6 C! I+ I+ m4 K) [
  3.         if(v==1){
    & x5 Z. Y( c9 Q: ]1 y; ]
  4.             this.counter -= 1' E3 p! [: m- O( {0 _
  5.             this.$emit('increment',[1])
    8 n- Y( q" n( u0 g
  6.         }else{+ e+ @/ f2 L% U0 w; P
  7.             this.counter += 1
    5 A& |' C8 u8 Z0 |
  8.             this.$emit('increment',[2])
    & _" k5 R8 c$ X4 k
  9.         }
    ; r4 P  X7 s+ m3 }' S) `
  10.     }
    $ K5 {4 d4 l: }7 ]8 U1 t  R. O* Q8 _
  11. }
复制代码

  |0 f+ W5 K4 q5 X5 w; i& O
  I  @0 m" z/ g0 E, a8 Z" a' ?1 R( w




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