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,并使用它:
" P6 v, K& w9 i2 b" g
  1. <div id="app">
    / g$ U9 x9 i1 N0 I/ P  J6 a# q
  2.     <runoob></runoob>& C' Z. Y' w) F9 a8 z- L
  3. </div>6 [2 O( s: B3 y  |+ o  v
  4. 7 d; k& I, S: {
  5. <script>
    # k# X2 H/ Z1 \  [* \' W/ _
  6. // 注册  t# ^: Y8 A% a1 k4 o0 A4 m
  7. Vue.component('runoob', {4 n" K+ J8 ?! z5 r0 }
  8.   template: '<h1>自定义组件!</h1>'
    4 e; I0 ?3 |9 W' ?3 p; o/ Z5 e# t6 z
  9. })
    - q; K7 ?- x, x' C9 b+ m4 V$ F
  10. // 创建根实例
    ) P) ]% K- s) }7 P5 t4 J
  11. new Vue({, I+ X/ d) i, e* _6 ?  k
  12.   el: '#app'
    2 E' \1 \8 I9 y3 h' E
  13. })* M8 s2 C* k: K( l6 _
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:
7 M0 S+ \8 W% L' k! t9 t# G0 r
  1. <div id="app">7 E% _7 g6 h5 q2 g5 p! p
  2.     <runoob></runoob>' S3 P' r; {* V9 E4 A0 _
  3. </div>7 \7 S! K5 h3 U$ [9 U
  4. 1 M! }" }$ G& J$ C+ ^$ }
  5. <script>
    , G) T* g) U5 {% o
  6. var Child = {
    # p) [8 S0 b7 r/ S  K+ t+ A& X
  7.   template: '<h1>自定义组件!</h1>'7 a9 j' N0 h' g6 }% V1 a$ t1 F2 c1 @
  8. }/ [3 x/ H7 O: K. ~' W' v7 \
  9. 6 c4 }, P3 |! I5 H4 `. g
  10. // 创建根实例
      I* z' f) D: C; w5 f/ x3 I1 }
  11. new Vue({" b% g- f" |9 H6 W
  12.   el: '#app',: Z+ `* a8 ^/ B( a# B' t
  13.   components: {  X; f( q9 Q( s9 i3 B0 [
  14.     // <runoob> 将只在父模板可用
    + J9 C+ i" J3 Y7 R- S3 |
  15.     'runoob': Child
    $ J% X( K' P( \5 n
  16.   }. e% p7 l; L- D
  17. })& e" l% t8 S8 d' V6 Y0 i  Q! H
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例! M6 b2 H; C* f6 V
  1. <div id="app">
    7 g5 d  y. _' D7 l" r1 ^
  2.     <child message="hello!"></child>* r! M- Q2 I) z) v1 m: L
  3. </div>7 l8 T1 `4 ?; n' A- ^
  4. 1 U4 f& M3 `- P' r/ u
  5. <script>& v. d, e$ D; g5 q
  6. // 注册; _" y- l' y- x& v% }0 k' K  t
  7. Vue.component('child', {
    ) k# u; F+ i" F% @  ^
  8.   // 声明 props9 ~, `# g% [  {, Q& `+ y& H) ^
  9.   props: ['message'],
    * {& y) r6 y. N4 f7 k- M
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    ; `: F+ V- j5 }
  11.   template: '<span>{{ message }}</span>'
    , T$ {0 ?# f# n$ }, ]5 c. G) h
  12. })
    4 z- _3 b4 \+ w& V/ d! R
  13. // 创建根实例
    - P# |: L+ K8 c
  14. new Vue({/ F2 y/ I: [+ o; U5 f
  15.   el: '#app'
    & D9 w* K) h% n
  16. })
    / H$ V5 n3 m4 Q, @
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例3 x! H1 y) _: b" n7 V2 A$ B
  1. <div id="app">
    ( H+ |8 p$ D9 ^( H6 q' c3 }7 E
  2.     <div>
    9 O: V0 P% @; D9 e7 {7 \5 X% n0 l
  3.       <input v-model="parentMsg">
    " Q0 l0 q/ C  e+ R4 p
  4.       <br>
    ' l& B: O: H: t7 {" d$ F
  5.       <child v-bind:message="parentMsg"></child>
    5 o( k6 p0 d7 z7 Z
  6.     </div>6 n3 R7 F1 w2 g2 A& K  i1 P# K
  7. </div>! p0 r0 u9 I# ]  m3 q0 V  z5 L; ~
  8. 7 o* W# I5 e3 c' Z
  9. <script>
    4 O% [' w* U' z  u4 U
  10. // 注册3 D  {* x% O8 [) M- A
  11. Vue.component('child', {8 {! y, Q8 h+ k! {9 x' R! v$ p& o
  12.   // 声明 props
    $ a9 q0 ^+ A% }0 @  a8 N& Y; @
  13.   props: ['message'],
    # `8 A! \( p8 Z
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    2 I6 A( ]* i- d! h& `
  15.   template: '<span>{{ message }}</span>'
    2 l8 |' w) U( g8 q9 f
  16. })
    . O9 L+ r. ?+ T  I/ D
  17. // 创建根实例
    + o2 e/ F. Z* f' |+ a7 R
  18. new Vue({* \+ \" l/ ]% ]% c5 e8 Q
  19.   el: '#app',2 E% P6 c% R3 Y# n4 w
  20.   data: {7 D& S0 x. A$ r. Z( W: f; ]
  21.     parentMsg: '父组件内容'0 `5 X( v& O9 Q( T
  22.   }! _+ u$ x& A" e- t3 A" @, u
  23. })% j" @8 H& M5 @% t* T* ]9 V  \
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
) `: Y7 i* Q$ j+ Y
  1. <div id="app">: G8 I" o# S/ U  `' u# ~! W
  2.     <ol>( ?" C( g) ]8 l5 ~' G/ D% m
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>6 f$ x: N' h; S8 ?: u" X- [& j
  4.       </ol>, D9 z3 v4 B; Y2 D  i3 [- g8 A# z
  5. </div># I/ d% f8 z' A5 f  o, k- Q

  6. $ \+ C& L7 l' x1 a: G: V
  7. <script>
    ! M# b2 @9 O1 g& @* F' v2 y4 }) u# t
  8. Vue.component('todo-item', {
    5 d7 z& h* w/ K: K0 w: a7 N
  9.   props: ['todo'],
    7 e, }  o) X+ }- n0 K+ f0 z: M
  10.   template: '<li>{{ todo.text }}</li>'# n& c7 j, J* t# }
  11. })$ I: c0 n! a# a1 T+ P- t2 C
  12. new Vue({9 m  \) E8 Y5 t1 ^7 G7 y
  13.   el: '#app',
    2 R4 N4 m; c" c0 a- g
  14.   data: {
    7 X* v& {2 @  h; I9 M
  15.     sites: [
    - p2 w6 z( V, ]& n: {% ^
  16.       { text: 'Runoob' },
    + E# y- N0 w- k# a" g9 o
  17.       { text: 'Google' },
    & X  T, w1 Z3 e/ c' N% q5 ~: w
  18.       { text: 'Taobao' }
    7 F" i# |8 n2 m- o
  19.     ]+ l$ F* b9 ^- N3 A8 ^+ i
  20.   }
    6 [+ o7 a8 p) i3 f4 E
  21. })# l4 Z/ j& t' |6 I7 T% X% G0 E
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {
    % v3 W) }- ~# |# b( ]- Y
  2.   props: {
    5 {2 {% J) |$ ^. c1 _+ s5 K/ }
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)
    # ]% d0 i) e' K% n8 b* e$ H: }
  4.     propA: Number,) q; b: H( r# h& {3 E
  5.     // 多种类型
    - D! z8 s# [& b% ?4 B
  6.     propB: [String, Number],1 [/ v7 F! ?. g
  7.     // 必传且是字符串
    " l! j2 |0 d! D0 v+ m
  8.     propC: {/ t8 i! G, I6 E! n& R+ Y" g" {
  9.       type: String,
    * s; ^  N& s$ I" S7 ^" S0 ~, _
  10.       required: true0 c- F1 V3 W) A8 Q
  11.     }," k7 T7 f0 t/ \# T- A
  12.     // 数字,有默认值
    . `. d& ~( X' E
  13.     propD: {
    . R! `3 b0 R; W2 \2 Y
  14.       type: Number,
    6 t7 k9 E# D0 }! M
  15.       default: 100
    ( u: X2 D- u1 B* j! W& P9 j
  16.     },
    5 |# E) x$ \+ C; l4 g4 P
  17.     // 数组/对象的默认值应当由一个工厂函数返回
    . C: B8 S& k" D3 X
  18.     propE: {5 B" q! e7 L9 @5 \/ M* _
  19.       type: Object,0 X6 z  H- x% l# G) _8 ?5 p/ p8 P
  20.       default: function () {
    ) Z5 B7 o( J2 u6 C% E
  21.         return { message: 'hello' }$ m+ J4 p4 m) T9 `. S5 m
  22.       }
    + i4 Z) O9 B; r; q3 x6 ]- h
  23.     },
    6 T) v, d9 ~! P( H+ \5 {8 {, g9 \
  24.     // 自定义验证函数
    0 W5 [: J& P1 F8 j: R9 a
  25.     propF: {
    * \$ Y! L1 r- h: k3 i3 N
  26.       validator: function (value) {6 E. W9 z3 c8 ]1 \/ h) Q
  27.         return value > 10
    % A  D% z4 l: ]. i7 p( O
  28.       }
      Y/ J! x  f! {  d. N1 [4 [
  29.     }
    - t  Y8 U( V: b9 @* c  _
  30.   }
    " J3 z. h, }7 S6 {0 A' j
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例. J& R6 P4 c3 D. {; f* z8 S# T
  1. <div id="app">6 ]" A! N: _  m2 D
  2.     <div id="counter-event-example">
    ' f7 V* }/ b5 G6 A8 |  n1 j
  3.       <p>{{ total }}</p>+ }5 O7 {' ^2 R. X) k
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>4 O/ x% V( c3 V& j8 H; ~/ {
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>
    - |" ~7 E8 j9 U6 f6 B
  6.     </div>  l% `) K; s' ~6 e- G5 p
  7. </div>
    ' W* L" r+ Q  O% x) E
  8. + \) \2 X1 W$ @/ w3 B# p$ |
  9. <script>6 Q" [, A4 N5 o. s
  10. Vue.component('button-counter', {
    4 e& _1 G. t/ d- I5 {2 k/ g8 A- }
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',( p) q  a0 J: e! t' `
  12.   data: function () {3 H. Y& v/ n( n5 I# [3 h' a
  13.     return {% M4 r7 t3 N: I, B7 P# }
  14.       counter: 08 d& K( z2 e& A
  15.     }9 ^) a% _! ~  W7 W3 `
  16.   },
    ; J% _5 \6 P4 s% K* n0 H( p3 K
  17.   methods: {1 r4 y/ b/ L/ x, \% v- H
  18.     incrementHandler: function () {8 D9 w' `  O( J$ {7 j# w
  19.       this.counter += 11 f  t+ N5 F7 K* X1 \" H
  20.       this.$emit('increment')
    . R% m7 N1 R+ v* ]3 I
  21.     }
    + o/ y9 K1 i, D. m
  22.   },2 ?) u5 x7 l* h( }* M0 Q6 w4 U, x
  23. })
    , ?% s, l9 R* `7 _. X: h+ S
  24. new Vue({
    , H) ]) @8 w9 y" e% d
  25.   el: '#counter-event-example',8 A- A7 Y- S$ o  D$ p+ ]; C& D* @0 f" j
  26.   data: {  L/ g  [: |# ?9 H6 v$ g
  27.     total: 0
    . s) [- q7 a8 |( x/ D
  28.   },
    # |; \6 {$ _2 E1 k7 w7 [- F
  29.   methods: {
    $ }9 l/ H& b) W. i1 S" G  X! ~
  30.     incrementTotal: function () {( A1 J& B9 y2 {( _1 h* U; G
  31.       this.total += 1
    ! ~, I7 }% ^" U/ t9 T& i! r
  32.     }
    $ h9 V5 {$ m: k! c! U* l: {% w+ V1 S
  33.   }
    ; O, _/ o4 l3 T8 }, N
  34. })
    + c. K8 L# y" g! \% p
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册' D2 [/ j* ?+ F3 p
  2. Vue.component('child', {
    % t# _- q) v0 R" m7 l* D5 h
  3.   // 声明 props: B! a% r1 R1 d) H5 j5 }
  4.   props: ['message'],. a8 ?3 D1 l8 p* G9 k
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用  [8 l. H, d2 p, I/ I. b& Q& Q
  6.   template: '<span>{{ message }}</span>'% Y  a8 x1 z% U! V. Y* q
  7. }): m: ]! p/ k7 B
  8. // 创建根实例, {/ U% G/ ^/ f9 O) x
  9. new Vue({
    7 l# G+ {3 D1 A, W' R
  10.   el: '#app',% y- r' P( |& Y( M9 x
  11.   data:{+ [4 n7 K9 s( o6 N
  12.     message:"hello",
    ' Y2 r$ c3 a0 t4 K( E. M  F
  13.   }. F% l8 ^2 s: T/ @
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {
    ) S% G( g& T' B  X; I5 h
  2.     incrementHandler: function (v) {
    ' e- j$ Z! p1 B# `
  3.         if(v==1){% Z0 J3 O. I4 V
  4.             this.counter -= 1
    8 S4 m% |9 s/ T  p7 p; e
  5.             this.$emit('increment',[1]): d' |$ L; ^2 o: h
  6.         }else{
    # a- I( p. z* E# Q
  7.             this.counter += 1
    1 _' I6 M6 \5 ]' U" X
  8.             this.$emit('increment',[2])
    & k" X3 |! f# U6 P* p0 P' [
  9.         }
    % p! [4 K8 k5 Z1 A. K
  10.     }
    1 K& ^3 {, h. x; r
  11. }
复制代码
- O1 c$ ^: ^6 N0 S$ H2 `
6 N% \  s( N. \0 A: i9 }





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