您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 11617|回复: 0
打印 上一主题 下一主题

[Vue.js] Vue.js 组件

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-4 11:28:06 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
  1. Vue.component(tagName, options)
复制代码
tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
  1. <tagName></tagName>
复制代码
全局组件
所有实例都能用全局组件。
全局组件实例
注册一个简单的全局组件 runoob,并使用它:

. o& R5 o& j0 T
  1. <div id="app">- L8 p* K0 m; O8 X
  2.     <runoob></runoob>
    6 n/ X5 k, @+ Q
  3. </div>2 |, f! w8 x( J1 U/ |

  4. % B& ^+ w. _* c% _
  5. <script>
    3 u2 t! R3 o6 M4 L
  6. // 注册
    , @/ F8 W7 {. V, W& N
  7. Vue.component('runoob', {$ d% L4 y3 M. _# r
  8.   template: '<h1>自定义组件!</h1>'
    ' W2 o5 g2 o3 t  R
  9. })
      f& |1 V# C+ E( J; g7 C. z
  10. // 创建根实例
    1 S1 X, |; T, [  q& |
  11. new Vue({1 z1 I- G/ C8 o- d* a
  12.   el: '#app'$ {/ H6 g/ y: Z7 e% P5 @% i3 L0 T
  13. })- c( j! T# \$ K+ E" A
  14. </script>
复制代码
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件 runoob,并使用它:
2 Y7 t4 n- v  ^- C' t, e# U$ v7 Z
  1. <div id="app">0 a" z( @& `5 m: C# @
  2.     <runoob></runoob>* W( r# H$ R) r& J) M
  3. </div>& M. s, s3 t7 [0 S4 r7 D  M( o

  4. 1 ]4 O2 x# y- y" H! i& l
  5. <script>! s/ X' w2 h! ?7 F. \
  6. var Child = {
    4 _6 U- Q& P6 ?% `% Z
  7.   template: '<h1>自定义组件!</h1>'3 a" |* d" L1 P( J
  8. }
    9 ~# h' J3 t/ _4 L( K1 i
  9. 0 ?% y" b8 M! C. h# _, A% ?+ K( X
  10. // 创建根实例
    # ?. h6 }3 c5 ]* J: D; p4 c
  11. new Vue({) s/ A! F$ _+ ^& B) d# I1 K2 q) |9 C) ?
  12.   el: '#app',
    , ~. {) b& W$ r  W) _1 ?
  13.   components: {$ c) \2 u; l* Y0 ?% l/ ?
  14.     // <runoob> 将只在父模板可用
    ! U- O4 B+ g  [$ y( C0 @
  15.     'runoob': Child: `- P7 |0 q3 ^9 k# E7 P: @
  16.   }5 G) a8 K& n9 G" P. r, h
  17. })
    $ Z' D# a+ f1 {9 k6 B
  18. </script>
复制代码
Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
9 j* A; Q. B+ a3 I, U
  1. <div id="app">
    ) O6 i) ^6 s5 z" {' Z
  2.     <child message="hello!"></child>
    ! R* |* E' X: @% b; Z
  3. </div>+ Y* `, d- [- \( |& l# Y3 A

  4. 6 D6 k$ Y' T' e- \
  5. <script>
    * Y2 B. \9 \: X+ Z4 }; o
  6. // 注册$ v& K. o9 w1 s; S) t% B
  7. Vue.component('child', {$ m* m& |4 L  I
  8.   // 声明 props
    ( {, E/ h* @  }  y
  9.   props: ['message'],
    # W( }( P9 }  ]
  10.   // 同样也可以在 vm 实例中像 "this.message" 这样使用' S; ^, G  f4 E  ^$ A. a5 W
  11.   template: '<span>{{ message }}</span>', Z  P& j, Z8 m; h2 T8 Q$ ]
  12. })2 N& Q, x" G; i/ ~5 A
  13. // 创建根实例& ~3 q" \; |# O$ _
  14. new Vue({  `+ i* F6 p0 ]4 m) d  [6 \
  15.   el: '#app': q' A# O; @, y9 I" q8 L( K
  16. })
    ( o7 G* s% J! h% O9 C
  17. </script>
复制代码
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
( {4 j* K3 U9 i
  1. <div id="app">
    ( B" i& I9 M% P  H9 B8 j5 B/ ^
  2.     <div>
    1 e( e4 x3 b3 d$ G3 ?3 v
  3.       <input v-model="parentMsg">& w$ [* p& m# u8 N( e+ q5 a9 D, o
  4.       <br>: T; c6 O1 ^) V# z) l% S
  5.       <child v-bind:message="parentMsg"></child>9 X# H- C+ i" `
  6.     </div>. d0 `( w0 p9 v, B0 I2 \/ i3 @* Z
  7. </div>  i* ?: q% U9 U' w; L

  8. 7 ]3 K6 S# z4 S
  9. <script>
    & Y. S# C) r4 A0 w# A! U
  10. // 注册
    $ C- X$ h, K. u1 g# |+ P
  11. Vue.component('child', {- l, ~/ a% u7 j: w
  12.   // 声明 props
    - v8 A1 x7 r" w9 J; |; K: z0 H+ X- J
  13.   props: ['message'],
    : N5 z/ s/ c6 e! x# u/ s
  14.   // 同样也可以在 vm 实例中像 "this.message" 这样使用; x/ s& \; \. ]6 ~
  15.   template: '<span>{{ message }}</span>'( M% C- l3 i6 T9 G
  16. })" H5 f' V; `. X" p  a
  17. // 创建根实例
    $ S; f' h3 s1 Y0 J5 Q
  18. new Vue({
    : X% C/ m9 K, Y  J% z
  19.   el: '#app',
      H* {3 I1 T9 ^) D! A
  20.   data: {6 z! o% b! P( p  l
  21.     parentMsg: '父组件内容'
    & ]7 W. A9 j! @% @; x" b- a
  22.   }" x9 I7 w. I9 }& e' p
  23. })
    3 M8 f5 J! W; k7 C' C
  24. </script>
复制代码
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
* Z, y* ]8 r, ]! [. b
  1. <div id="app">& }0 O+ A) p( R$ H! ]! X. ~# z
  2.     <ol>
    + j# a* x+ {% R
  3.     <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>9 Y* v* ?! i& B8 X0 D7 q
  4.       </ol>
    7 a$ x" {: j$ Q  D* ~- v2 L
  5. </div>4 v5 [# p# `/ }) E
  6. : T6 @" X' R- I- U
  7. <script>
    " Y. @# _# z& ~* E! X& d
  8. Vue.component('todo-item', {  T, }7 n" s& U, d" h2 q
  9.   props: ['todo'],
    4 ^$ c, }+ F1 c
  10.   template: '<li>{{ todo.text }}</li>'* Q9 O6 a* \. d# H* S
  11. })2 M: I; {) W2 y. Z; v2 q1 y) i! A
  12. new Vue({2 Y' R2 c6 Z3 @3 ]1 O& S
  13.   el: '#app',
    4 i# F1 f+ V9 ~3 K
  14.   data: {
    7 O: P- O, v' Y9 @1 f
  15.     sites: [
    6 J$ r7 f" l' b! Q
  16.       { text: 'Runoob' },9 T8 H0 F. J) b" S& H  s
  17.       { text: 'Google' },
    , O* {& N8 r) Q
  18.       { text: 'Taobao' }$ S% {1 {- n- {) w4 l8 x' l
  19.     ]; K9 O$ I% \6 \5 i
  20.   }( v" W' V  k2 S0 _1 i. \) `
  21. }). Z8 l% W2 }4 K1 l  I3 m4 ~" ^
  22. </script>
复制代码
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
  1. Vue.component('example', {9 G% p4 W4 |  N8 p' b
  2.   props: {: c9 j0 w( a0 P
  3.     // 基础类型检测 (`null` 意思是任何类型都可以)
    / w0 I. `( P# r9 H1 V( L
  4.     propA: Number,* S3 ^$ h5 N7 O& L/ b! `2 k1 G' ~
  5.     // 多种类型8 ^  B  C: ^6 j' s7 A; t9 [
  6.     propB: [String, Number],: _  k$ a& `0 o/ I" @$ a
  7.     // 必传且是字符串. w& W3 t  E! |! }2 ]8 A
  8.     propC: {+ C2 B& v4 V/ i& X  f
  9.       type: String,
    ; m5 U9 s; j/ y# X, v  o3 Y
  10.       required: true
    & Q& n% N) n: }/ y
  11.     },. N! f/ N# K+ X; r% M
  12.     // 数字,有默认值$ ^8 P. A; _& ~, i5 C0 m' a, Y$ I
  13.     propD: {
    . i. P1 p3 Z. y2 n& y
  14.       type: Number,
    : [2 o0 f* g3 ]* h
  15.       default: 100
    6 `% p5 ]/ ^3 p% |/ l9 b+ i
  16.     },& E+ u) P" E6 \/ K5 C( m3 l3 ?
  17.     // 数组/对象的默认值应当由一个工厂函数返回8 U) z; `' h4 j5 Z' I
  18.     propE: {
    - q7 T2 `. F& x
  19.       type: Object,6 ]  t/ H% [$ T" z7 C
  20.       default: function () {
    $ V) b) R( ?, F: n0 }( ~5 b( _
  21.         return { message: 'hello' }
    * ?) ]4 j0 e; E, u
  22.       }
    + \6 w) Y( t  ^# h
  23.     },2 k: E4 v# @) {6 l/ ^# R, o) l8 N
  24.     // 自定义验证函数1 P7 O$ t, @9 i
  25.     propF: {
    2 Y+ p$ N4 h) Q1 z  V
  26.       validator: function (value) {+ z& n0 g4 L7 T1 ~  k% Z3 T
  27.         return value > 10: E. R6 F2 Q3 ~0 Y: t' `: ?; Z
  28.       }* ]; O* z9 J8 W2 q
  29.     }
    2 `0 }0 `0 Z9 h; q
  30.   }% p; Y( {) A  k9 @& _3 y: s% a& [& f
  31. })
复制代码
type 可以是下面原生构造器:
  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array' \8 `5 b5 C# m2 |
type 也可以是一个自定义构造器,使用 instanceof 检测。

自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件
    / a1 |8 q7 S! z
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例8 w4 k& V/ o- D4 \* o6 R
  1. <div id="app">+ Z) u/ b1 P7 S( G9 N5 b
  2.     <div id="counter-event-example">; _' B& T' H4 @, ^0 [3 i
  3.       <p>{{ total }}</p>( \4 y7 O  p! ~) H# A; o
  4.       <button-counter v-on:increment="incrementTotal"></button-counter>6 Q3 t8 R& _4 n) W
  5.       <button-counter v-on:increment="incrementTotal"></button-counter>
    5 |6 h. i8 Q2 {6 M
  6.     </div>
    ' y- g: U' B( T4 e
  7. </div>& l5 i& a  a3 j( M9 o
  8. - C8 H0 v. Y0 p
  9. <script>
    % I, U2 `  U( e, B9 ^! q
  10. Vue.component('button-counter', {1 {! q( F* Z5 A2 V- w3 l
  11.   template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    # p; [; u' ~! f- M1 k
  12.   data: function () {5 t" z  m. n) }4 s" }: Z3 D% ^
  13.     return {2 ?4 S. s4 X* t, u6 [
  14.       counter: 0
    * R( A0 L. M; j! Q( G" \  R4 q. H* L
  15.     }
    7 U2 b+ v! `( [8 N, e6 G. j
  16.   },/ x# Q) T; c8 @. ?. o8 m
  17.   methods: {1 l# ~# E+ P; ~% f  B6 \* K
  18.     incrementHandler: function () {0 N; `( L9 O* [" A9 T1 g) O! F
  19.       this.counter += 1% D# }$ }- Z$ D+ x# P
  20.       this.$emit('increment')7 Y1 ?3 h. b' W5 S$ K
  21.     }
    " E1 y% j! Z% O
  22.   },
    4 F, p- n; {# E
  23. })
    & F2 x' T- m$ S! |
  24. new Vue({
    ) S0 p) l( |+ ~& [
  25.   el: '#counter-event-example',% `# R, B- i% b
  26.   data: {3 E' q7 a1 C# p# o+ F9 g. R
  27.     total: 0
    / u- {8 m, P2 w' b2 K3 {9 O/ S  o( A
  28.   },
    ' Y7 _7 b1 C6 d
  29.   methods: {  q5 b2 Q; b* z( Z2 l
  30.     incrementTotal: function () {  y# d+ D8 K- s( q
  31.       this.total += 13 ?* \. F" p$ ?* Q+ r
  32.     }3 U  C4 k( J8 i$ N0 C
  33.   }
    9 o3 [; W" u  h  [; s
  34. })
    3 L( x3 A: L( b
  35. </script>
复制代码
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
  1. <my-component v-on:click.native="doTheThing"></my-component>
复制代码
父组件给子组件传值的时候,如果想传入一个变量,写法如下:
  1. // 注册
    1 [+ w" T$ W$ `$ m
  2. Vue.component('child', {
    & N' H2 h/ q; O% {9 x1 Y0 c( r
  3.   // 声明 props2 L4 R$ t2 s+ z) n2 i4 a
  4.   props: ['message'],
    1 ]9 s  i2 }7 y. q6 n+ ~$ Q0 \
  5.   // 同样也可以在 vm 实例中像 "this.message" 这样使用
    . S5 t6 L, u! c+ Z
  6.   template: '<span>{{ message }}</span>'
      l; O5 {" O  q- B* f/ o
  7. })5 s2 }! F. q; \; u
  8. // 创建根实例
    + _* r9 R3 E4 Y/ R
  9. new Vue({; ?$ m/ U8 `2 J' @( l' t5 ~
  10.   el: '#app',
    1 P2 T7 [- q3 }+ l( E  g+ P
  11.   data:{( {5 Z0 O0 ?1 a9 J3 w( e% A
  12.     message:"hello",3 c! `6 r" U, J# K  H% r6 p6 ]( C
  13.   }# U5 i' K# q, N8 C! a& a( g' a# [# ^9 b, W
  14. })
复制代码
子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
  1. methods: {8 k! q: `, T' f9 G+ b! y1 w
  2.     incrementHandler: function (v) {+ `3 V7 ?; {6 X% C
  3.         if(v==1){
    0 I( q  D! L( Q. O" l
  4.             this.counter -= 1$ Y# V: A* d9 z1 s% Q* W
  5.             this.$emit('increment',[1])
    ( c; [( O1 T4 o. p. c! b8 K
  6.         }else{4 L' _* V8 T" _2 w7 p
  7.             this.counter += 1
    . {! n! f$ J& w
  8.             this.$emit('increment',[2]), N( g  T4 _. k1 @, g( {" q! l
  9.         }& G: Y1 L' C# T5 S# S
  10.     }
    ) p3 m0 Q7 A) W0 a
  11. }
复制代码
" ?) F: |; E6 w- E
9 g0 h3 [, ~4 g0 J
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-6-27 05:30 , Processed in 0.278067 second(s), 69 queries .

Copyright © 2001-2024 Powered by cncml! X3.2. Theme By cncml!