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,并使用它:

  I" N0 X. R( V; ^" I
  1. <div id="app">
    . b3 s+ C  ~) T' f
  2.     <runoob></runoob>4 J6 `5 H) ^% _4 r
  3. </div>2 v4 y" C1 H! q( ~$ W  G7 _7 Y

  4. % E1 p, ]6 K5 Q0 M  R; Z
  5. <script>: x1 D  h- @+ w8 E4 U0 y1 v6 p
  6. // 注册. T+ Q2 \7 R/ J( o5 m
  7. Vue.component('runoob', {( i; z" _8 B% I# V/ x+ k" ]9 R
  8.   template: '<h1>自定义组件!</h1>'9 s/ q& Q, F$ I! |/ x2 n# |5 `
  9. })
    7 P  `: B: o$ U9 I
  10. // 创建根实例3 L8 t  A2 b" ?1 M
  11. new Vue({
    3 b6 A, B+ @/ c: P
  12.   el: '#app'* W6 F& ^! f0 ]8 S" w
  13. })
    / o9 R2 |* T& ~( N; G( E5 K5 n+ [
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:

: P' j: z' C$ F' R) |. p0 i8 u
  1. <div id="app">) H( V- D- R, d1 o1 C
  2.     <runoob></runoob>, B9 m, n3 z, }
  3. </div>* W2 k6 w; q; Y) p

  4. 6 K. ?" ~: @, w2 ^" T! O6 h
  5. <script>0 C$ [+ K: O: Z$ v: ^& W# f
  6. var Child = {
    ) V8 v0 d, t- u& ?3 l
  7.   template: '<h1>自定义组件!</h1>'
    2 w. H4 h; A3 K' }  M+ i7 K# t
  8. }
    0 \. \% Y* l2 n+ P: Q. J
  9. " @2 W" X. U# K. |; }/ i, B
  10. // 创建根实例  ^2 x! }8 x0 f% g! g
  11. new Vue({
    1 E! S) u# ?* I0 t5 W2 X; b' {
  12.   el: '#app',
    4 `. L. U9 L6 E; _6 @( e* \
  13.   components: {
    * i0 J  @* b: X/ O: J
  14.     // <runoob> 将只在父模板可用
    / ]+ `& ^) L  q* B  X; A& r9 Z! L
  15.     'runoob': Child5 w) B% K& E% q# h0 O8 h
  16.   }' U% |1 U4 a8 a* ?
  17. })
    $ f$ z' J2 \" P  A! e9 p6 }* I
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
# ^8 W3 D2 I0 H6 E1 f; Q3 {" G
  1. <div id="app">
    5 ?& j" d% X  ~: Y
  2.     <child message="hello!"></child>6 w- e* o* Q; j+ ?( p- u
  3. </div>; \" T% i* n; Y3 [& n7 W
  4. ! s5 X& Q2 f! @2 ?  f
  5. <script>
    + b9 u4 S  r$ l! n/ x% z1 [
  6. // 注册
    / h# M+ k1 w% b. o1 W1 K
  7. Vue.component('child', {
    ! G- a9 p" Q% `, Z
  8.   // 声明 props/ `7 z1 U. V0 }3 X5 ^
  9.   props: ['message'],
    * g- {! b  L2 i* k9 I) P! m/ T  N  T
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    . E2 I! m3 I4 N# m- p6 D" {
  11.   template: '<span>{{ message }}</span>'
    2 y# Y# {8 j% @( q& E; l* @
  12. })& O+ d, K% E) H3 G& X6 X& D
  13. // 创建根实例( F( W' O0 A4 }. J3 m5 P, r6 C# Y
  14. new Vue({9 i2 D1 Y4 F' b3 G5 A/ b9 [7 u
  15.   el: '#app') B( B7 _% {& \1 D5 \, u
  16. })
    + k( R$ l* F# Z  u9 m0 u# g
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例! T) \, {# S9 J
  1. <div id="app">
    ; c& \2 K% Q7 w& ~4 S, t3 c) \6 a
  2.     <div>
    & y; ^* K4 U( k; Q/ [# B, o' j
  3.       <input v-model="parentMsg">$ S( n* p- H2 b8 p  c* ], A
  4.       <br>
    ! u" O* k, _& p! R: y
  5.       <child v-bind:message="parentMsg"></child>; g8 A) s" a  {2 j9 M
  6.     </div>0 M0 F" N) o2 k& c# \9 ^
  7. </div>9 `- E5 h9 b, o- \& P
  8. . A) g8 C: p5 o6 q
  9. <script>
    , y+ R$ W9 K1 H  y0 }) p
  10. // 注册; O! P; K& R1 L) z3 u1 ]: p
  11. Vue.component('child', {
    ' b' H. U: V! W# [* B; T  W8 W& J
  12.   // 声明 props
      i0 ^$ ]1 C4 b5 b) A3 X
  13.   props: ['message'],, c+ K) Y  g  g' w0 c
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    6 M& L5 D6 L& Y5 u- M. @
  15.   template: '<span>{{ message }}</span>': D- H( K; t/ e. Z6 r& a6 v) I" R
  16. })
    6 s5 u" f: n6 K$ j0 g* k/ K
  17. // 创建根实例
    & D2 p% ?9 @- P
  18. new Vue({5 O9 b: P! J+ U8 K- v5 Z
  19.   el: '#app',
    4 V1 I1 h2 r4 G3 Z- W' G
  20.   data: {
      |' d/ V4 f. V6 }
  21.     parentMsg: '父组件内容'
    3 s; Y: o1 R; f; }! _) ^$ u
  22.   }. X% J7 F" X! Y. \2 P5 J1 X
  23. })7 a! e+ G3 v. q  L3 c& d9 \
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
3 y6 w; N0 I& ^2 Y) v9 [8 [
  1. <div id="app">% Q( t  t$ C8 G7 q  j' ]
  2.     <ol>1 U# J/ p) V# H' x) A3 J8 W
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    ) I- L% `! u2 o: }3 a
  4.       </ol>2 l7 w$ J$ b/ s) M% R6 P' k) B
  5. </div>( Q' h  g# ^$ _& y# D. ~3 `

  6. + g# W, p& Y9 t# t8 ]1 ~! q
  7. <script>* U& a! C- |# i0 Q; k6 t
  8. Vue.component('todo-item', {# i8 U0 }; J5 ^0 y" g
  9.   props: ['todo'],
    3 o; x6 k1 V  [
  10.   template: '<li>{{ todo.text }}</li>'
    - }; V$ r- x# }8 h
  11. })
    & [: d+ {2 X, i: h" f" O
  12. new Vue({
    7 J2 `' B$ a' [# \2 o3 J, {  N0 B
  13.   el: '#app',
    " d  F4 X; P3 J
  14.   data: {
    0 w9 n# z8 `- s3 r0 f8 e
  15.     sites: [
    + G& U" o! m& @$ [$ i. V
  16.       { text: 'Runoob' },
    + b/ ]0 t/ C1 k+ K7 G7 F2 Y: h0 r3 z
  17.       { text: 'Google' },
    7 T; [1 o7 }+ ]
  18.       { text: 'Taobao' }7 G& Q; b, S0 p# D5 T) ~
  19.     ]
    + r, t! @# m& p6 `8 `* n- s2 t
  20.   }
    ( O% [6 Y/ s, g6 c
  21. })
    4 m& P" \& ^& W% w7 [- Z
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {4 Z3 n# ]6 R7 n
  2.   props: {
    + z! \* D3 Q% i% X; d: a" I( ]
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)8 @- a4 y1 j8 g4 |$ r5 R1 ]
  4.     propA: Number,
    7 o& E  _/ r( t
  5.     // 多种类型' G$ v: b2 t5 T. u
  6.     propB: [String, Number],9 w9 [3 V; @  o: O/ p* n" C  r6 a
  7.     // 必传且是字符串
    , B/ q% y% k+ h2 n/ \9 f$ z) P" B
  8.     propC: {
    - g9 q6 X0 v$ _( o6 C
  9.       type: String,
    6 Q6 B+ s* t  J! @3 w
  10.       required: true' ~; O9 I, }& P6 r  h5 A5 s+ D* q
  11.     },
    0 b' O  o: \& K/ K0 f7 }1 Q* A
  12.     // 数字,有默认值
    3 d$ Y3 k0 z0 L& L; y
  13.     propD: {
    , E. s4 [% q) s5 k6 j. G
  14.       type: Number,
    + \; O1 r' \. m6 H9 c/ m! K
  15.       default: 100
    - H4 P* t3 \2 v0 v" @
  16.     },
    ; b" @1 x/ g" r9 c7 n# s/ K
  17.     // 数组/对象的默认值应当由一个工厂函数返回
    & _3 n& n& |+ A& X
  18.     propE: {* O+ m3 W, ~* @& x/ B
  19.       type: Object,5 x; ]) `  H, f5 c, F
  20.       default: function () {$ E6 \6 f3 \, H0 B6 A) _7 d1 n; o
  21.         return { message: 'hello' }6 K$ E, z6 A# s9 H1 l! A, s
  22.       }' L2 V* Z6 o& M. O& w1 ^- k
  23.     },
    + t" M: J/ s$ d3 x9 o% A7 [
  24.     // 自定义验证函数
    & a  _; a+ p! `) n, h/ ?1 M
  25.     propF: {9 k8 Z/ b, M5 [- z
  26.       validator: function (value) {
    7 }0 b5 A' n- l+ M* J. V
  27.         return value > 10
    1 I7 Z0 J7 C8 V# {6 T- F6 B
  28.       }! o0 ]* v1 c" F% p
  29.     }, ~# b8 q" `; a9 a! ~
  30.   }
    . A" v9 k, o: x1 q
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
# I% e9 d3 m' ?% C
  1. <div id="app">
    . b% U0 ~9 Z. W( d$ b: n
  2.     <div id="counter-event-example">
    ! [6 B7 t: P- P
  3.       <p>{{ total }}</p>
    ; t( I. `) U4 Y2 q5 x& _3 J5 L& s
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>
    2 ~" }8 E- L# r+ K2 h
  5.       <button-counter v-on:increment="incrementTotal"></button-counter># j7 u/ V, g0 |# R! x
  6.     </div>
    0 W2 c. N4 r3 Z+ |$ y+ ]% c
  7. </div>
    ( D3 T4 m7 p1 ^6 Y1 a

  8. : P: P1 e) }) S7 R: `) k3 L2 w
  9. <script>
    ) G3 \# u; O8 ?4 n' Z% B& E" F
  10. Vue.component('button-counter', {7 D" D4 Q# \! g' H
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    % P' S3 }0 Z4 `- E( a5 T' s. `
  12.   data: function () {
    ! O1 M- s1 P+ a3 t# D, s# v) O7 `% X
  13.     return {
    7 G5 m# w& a: @  c$ u
  14.       counter: 04 f. U- ^+ }. g  o( @; P
  15.     }
    / x. H% d" m  o. C3 @
  16.   },' {3 I) k, e+ Y9 i: }9 D. I! j2 r9 ^
  17.   methods: {" |9 t" ~9 d& t& W6 z$ Z
  18.     incrementHandler: function () {$ Z) w: i; f4 R& G+ j0 D- p" P
  19.       this.counter += 1# b4 n7 ~9 s* S% x* N
  20.       this.$emit('increment')
    + _8 f+ X* b5 N" F3 t# R* t; }
  21.     }; k7 ?% j. i. |7 C) O/ {
  22.   },
    ) E5 a3 ?& [; c" Q) ^6 G
  23. })/ s( ^8 J* B) J) V/ c/ K
  24. new Vue({$ f' `6 _& t  D4 u
  25.   el: '#counter-event-example',* o2 T5 B( h" l- t
  26.   data: {
    8 B/ x5 w! ?) A3 T7 h6 O/ ~1 k
  27.     total: 07 C. z4 Q4 R( V* d+ i0 K' k
  28.   },0 L4 r' i$ V* _
  29.   methods: {
    # e: Q$ o7 C3 u
  30.     incrementTotal: function () {
    ! }5 n. `3 V* S3 D) J
  31.       this.total += 1
    ) y$ g' x) c6 o- V9 P' H. m2 E% O
  32.     }
    0 d4 A* v4 v# m( R
  33.   }& n$ r+ R$ ~9 `" b# [6 `0 }7 m% A
  34. })
    & F7 i$ {+ P% {7 P, U7 R. J
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册! m+ o' O, s7 z! L" f8 _5 _
  2. Vue.component('child', {, {: j* A8 N' S" e$ v
  3.   // 声明 props) r! O/ Y' A+ ?. ^) N
  4.   props: ['message'],
    5 \( M7 R; A4 v3 E
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用9 Q+ P1 |3 V1 w- ?% @" g' {& ]
  6.   template: '<span>{{ message }}</span>'8 w- k% c# _/ p4 |1 P
  7. })5 B$ M/ y2 h/ ]; x' }
  8. // 创建根实例1 i9 y0 W+ Z5 D- b4 p3 w9 Y
  9. new Vue({  U- n1 J& a" L' i. M1 X
  10.   el: '#app',, Q! \3 S7 c8 J$ S# @7 \2 y4 C& }
  11.   data:{! [8 B; f; `% J5 F! w
  12.     message:"hello",; Z; C& Y0 x' n; a
  13.   }1 n2 Q" n+ N& J8 W, b7 K
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {
    . l; C+ @# C  i
  2.     incrementHandler: function (v) {7 i$ Y* d, O$ _, N% m/ {! A3 u) x
  3.         if(v==1){( ^* a$ z1 E' }/ I4 A2 P
  4.             this.counter -= 1* ?5 Y2 A2 {) s
  5.             this.$emit('increment',[1])
    ' v$ b3 N: a$ b2 E, s( B
  6.         }else{
    4 O2 [1 G9 S. l9 ^* b' p
  7.             this.counter += 1  X( U2 }% ]+ W) ~, W$ k/ R
  8.             this.$emit('increment',[2]), B  d  L/ N  P
  9.         }$ Y/ k. W+ I! m
  10.     }+ R: ?& K7 ~* ]. ?. i+ {
  11. }
复制代码

, a4 d  E5 }  d3 f9 l. ?: f- r) q+ L3 I/ b$ Y, C





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