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,并使用它:
- X& N2 T2 i. k9 M; d, g; `- H
  1. <div id="app">; G" L* S: F5 O! }3 E- n1 w, M
  2.     <runoob></runoob>' k* k4 u3 m  \9 n
  3. </div>
    1 ?2 @# ~; d7 Z; B$ g& F/ O
  4. % D. s9 M" m, E5 z! f1 g
  5. <script>
    0 @4 \$ e' u4 j
  6. // 注册  i9 V$ o) c' W
  7. Vue.component('runoob', {
    + M' T* C- ^' r9 k4 y' K
  8.   template: '<h1>自定义组件!</h1>'
      U* i. K! F5 m& T/ z
  9. })
    6 d5 t/ \$ {) _# Z3 G6 k( `
  10. // 创建根实例: d2 @' J8 T5 N- Z$ [6 r) }
  11. new Vue({
    / c' ?& t3 S) @& F0 i0 e* \( p& u
  12.   el: '#app'0 B( T+ h: [) u2 u9 l0 d& {: P
  13. })
    / z/ b) s9 V9 ], D$ E: ~
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:

) c  \" l* A. v8 m" G, F
  1. <div id="app">
    ' L& d* b4 Y# S  v
  2.     <runoob></runoob>
    / e- Z6 r. E0 u$ ]" u! o
  3. </div>4 N, e) w- s+ c; F/ g8 f2 V8 M

  4. . A4 ?' n+ u' B# ]% t% A
  5. <script>
    0 L) h- L; Q) z
  6. var Child = {
    ; |8 k9 r, }+ x. |' ^- E4 p4 _
  7.   template: '<h1>自定义组件!</h1>'
    & V, Z( A( C' R  P
  8. }3 {2 S* J4 s) c' m4 A9 O& a, p* S

  9. 3 P% n& x  B: S5 v! I
  10. // 创建根实例
    # K3 ?3 a- ^0 w' i
  11. new Vue({4 T/ b7 U' e1 A' x* f2 {5 L
  12.   el: '#app',+ j# [7 y, q, S1 ~) m
  13.   components: {
    6 \' `, h1 M: o
  14.     // <runoob> 将只在父模板可用# l7 y7 _, [. V0 i# L+ j' a
  15.     'runoob': Child' s5 \; C) [* Z+ B3 u% p6 u- {
  16.   }; N. N. @1 J8 h7 q
  17. })
    2 C# d: `- I0 t9 v, f
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
( e8 r3 e/ J3 M
  1. <div id="app">$ A5 R$ e( f; b! h; `( |; E3 n
  2.     <child message="hello!"></child>8 q. q2 i& z6 b' w' P# R
  3. </div>
    8 O) O( K/ r% T. |  g
  4. 1 f8 r( Q3 M+ N
  5. <script>
    2 z- z* z% s  }4 F9 u: n- @
  6. // 注册
    & I! P( |; Y9 N- K. ^
  7. Vue.component('child', {3 l  V3 a$ S0 s
  8.   // 声明 props7 J* o9 S# v! d& B
  9.   props: ['message'],
    ; O' o/ Y0 I; Y: m
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    1 }8 u2 h& W. x
  11.   template: '<span>{{ message }}</span>'
    # V! v) O, A5 w
  12. })
    ! a1 A4 a# K( h0 r" p2 L" T& G  x& z
  13. // 创建根实例9 P5 e1 ~( p* R6 }$ T# B/ m
  14. new Vue({
    , h0 S. T7 G! X# O7 e9 Z2 O
  15.   el: '#app'
    ! }- X8 W) y( x/ x# F+ @
  16. })) I2 w* I9 @3 [
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例: ~$ s9 i; ^# E, r2 [0 S" u* Q) D
  1. <div id="app">9 B) O. l/ X. i( c; \7 Z
  2.     <div>
    * [4 t0 _; i0 F+ B# |; U
  3.       <input v-model="parentMsg">
    ) }; A, T/ V1 v, X# Y  G
  4.       <br>
    4 |# j# D, n7 [. k. S! V2 Y
  5.       <child v-bind:message="parentMsg"></child>
    8 I* k2 C  ?1 J) f6 ~& ~# t
  6.     </div>
    ( Z4 O5 L7 [8 T# s% g9 E
  7. </div>
    9 g4 a5 q4 p! X# n0 @

  8. & _, y" w& K3 _% V$ @- K
  9. <script>
    ( m4 |3 v8 c$ ?2 u6 N$ a
  10. // 注册3 A& B( \+ q) W8 k6 d1 J: D
  11. Vue.component('child', {
    3 e0 P) o6 ~: b' _) o0 ~7 r
  12.   // 声明 props( v4 B6 R9 l$ ?! G6 H4 U
  13.   props: ['message'],
    % c+ w1 z( G2 W$ O; H
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用  s) k3 F2 O7 O2 L6 C& K4 }
  15.   template: '<span>{{ message }}</span>'+ y+ W: t8 C5 M7 [& \
  16. })
    3 c  C$ x! i4 t2 ^( ~
  17. // 创建根实例  h- @2 u( ?; \) A$ N
  18. new Vue({) a$ {$ ^8 y# W& @! V# _* O
  19.   el: '#app',/ H3 s0 z& J3 z9 g+ ?# ]& @' E
  20.   data: {5 C8 T: D( y/ Q2 j: O
  21.     parentMsg: '父组件内容'
    # Y6 q4 `  V0 |- ^7 s" ?0 \
  22.   }+ q/ W* n8 {: |
  23. })
    / [% r' g8 ~! \4 W( x
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
6 E7 Y# n" ^& t0 o7 W4 p! W% ~. h
  1. <div id="app">
    - y/ ^' ?5 l$ J: S# f- z3 G
  2.     <ol>3 \, j/ U+ i8 @- ^! P, e2 V- L
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>7 w9 W3 ^8 e6 T9 q: f/ v
  4.       </ol>
    ( i8 r5 v( I, o  E9 Y
  5. </div>* y3 ~8 Y3 @9 w2 a7 ]7 B

  6. ' c8 \; P8 H; C0 _( i
  7. <script>
    6 }& @3 Z/ U5 {) v, C; [1 \
  8. Vue.component('todo-item', {
    # e' W6 E) z. f, V
  9.   props: ['todo'],. |4 _6 u" S' m+ q$ Z
  10.   template: '<li>{{ todo.text }}</li>'
    7 o+ O; j* ?2 }6 _+ x/ H
  11. })
    ) i4 w4 m, A9 h4 h/ q" u
  12. new Vue({
    7 |! D0 G" @) U  s' [( f: a7 P7 y
  13.   el: '#app',
    & n6 t* `8 h- X% D4 p: Q0 z5 x
  14.   data: {! d" B" h  G6 J0 U5 }4 Q" s) O; n
  15.     sites: [
    % G9 v2 i" Y. k4 @
  16.       { text: 'Runoob' },
    ) {: j- q" m8 k0 A. d! x
  17.       { text: 'Google' },
    3 u6 {! h6 u0 @1 F8 E4 \+ h
  18.       { text: 'Taobao' }& R+ W, W3 W7 k! X% n
  19.     ]
    4 r% e" ?  \/ k7 c0 J; ], K
  20.   }  |! [1 B$ F1 p0 z* N4 j
  21. })
    5 V% |5 l* L& ~7 X
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {
    ( J/ M/ w% B/ V
  2.   props: {! A* ?+ D1 R. \: l% Y2 N
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)9 g5 c% [4 a- b4 N
  4.     propA: Number,6 A- ~/ f- X3 n2 O
  5.     // 多种类型
    8 w1 `) X6 d. a& j/ Z& i* n
  6.     propB: [String, Number],2 F& W/ x4 P2 D, n! [9 m( @
  7.     // 必传且是字符串& A( Y) K( \; `# X  L
  8.     propC: {  ^- u* m7 P, l& |+ O6 t
  9.       type: String,' k( @: m& {4 l: j1 h! O5 J
  10.       required: true
    1 i0 G8 |  p8 @* r
  11.     },
    $ Q  z1 N( n+ J, v* ~
  12.     // 数字,有默认值
    : S* M  a+ _" I  e6 ]. C
  13.     propD: {
    ' }6 O3 U; x3 j
  14.       type: Number,
    + t) j) O; u2 ~3 E$ Y# u4 e; \/ d3 S
  15.       default: 100
    ' d, h- B$ W5 y
  16.     },- U. m0 @! J9 }0 f
  17.     // 数组/对象的默认值应当由一个工厂函数返回5 V) A% h/ X: E1 k: L- P! O
  18.     propE: {) A/ ~2 Z# @9 X* L0 m& f7 h: i
  19.       type: Object,% `0 }" e/ _2 d2 d
  20.       default: function () {2 s+ u$ c8 v; ~% R+ B; H. M
  21.         return { message: 'hello' }
    ! o# j: \3 t$ y+ f# ?# q: J
  22.       }
    3 }( w* U) l4 _' d4 ?+ x8 z, u
  23.     },
    + V9 }* X7 F  ?% h1 r$ ~& Q* H8 r0 V
  24.     // 自定义验证函数+ k2 u. I( P# \1 x
  25.     propF: {
    9 H; X% g  r7 z" d- D  ~6 ?" _
  26.       validator: function (value) {. b. Z" g6 T# m- w! W1 L' X
  27.         return value > 10
    0 q+ a9 N7 e7 J# c/ ]" A
  28.       }$ Y  y3 r& K( [4 j8 ?' L
  29.     }
    1 T* g. n0 B) m! X; W3 x9 L4 i
  30.   }* c4 e- A( [$ q# {8 ]# x' T
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
/ V2 z4 ?1 @8 T
  1. <div id="app">
    ( ?: Q2 p8 c/ Z" [5 e$ O8 ]: C% }/ [0 J) Q
  2.     <div id="counter-event-example">
    : n8 ?( v- w+ R, c1 P- S% D) k, I. B
  3.       <p>{{ total }}</p>
    " k6 u/ T8 Z1 w2 f6 M
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>, T! t" T; i# A7 {% E
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>2 p- e  c+ ?- q8 V' v
  6.     </div>
    7 |- N  m+ h. a/ a% ~
  7. </div>$ K1 q% s. K: F5 r

  8. ; g/ a9 ^* x+ G: P- x
  9. <script>* d# G- [, z& |9 z4 d
  10. Vue.component('button-counter', {& C# R4 m- A" G# ?" ^7 F
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    6 F/ S6 m! @% v
  12.   data: function () {
    0 Q# b( I& S) h* U5 Z+ C) V  E* b2 e
  13.     return {
    % v* P4 A$ e% Z
  14.       counter: 0  k& g! T! w7 r) ~
  15.     }  U! n$ t# S% {$ P7 M& _
  16.   },! u1 D' y% d; c4 l
  17.   methods: {
    0 v- I  i" [$ Z/ o+ q
  18.     incrementHandler: function () {$ ]. Z. v2 s  c8 e/ H( y
  19.       this.counter += 1
    7 r1 m  Z; t* Z6 V- u
  20.       this.$emit('increment')( g9 @/ G0 _. k3 X  C* j3 g7 l4 Q) g0 v
  21.     }% R* D% w, I! S. X3 S4 S9 J
  22.   },% q. n( H% W( J; n) o1 E, A1 y
  23. })9 |) i% Z; W8 b$ b! A1 B/ R3 z  N
  24. new Vue({
    3 `, V, _1 w( F4 e9 D: S' c
  25.   el: '#counter-event-example',
    7 k. v+ X8 Q% k" {1 d7 d& \
  26.   data: {
    3 D& [& N6 @  v% l5 }( P
  27.     total: 0* z% _. i0 O8 k9 e* f8 |, B* h
  28.   },
    , s5 v2 H. g( j  S* j" _2 K
  29.   methods: {/ F; |* A9 M2 {; O
  30.     incrementTotal: function () {
    $ F; A3 H' o7 w9 @
  31.       this.total += 16 |+ X" S6 g, V4 M' G9 Z( j& s
  32.     }+ x4 ~% {6 ^; \; Z- ^+ `2 U8 D! p
  33.   }, T$ S) e: t% w' i
  34. })
    . z: h8 s8 v  i& {! R
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册
    , W/ I+ S, p8 a( ~3 E
  2. Vue.component('child', {
    2 f( z3 I6 R( }% O1 b1 @
  3.   // 声明 props% M+ c) D6 F" M) T# q8 E$ x& u
  4.   props: ['message'],
    / ^3 z. h3 d- U# F8 y* E' H
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    ) j2 Q2 z% Z4 {0 w+ T6 R" M
  6.   template: '<span>{{ message }}</span>': L/ W5 `8 }: b# K6 i! W& p! V0 P
  7. })
    0 w! ^% ]6 r3 o: V
  8. // 创建根实例
    7 t* Q+ ?& j, l; q: N
  9. new Vue({
    : I, \/ k9 H: c2 o. V
  10.   el: '#app',' S" t5 M5 s% H% Z& u/ e& Y, d
  11.   data:{
    0 k6 {- }6 |. {7 C+ N# L  |
  12.     message:"hello",' }* P# ]. ?; X
  13.   }
    & W# B0 r+ j; l6 N% _
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {
    4 X, q0 ]  L5 ~/ ?6 q3 t( Y
  2.     incrementHandler: function (v) {
    : ]+ ~8 x' O% `$ t0 c( g
  3.         if(v==1){
    ' {. [( {# _" o$ u) W, P
  4.             this.counter -= 1
    ! [1 b8 }9 S9 E$ n0 Z$ s# B# i* R
  5.             this.$emit('increment',[1])/ I* W2 W' c: w: |- O
  6.         }else{2 }. @  E2 F$ m, `
  7.             this.counter += 14 H) H& G( H1 u
  8.             this.$emit('increment',[2]), D& G% n8 N3 w
  9.         }
    # ~- ~# P7 `/ X0 w7 L* S+ I
  10.     }( J9 ^& U  k% _! p8 u
  11. }
复制代码
! F) W, J- s' K8 _" A

4 z; n, b) A& [. D: h/ _# r6 B




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