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,并使用它:
" g. z5 X$ x5 z0 |$ J, I
  1. <div id="app">
    9 ~+ Q8 N9 Z) ^& a
  2.     <runoob></runoob>/ {/ d# G; K  u( j9 _
  3. </div>( y$ H- v" k* S4 S& v3 m/ m
  4. 3 d5 U: Y1 d* W; T' S, }* ]& f0 M* W
  5. <script>3 O: K* `) ^7 J. v1 i. X
  6. // 注册
    ) H6 p: q/ [  f' r# c1 i- `* P4 `
  7. Vue.component('runoob', {
    4 {6 J8 T: {" e* v: B9 w, a2 e
  8.   template: '<h1>自定义组件!</h1>'
    ' O: n* V" f% |3 y
  9. })
    * K7 q2 P  E7 ~7 H8 |
  10. // 创建根实例% b5 ?9 f/ ^9 ^) o+ Q
  11. new Vue({
    , Q' [4 \* J0 R& t
  12.   el: '#app'
    ( }( ]# Q* P7 M1 o! z; u
  13. })/ ?$ r, E0 _. e) r, F' r# j
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:
/ L1 q+ t/ A4 T
  1. <div id="app">/ v3 C) G* G6 S+ V* E$ q( `
  2.     <runoob></runoob>" F4 w% c- L3 n- y( G
  3. </div>
    + `$ @2 w( A2 T4 p, ?, Q. L! d

  4. 5 l  ~7 m# d  L& h9 b# `1 Y
  5. <script>/ A$ K4 G; f4 C: D' i+ z0 J; W
  6. var Child = {
    ! s1 S7 m# o" X
  7.   template: '<h1>自定义组件!</h1>'
    - f0 |7 |" R% [
  8. }
    ! Z0 Y0 L+ U# {! P1 v+ p3 U' o

  9. 7 h; Z5 Y: a7 k+ }6 q: [
  10. // 创建根实例2 T) g5 m* o* ^' M- c$ X
  11. new Vue({
    % W" o7 F6 N) ]& `
  12.   el: '#app',
    7 _% Q3 Q6 m- f' I
  13.   components: {' `+ Y; Q; C% S  {
  14.     // <runoob> 将只在父模板可用
    1 ?9 Z3 E% l# Q
  15.     'runoob': Child
    % Z1 ?- V+ G) ~& v. U" F3 h0 ?* W
  16.   }
    1 i  D9 x8 r0 l. L' o; x
  17. })
    1 Q' u5 X: O' \
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例* t% X$ d, f7 n4 q: e
  1. <div id="app">
    % }8 l0 ~& {) V/ @0 B7 L
  2.     <child message="hello!"></child>7 C' e; p& v' i# k# h
  3. </div>
    3 N; s5 a! r2 t8 ?$ V

  4. * L0 p5 h0 Z) R( R0 ?
  5. <script>: S8 i( W% n5 X; `, V
  6. // 注册, A+ S* w+ [& e9 Q6 H
  7. Vue.component('child', {. ]4 P& I. r( M$ r7 F" \( d
  8.   // 声明 props7 Y/ s$ f1 \4 R2 h% I4 p6 N
  9.   props: ['message'],# E. u6 f& q; g' G
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    + w# W4 q6 i% X! r$ e
  11.   template: '<span>{{ message }}</span>'% K  x8 W' Q2 Z# t# t1 h8 x  ^) a
  12. })$ L$ i7 B; f! @7 V# c! Z" `
  13. // 创建根实例/ g  @% O, I: p5 b0 ^
  14. new Vue({, M# E- V& u! @) S# L+ Z) ^) y
  15.   el: '#app'; c6 N2 S7 ~& d* {
  16. })! x1 K2 O) G$ k1 Z2 E& I5 Q
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
: M- B: z+ J9 y! H
  1. <div id="app">
    ; e9 R) [5 M6 v+ |% z6 n1 g
  2.     <div>$ y# }2 l6 d! A& {0 A/ J
  3.       <input v-model="parentMsg">
    ; _4 r0 c& O3 ^) h4 y
  4.       <br>) h$ ~# e2 i* g; {+ x& H
  5.       <child v-bind:message="parentMsg"></child>
    & j2 B' y; l. d' \( Y$ k, A
  6.     </div>  w, w% |3 W% h& E
  7. </div>+ y7 Y# n4 k9 ?6 _" ^: R, g& y
  8. , f6 F2 T/ Z7 j4 Q# L1 P
  9. <script>
    5 i% ]$ |. a! M+ P' P" r& Y1 i
  10. // 注册' \$ _- H8 v: F8 n
  11. Vue.component('child', {
    ( t- W2 H% P& H. m0 U4 e: H( U7 q
  12.   // 声明 props
    / ]5 R4 j: n- w' ~/ L# |0 ~
  13.   props: ['message'],, ]& C9 d9 O6 f6 L6 f
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用" A7 i* f$ `1 o9 O
  15.   template: '<span>{{ message }}</span>'
    4 t0 m0 D  t+ v/ {" W
  16. })
    & `2 F0 W4 Z# H- H3 N
  17. // 创建根实例8 p& F! D3 R# o5 _7 y/ p
  18. new Vue({
    * h! T1 Q5 _8 m6 l5 s
  19.   el: '#app',
    0 w0 u! U/ k" g. x) ]0 ~7 ?
  20.   data: {& `- P  o( i# z* p8 `  d  R
  21.     parentMsg: '父组件内容'9 K* i$ Q3 R, z3 j3 Z8 K+ B& `
  22.   }
    ) `6 @: c0 u/ K5 m7 V( `
  23. })0 U1 W: F" l, h  R% f( u2 Z
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例4 F+ f* d% l! m& a" F
  1. <div id="app">- X) P) Z1 _( s# _, E, K  D
  2.     <ol>( d4 b( U% V$ U* L) w# k; E
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    9 w9 M7 l1 ], C: w- r
  4.       </ol>
    " d" L$ e# G% Y: w
  5. </div>
    4 m0 a4 a- E% T' k$ Z7 s, K2 X
  6. % b! C+ v$ J1 m$ ^+ e& v
  7. <script>
    2 q, g, j% s5 i# d4 R
  8. Vue.component('todo-item', {
    * L9 w6 a9 o% N" T1 m' ?6 U( b* h
  9.   props: ['todo'],
    - T1 |( J+ B/ I
  10.   template: '<li>{{ todo.text }}</li>'
    9 |1 O3 C( Y* u" D6 R) P: y* D
  11. }): v. ^  y; G' ?7 |( z& y( S
  12. new Vue({3 {1 g; [. ]- M0 A: K
  13.   el: '#app',4 u! t3 q2 u& G0 G6 v
  14.   data: {
    $ J# x- W4 c4 E0 m7 n2 p
  15.     sites: [" Q4 \" n& Z! f9 |% P
  16.       { text: 'Runoob' },2 m" c/ a; F9 h  g1 w5 b. F0 j& e
  17.       { text: 'Google' },
    2 O# [5 d$ Q/ t) d
  18.       { text: 'Taobao' }
    7 s% a/ p2 S1 U
  19.     ]* E% ~/ w& R: j: ?- M
  20.   }
    , \  I+ m  J+ [9 {( b( f% y% z
  21. })
    ) V6 V, p8 I- o3 ]6 p: T+ E# f
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {
    4 k- k0 d" D0 |- m# k$ W
  2.   props: {
    / T* Q0 M$ L+ J( T  S  W
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)2 O- M* s* l1 M) M/ V
  4.     propA: Number,
    0 e) A0 G& t0 l
  5.     // 多种类型
    * \  L' U& u: Y" C, k
  6.     propB: [String, Number],5 L6 o; j% @' I. K
  7.     // 必传且是字符串
    1 ?6 A7 {3 Z6 b* C9 Q
  8.     propC: {
      _/ y$ D& ?/ v+ P% Z( s
  9.       type: String,
    ( B! G0 B) x; F5 M
  10.       required: true3 C9 W& @. p0 E
  11.     },
    , J/ z! l9 X# c& Q2 c, J  ]
  12.     // 数字,有默认值
    - H8 l% _5 x$ t, ?2 R
  13.     propD: {
    # B+ h5 A; s' b& M. W6 t) g
  14.       type: Number,
      s; Y) e/ ^% S+ Z( d* ?3 K0 ~
  15.       default: 100  N0 A# |1 N/ v* i9 q8 U6 M8 P
  16.     },8 J+ F0 P2 s" B' _$ M: `$ ^
  17.     // 数组/对象的默认值应当由一个工厂函数返回" k, V+ h, s: Y: y+ Y' o% w0 E
  18.     propE: {
    6 F5 G  Q* r4 ?7 s1 \
  19.       type: Object,
    & i- B# d/ o$ [0 e) T
  20.       default: function () {7 Y2 @* C4 ?7 R$ J" U
  21.         return { message: 'hello' }
    3 N' ~" k1 k0 r! w" Z/ r
  22.       }6 D. U7 L& T1 k# u
  23.     },) O$ A. ]+ x$ g% Z* X' \9 o: C
  24.     // 自定义验证函数
    ' X3 Y* G. u7 L; @9 A
  25.     propF: {
    ' D) ]4 z3 b3 }
  26.       validator: function (value) {
      c1 m; p' x( Q( d- I$ O
  27.         return value > 10, w3 n+ T5 u6 s& B+ X
  28.       }
    8 M( p) \- E2 G. I; f' N
  29.     }
    # l, P: A: K' J% Y6 c. f
  30.   }" ?, U* @% ^8 F+ K7 d* n. ~4 F
  31. })
复制代码
type 可以是下面原生构造器:
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例  Z: ~+ Y; p2 {" k8 c# E* S
  1. <div id="app">
    . d2 `8 Q' F4 M. f) [# P
  2.     <div id="counter-event-example">  I- h' g7 i* V
  3.       <p>{{ total }}</p>
    1 T0 k7 h2 {3 d! ~' m
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>
      ~! d9 U0 t+ t8 ~, j7 z
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>
    " x: x. O* E0 l3 l/ e) r4 Y3 h
  6.     </div>* j7 y9 Q  h' e' C- k: O
  7. </div>/ S* Q9 V% Y- X6 O& E& O7 V3 Y8 h

  8. " R, L) {# s. M. P# V0 P  I+ ]
  9. <script>9 s0 e3 I2 ~! |7 m5 \3 ]
  10. Vue.component('button-counter', {
    $ h& F: h0 G' r$ b: R% g
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    + T/ J6 S( x) x: S- H# c& P1 d0 S3 C
  12.   data: function () {' J) [: }% G; j; e6 ]1 I
  13.     return {$ C/ K' Z" k/ L
  14.       counter: 0; c% Y1 J! G2 R. S: }/ J0 K
  15.     }/ ]+ H# ^( o0 S
  16.   },: n! w" u- D1 j1 v. X; ?
  17.   methods: {
    1 ~9 n8 X1 N2 [6 O
  18.     incrementHandler: function () {
      Q5 b9 C9 A) {! g2 A- T: J0 u" |
  19.       this.counter += 14 H. B0 z% ]7 x
  20.       this.$emit('increment')+ i5 g. \5 I2 I) o0 [
  21.     }$ S- c7 f0 y# m1 Y6 A& [8 o* J% o# ?* h
  22.   },
    5 w, \( v  ]9 T3 W5 M- Q: I1 r
  23. })
    0 B" P5 D/ E& {3 o
  24. new Vue({2 H5 i3 Y6 Z" ~
  25.   el: '#counter-event-example',7 ?- B5 e+ U6 i3 h
  26.   data: {
    0 H+ n+ V$ O( J
  27.     total: 02 [8 _+ g4 ^) x  v) ?6 R8 A
  28.   },
    " x7 }5 k  [& I  y$ v" ]2 P
  29.   methods: {+ _' z* [. J3 N$ d9 W4 V, V5 _8 R% E
  30.     incrementTotal: function () {
    8 {1 o) {) y, g. E
  31.       this.total += 1
    3 V1 ?' L; P+ z2 @! y" z( a0 t; j
  32.     }
    : B2 f* Z3 P6 ?. G) Z. A* }# G( H$ d
  33.   }
    * f+ ^% z; m8 m; ]4 l" Z  ]4 L. t* s
  34. })
    ; ~1 S: n7 M# f
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册" U4 j" T7 h) l
  2. Vue.component('child', {
    9 r/ H' e& w4 ^: G+ `
  3.   // 声明 props
    1 e. c( O4 z# v. Y0 G& v2 o2 H
  4.   props: ['message'],
    . N: R0 W% W6 J: J+ s. |( c# z
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    ( i3 R+ V; k5 [- {0 C9 o
  6.   template: '<span>{{ message }}</span>'
    : F* c* Q# Q3 s% ~9 u
  7. })
    7 k0 K9 x  I" U7 ~9 A
  8. // 创建根实例
    : z' b1 y  O& i$ S( {& y
  9. new Vue({
    8 o6 `9 t; Q# L$ X& n1 @
  10.   el: '#app',3 e3 M$ L+ h: W4 d! p/ p
  11.   data:{
    % a  r9 |1 B: x- X" N; @: o; o
  12.     message:"hello",
    . H& H4 F5 ?1 D, ^( V1 t* p
  13.   }
    % L0 ]3 D/ ^% g7 U8 ?% Z  v
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {
    , K2 s: u3 U  T
  2.     incrementHandler: function (v) {
    ( N! r0 G$ m6 d8 R
  3.         if(v==1){
    ' @5 C: _0 u; p% i. r
  4.             this.counter -= 1! F+ p8 V0 S! J  L. ?+ F
  5.             this.$emit('increment',[1])( {$ O. O' ?, f" E- V2 ]4 y+ a# t/ k
  6.         }else{
    4 H6 V& h8 O6 g3 m7 j0 H
  7.             this.counter += 16 @: ~1 S+ ^2 {- H
  8.             this.$emit('increment',[2])6 T5 c, r# I1 D& l5 z8 g
  9.         }+ r# w( Y$ N: E! T
  10.     }
    6 X4 j0 `/ D4 x, v
  11. }
复制代码
1 |( S/ }( {5 u2 ?/ H. }. ]4 @2 E

1 }3 x: h3 u: G% P5 f- }  |' ?  Q. s" u




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