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

# }  ?! u% i! Z. ?0 o% i, ?1 X2 I
  1. <div id="app">
    , y. j" M' g2 s* i
  2.     <runoob></runoob>
    , ]) D# D4 z- a# l- A5 J1 B5 z8 S
  3. </div>
    # z2 T& N+ ]4 _' t0 \! X1 I6 d
  4. 7 t: x8 b. Q! Z  k- S5 i" Q
  5. <script>
    : w" N6 R% j1 N( A$ j
  6. // 注册" [, ?" ^7 X* v* ~
  7. Vue.component('runoob', {4 K+ e* w. `) F, l" S! v& A
  8.   template: '<h1>自定义组件!</h1>'4 R- R: P7 c8 ~4 B" ~& J
  9. })) l+ L2 C3 X1 T0 J
  10. // 创建根实例
    % E) \/ ~9 S, G' s5 r) ]% y& e4 D
  11. new Vue({, z: I8 F: h: Y, }1 R6 F
  12.   el: '#app'+ d* c9 e: v' k* \& m
  13. })1 z; J- [/ I& i8 B$ ~0 C+ C
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:
7 k$ A4 w# l6 L+ F' Y
  1. <div id="app">
    $ ]0 [; C' b* u& `7 J0 @8 s5 {' A: E
  2.     <runoob></runoob>$ K) a# _: l" r7 M( K, |& x% T
  3. </div>
    ; `) ^6 ]! z8 y, b

  4. ' u2 @& f: p* }$ |0 j9 K% ?
  5. <script>3 i7 X* }# p" ?  n- v* g
  6. var Child = {" i$ g4 R% V. p6 `* u) D9 S9 }
  7.   template: '<h1>自定义组件!</h1>'
    " \, J0 B7 G2 U! o' g
  8. }
    & A, M. m6 v+ g% D+ v
  9. 1 _" s+ k$ ^/ N6 D0 o# l9 l: b5 B
  10. // 创建根实例$ C4 ]7 ]% M9 r7 G; Y# v( |3 M
  11. new Vue({
    . V% t& X& A  ]7 d4 @
  12.   el: '#app',
    4 `1 s0 @7 N7 Y4 A1 Q% r7 z' o/ w
  13.   components: {& T5 v) w$ H; k+ t- |9 x
  14.     // <runoob> 将只在父模板可用! ]8 x. x8 W) J+ B5 `
  15.     'runoob': Child
    : m. c* s; D5 V9 i- ]$ G- o
  16.   }! c- I' E  z) V" `
  17. })9 g# I' o, l& k1 I4 G
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例+ ]* s; x  p. p8 y4 A6 V
  1. <div id="app">6 s2 M& w1 H% ~2 ?
  2.     <child message="hello!"></child>, G9 ^( d3 k0 c" J5 e) S/ Y
  3. </div>1 Y' k8 s0 V& D0 [
  4. $ j% w# n/ s: U$ |) t
  5. <script>
    % w, {# L2 z: z# v8 I
  6. // 注册
    $ X! f: l3 c8 w! C
  7. Vue.component('child', {
    $ Z' v9 ~8 |* _4 L/ b9 Y
  8.   // 声明 props
    ; @( J0 }: ?, `" n
  9.   props: ['message'],: c0 p% S7 W8 \% M7 t
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    ) @7 L- V; Y/ E* E; a2 s/ J+ u
  11.   template: '<span>{{ message }}</span>'
    9 s* C1 b8 H8 o: V+ `. f4 N- a
  12. })
    $ \; G) Y; U$ p+ \1 ~" F
  13. // 创建根实例
    9 B6 p# L$ n/ S, j6 K
  14. new Vue({+ @4 d6 Y3 V1 W. R+ f2 e, ~
  15.   el: '#app'  o/ Z3 [; Z* \9 j" ~! b& `
  16. })1 W6 x* Y# m7 W4 V, O
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
7 o0 p6 _8 n* D! j; ^
  1. <div id="app">+ s- b8 Y4 U( C  {: E4 n, Y2 f% T
  2.     <div>6 L: h3 W9 u+ K
  3.       <input v-model="parentMsg">2 A8 [- y) `+ |2 ~& W
  4.       <br>
    ) v* H" O1 |( d& v
  5.       <child v-bind:message="parentMsg"></child>0 {3 V/ I1 N/ w) R2 M' c* h
  6.     </div>2 E8 L5 X3 P" P, l- u
  7. </div>
    5 c& Z* s. y  P3 u$ J1 S! ~2 _0 X
  8. $ k* |- u) j5 W1 K: L1 W  [6 J: F
  9. <script>
    4 r* {, f! U+ P! x7 ~$ ^% }1 o
  10. // 注册
    % m( j0 P) [  @2 G, ~6 d: K
  11. Vue.component('child', {& p; O8 ]" H, W- U
  12.   // 声明 props
    4 c- O+ U6 m0 x( R6 c# a5 P
  13.   props: ['message'],7 {* B5 U3 i( X5 {8 }% a8 n2 z
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    3 l- A+ G; y1 \' F
  15.   template: '<span>{{ message }}</span>'
    * v! M( `  A* y- a* s
  16. })# g+ {8 M& C& T  O! _+ v1 L8 m
  17. // 创建根实例9 e' ]* u2 n5 V+ t( G# Y0 d. U
  18. new Vue({
    . C! C" U7 p+ u$ v
  19.   el: '#app',! [# k9 v4 q+ Q& y; A* T
  20.   data: {
      \! M/ K$ R2 ~6 J$ f4 N1 i
  21.     parentMsg: '父组件内容'3 D: A" x; ?2 [( d* A- {% ^
  22.   }
    - k# }, C7 j+ |) Z
  23. })% b' @3 m2 t3 m  x1 L9 Y; L2 u
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
- r" A" W3 p1 H: q6 [: T
  1. <div id="app">5 Q% s. p$ h/ s
  2.     <ol>2 H9 P/ _! e& _
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    ' i& B& e, C9 f! ^3 l" S, Q+ K
  4.       </ol>
    . z0 _3 l, \1 P$ H2 Q
  5. </div>
    # e3 @# {6 l8 M# Q2 b& [
  6. 4 u! U: W# o. Z" x" n0 G3 M
  7. <script>( c8 y. D+ \) @: F% Q  f0 \. w7 g
  8. Vue.component('todo-item', {
    ' R, Z" D# E2 o
  9.   props: ['todo'],
    8 f4 H5 Q* e6 ?* m6 q7 j( L
  10.   template: '<li>{{ todo.text }}</li>'& d' ]+ k$ ^/ o8 O2 S2 R
  11. })
    3 m6 P( S  K" w3 @) J
  12. new Vue({& B$ y5 y) f9 x
  13.   el: '#app',
    , d" V& \0 w) ^' V$ y& W
  14.   data: {
    5 j" F# ?6 q! q: J
  15.     sites: [
    , |3 D. Y1 i; Q
  16.       { text: 'Runoob' },
    * V  l6 M& K6 T* o/ {
  17.       { text: 'Google' },
    + p- d/ H0 ?3 r  p& U% ~  P) j5 S
  18.       { text: 'Taobao' }8 n4 z4 y* z) N
  19.     ]
    0 o" j6 {# I1 ]" R; |" m% n% f
  20.   }7 y( t% [7 t! S' _
  21. })
    3 X  ~/ h. b3 y6 |
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {
    * q) S. q' ?* J5 {
  2.   props: {
    ' O9 c9 ]. O" G) |' c* J
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)
    ' v5 j9 _. B' D0 u# m
  4.     propA: Number,% |8 T5 p9 g9 S. b
  5.     // 多种类型
    ) q+ e* A7 [% n+ H/ o0 P
  6.     propB: [String, Number],% p( c  z( |8 O& C2 X
  7.     // 必传且是字符串6 ~) _& `: A: ^' y0 [. |3 X  W
  8.     propC: {
    " C/ ^9 _+ `% Z& x) Y; G
  9.       type: String,( x8 v2 {  P( }9 m; v8 {
  10.       required: true
    % I9 Q, J- P% S( [
  11.     },
    0 ^: H1 h# W! S) D; \% T- p
  12.     // 数字,有默认值
    5 l& Z9 ~% T% [" i0 B& q3 x
  13.     propD: {, u9 a# [- t8 v8 U7 X( Y5 ~
  14.       type: Number,
    : s) Y+ l, |. v8 }
  15.       default: 100  N' @+ x3 p* k- I; e; p
  16.     },
    : E" W2 ]9 a" o  M) C' M
  17.     // 数组/对象的默认值应当由一个工厂函数返回
    . L, S/ f) D- Y" U  m4 p0 @, d% r
  18.     propE: {1 m; s* s9 V1 a
  19.       type: Object,
    0 F- X8 X+ v( i" _' x
  20.       default: function () {- I: q# c5 v1 D8 ^( Q
  21.         return { message: 'hello' }2 ~: z- |1 m% ~% ?3 S
  22.       }
    ! r+ B, Y; i/ d3 Y
  23.     },, e  T4 t6 m* ~4 m
  24.     // 自定义验证函数
    3 K. d2 H' y# `
  25.     propF: {
    8 ]9 F( |& n. i# e! q  h- T
  26.       validator: function (value) {$ z) n7 p9 O/ u7 a. P6 k( k
  27.         return value > 10: ^. C2 p; j" n* b# Z: J
  28.       }
    . H$ t  ~0 S0 G. f9 m
  29.     }
    ! Y+ `+ t- F: ~) F( R! {1 Z/ B
  30.   }
    " Z% i* u  c: X. J7 ^0 l: f# Z
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例0 V! G5 M% c5 ]8 d2 ~3 _% N. S) w
  1. <div id="app">7 N1 k6 P0 t9 a/ P2 K; h' B
  2.     <div id="counter-event-example">5 X5 @' X( `4 P
  3.       <p>{{ total }}</p>; B! j+ V: S+ O) y% A% e, x
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>7 x+ h* U$ j% e. E5 _
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>
    ( u/ O& j6 A8 u: _* O) r5 l* V
  6.     </div>( k! p1 V+ X+ [( B) |- q% ^- p
  7. </div>4 R% r: m0 S* K- Z# h$ _. b4 m
  8. ; i+ g8 |7 l6 v7 t
  9. <script>
    ) X' ]" d: }8 {$ s5 X
  10. Vue.component('button-counter', {# F) H; r: H& T$ O$ t# z1 w
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    " i& k8 c9 h) m( T4 U" ~& I6 b/ t( D
  12.   data: function () {
    . c5 C# f  e2 N, k5 E8 a* L
  13.     return {
    8 n6 K1 b% Z$ d& @9 r
  14.       counter: 0
    0 e' L2 v  M+ C# l- m
  15.     }" m+ {2 w& A& h& H! a
  16.   },: \2 K0 u0 K; [- O
  17.   methods: {) a2 Y2 h: V& b2 |
  18.     incrementHandler: function () {
    8 ^$ ?7 _* L* _2 f  z
  19.       this.counter += 1
    " m0 H7 f1 W! I1 [
  20.       this.$emit('increment'), F, \- m4 [7 e) ^# D: H
  21.     }5 E7 t9 j  v" [; l) _' Y; q
  22.   },
    & h) Z: b: V0 w* D: D
  23. })
    ( q, Y' m1 O  W6 N- P+ _! Y
  24. new Vue({
    ' g! b3 y5 O, l
  25.   el: '#counter-event-example',
    ! C) Y3 q. t- t) H5 a+ p
  26.   data: {: g9 e& k0 a' I
  27.     total: 0* F* Q( j( [/ \" H( k
  28.   },* y* b! Q! S4 c, d6 t" b
  29.   methods: {4 i% b% T* a; ]+ `7 K1 c
  30.     incrementTotal: function () {, M" T" Q3 q, _- v. U: c* r
  31.       this.total += 1
    ( F# J* @) X# B
  32.     }
    ' c7 q7 O1 ~: b. B0 G/ O! h
  33.   }: @& |$ Q; h* A+ j8 T: [) P
  34. })
    " \- l; ~; F8 q6 X
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册
      r* w% b! m8 H/ F  J
  2. Vue.component('child', {
    7 ]5 u  F! x. q- ~: _. [
  3.   // 声明 props3 o4 ~/ T  D8 z4 F& f0 _$ {
  4.   props: ['message'],
    * D4 L9 i% e& b( [; ?( d+ K- i
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    3 o* V* R# s+ U# S3 t5 x/ I
  6.   template: '<span>{{ message }}</span>'# Z7 I4 T# x+ t
  7. })! s) E2 A4 Y/ u* b) h& M8 A, ^
  8. // 创建根实例
    0 ?# j1 U* t. P" \% v% U# W: O, T) w
  9. new Vue({% t# E  F& U% {' K0 L/ b# _
  10.   el: '#app',5 _" ]( U& ^" w- {  J( z& k: m2 M3 V
  11.   data:{
    9 E, W% ]7 b  K7 [, S
  12.     message:"hello",
    * r" P7 I4 e+ s" N+ Y
  13.   }
    3 C2 O1 L" a/ C1 x' g
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {
    ! a4 Z; {) ]9 d7 G' ~  ?1 g
  2.     incrementHandler: function (v) {, K0 {. k8 F6 y% v4 V
  3.         if(v==1){0 b$ r: s$ L* I9 |
  4.             this.counter -= 1& ^# a  q! X. v& z3 D
  5.             this.$emit('increment',[1])
    % e. K$ ^$ Z, G6 B) A* }1 w) v1 Z
  6.         }else{. c+ M* I1 T+ t! M
  7.             this.counter += 1
    # K0 u2 @0 l. Q; \2 |5 P
  8.             this.$emit('increment',[2])$ ^. ]" U) b5 c& E9 I& i" a  ?- k
  9.         }& i! a5 ~' N& X+ a
  10.     }
    % S3 l" [7 o1 c3 p) k- k
  11. }
复制代码

* t/ S4 W# B9 {+ t% T% }! C
" o& G) v7 Z  W+ l: B  C7 z/ n




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