cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
% K1 R$ E1 f* m# M
- <div id="app">4 V- F2 s0 D* L
- <runoob></runoob>% N2 _1 o0 v8 H- l. V: g
- </div>* |2 m. u# N7 ?
- 2 ]6 `" R5 C: k$ I$ Q
- <script>/ C& H9 j' O, g' V+ c1 z
- // 注册
/ F. q1 `* V6 S8 U5 M - Vue.component('runoob', {' c4 z3 G4 g6 G
- template: '<h1>自定义组件!</h1>': T8 r# a* } S5 ~
- }): E* r# b7 o( Y: K. p0 q
- // 创建根实例0 A2 D9 ?8 D' g4 k& V
- new Vue({
* y2 k# n% [6 e2 v3 G" Z/ Y - el: '#app'
1 e6 r# N5 S) i1 i$ Q4 Y( ?4 k - })' ~2 ~3 M0 }. ~* D/ h- d5 U
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
1 A- _* v" n2 f5 g9 P
- <div id="app">
! t0 C8 c. @5 H4 \* g3 U% k' } - <runoob></runoob>
! g7 e0 j- l# V" X - </div>
4 a- e+ e4 u( G - $ b5 y) A2 h' s9 J/ x
- <script>
2 g9 ?! H" }1 H1 H. _. C3 s - var Child = {. _( D" Z5 g; Z! B5 X7 |- S3 x/ Z
- template: '<h1>自定义组件!</h1>'. \1 }# m, F3 S5 S4 K
- }
( Q; U$ }8 l+ |- B; o* w; f -
- j% ?! E; o5 s: x& P/ z( U; h+ { - // 创建根实例
9 B. _* i3 Z/ T! ] - new Vue({' a; I! e" S5 |& r& u/ G
- el: '#app',
1 @! D9 T6 p5 ~4 B. A3 t - components: {7 ^) e. O) s# C% I1 C
- // <runoob> 将只在父模板可用
+ ~0 _" Q7 s1 f5 b/ l. i - 'runoob': Child2 G* ~. o0 c6 ^: e" T" ^/ G
- }
`: _6 z, _# k& `0 q: w - })
) T& t; c* C$ J: Y, _, T - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
' Z. Z# B+ f" u1 h- <div id="app">; h: k7 E$ e/ }! Q5 Z
- <child message="hello!"></child>
& r) V5 k; H" g* n! W) @* o - </div>: d' C" `* c/ P$ G0 t9 r0 A3 T
-
# o7 t& s2 f# |/ H& S; G - <script>6 s# t9 I$ u, ]" n$ z
- // 注册; N+ H6 N5 Y1 Q( c8 {0 t0 f
- Vue.component('child', {
9 n) E, v! U$ i% g& I4 h1 k - // 声明 props3 u" p* e7 k4 A% I, w1 H
- props: ['message'], W3 ]. F$ L# i- J
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
/ E4 \/ B" B7 @- }% e* m3 V- ~9 c - template: '<span>{{ message }}</span>'" Q( k0 c4 U' k1 X$ j
- }) m9 D- \- {, Z1 g" [1 V/ I
- // 创建根实例. M6 |- i- g" R G0 I# e
- new Vue({
" Z2 {0 p" v8 \: T$ m4 `# {* g* @3 K+ u - el: '#app'
1 r2 ]# Y5 M* {( X* F) h) ~ - })
& c+ ~; S J( n- p, {3 r, m) ?$ T - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
' T4 {/ H- T0 k9 R \* {- <div id="app">( S* d- u' g8 ~7 P: {) @/ A" ?7 C( G
- <div>
7 L" L, D K5 y- z1 W - <input v-model="parentMsg">
; g) b" l+ @& B - <br>
; r" `$ I7 V3 E, f - <child v-bind:message="parentMsg"></child>
8 K2 x# `. r& R9 `' R: [5 |8 d/ d. X: B - </div>8 D [/ j6 g3 |
- </div>
; X* @- K$ h9 f4 | - ; b' O1 ]- m- j7 ~
- <script>
" V3 f/ {; ?3 y! D* l# m( U - // 注册! I' F% K( W0 l
- Vue.component('child', {
1 U8 r/ }, R) S2 _9 _) {: K0 v1 I+ k: M - // 声明 props
; c. _# f' O; U3 L2 Y - props: ['message'],
) a( r7 w$ \. h! a" X7 d% t+ ~ - // 同样也可以在 vm 实例中像 "this.message" 这样使用
+ B. a' h; ~# ^: d" ^' Y* X9 R - template: '<span>{{ message }}</span>'
" @# _6 t, p6 h- W: I - })
O5 k* ~9 C; { R - // 创建根实例
% p$ q- B; W4 u2 A3 n% a7 P - new Vue({3 K0 I7 a# e c7 F0 P) o/ |5 H; A
- el: '#app',
" ]( j& }5 I3 P2 I$ D% B; k - data: {" ^2 [2 z# \+ ~ |
- parentMsg: '父组件内容'# p4 `1 a" B- a3 n- p/ {
- }- g7 t i* Q8 F/ \' ^3 G
- })
/ L1 u# p% r( R' g - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例7 A# k4 `) c `# c! K
- <div id="app">& L; Z: I8 m6 t1 ^
- <ol>$ u' v3 h+ p+ o4 E7 S
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
5 {" @8 R5 ~: ]- z0 M5 R9 R - </ol>) k( a. s/ s O& l) A+ O
- </div>2 q3 k# s; P5 r- ~0 n. H/ X2 g U5 b
-
2 @1 G6 L! a- k+ |- J' [6 d* k' w Q - <script>; U* ~; x, @* \ n
- Vue.component('todo-item', {. J: |( p2 B0 N3 }
- props: ['todo'],
+ h. b& c6 P' ^+ x q - template: '<li>{{ todo.text }}</li>'
; {1 O" `/ W8 H6 ~! U - })
+ X* N, z9 X0 {) i6 n3 A$ Z2 X - new Vue({4 Z; g5 `& I$ |+ @# c9 }! d
- el: '#app',* G4 I9 M, f* }8 M9 L3 r0 n3 Z
- data: {
/ I/ y, m% N: q7 b& T0 d) p - sites: [4 f, P9 F: u% p+ E1 i8 p
- { text: 'Runoob' },; `# E/ G8 L8 B
- { text: 'Google' },& O8 O' W( A" b# ]1 O6 t
- { text: 'Taobao' }0 l: p9 K! Y4 d
- ]6 i6 e& @& h7 K; F9 q
- }
8 n" V2 U2 ?1 T4 Y, o9 s8 _ - })4 v G- O8 X' _
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {6 w, d3 M% p3 r! N3 }
- props: {& \) k, v/ g5 L8 C: C; W& B
- // 基础类型检测 (`null` 意思是任何类型都可以). d0 s- d( r3 w6 P+ a/ Z) Y- \8 A
- propA: Number,0 u8 Y. h5 e7 y) w. t% G, G
- // 多种类型
$ v' a+ d3 ~7 a5 N - propB: [String, Number], e/ s1 |) k! W
- // 必传且是字符串
' j6 T! k: e" N& q0 Y4 }0 d8 K - propC: {
# Y. G E: J+ q - type: String,9 i4 T2 E. r% N" U r: K3 z9 F! n4 h
- required: true
1 A2 x! A6 z, M9 r6 `% p h - },
6 P: d6 L% g0 x9 r4 m - // 数字,有默认值2 k8 z/ [0 Q1 V" @7 o2 [( r6 X
- propD: {
- D2 o% ^ X$ {5 \2 O* q7 h3 L7 ? - type: Number,# @" b0 C' C" P2 z. n
- default: 1007 a! K* [) l u! U5 {
- },
; Q1 S S1 _$ _, }( f5 ~3 _3 E - // 数组/对象的默认值应当由一个工厂函数返回4 A% i! Y% M7 ?2 j% l
- propE: {2 W$ Q4 t* k3 [" H+ M! d
- type: Object,
/ | q% M4 |5 l1 j) \ - default: function () {
( B. l5 Y$ t4 T: K - return { message: 'hello' }5 q# w6 c3 ~9 t7 \8 I* t$ [0 u
- }+ g% i* \2 S, P
- },+ y- P1 y% Q+ `: g: Z
- // 自定义验证函数
7 k" Z; |$ o9 _. Y - propF: {
' {& E7 m( U" ]* D4 s2 q - validator: function (value) {
/ ^% ~5 D# j$ m6 w6 v/ s - return value > 10' h6 c% y' P: r0 `0 u5 e
- }
8 f: s4 P! R9 y# l T - }
0 p& i; \% G. R! J% m x - }$ c* D3 [( F T) E
- })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
7 d; g3 A' J5 |* Q3 o/ ~- v" M
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件 B/ y& T& I7 D& ` x! w
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
# m3 R: d8 V% i, Q0 A- <div id="app">
: T: I; c7 J/ D/ o - <div id="counter-event-example">( w6 p" S! [2 G$ q' I/ }4 j
- <p>{{ total }}</p>
: d$ v3 L8 j: L" `6 ?, S( s - <button-counter v-on:increment="incrementTotal"></button-counter>1 s+ E( O+ y; x0 q
- <button-counter v-on:increment="incrementTotal"></button-counter>
. I, a+ u$ Z0 G+ K - </div>
8 F* j) n1 x6 h" ^8 z - </div>
: V4 C2 i1 F# k4 g; k" H9 i - / u; U* Z y9 _5 K5 T* ?
- <script>
' N3 p {; R% J7 } o7 F; W, ]! H& \ - Vue.component('button-counter', {! I0 b9 ?" g2 k, S
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
3 k ^3 v% e6 ~5 I - data: function () {/ s6 E! S" T+ J1 I8 x" v- w
- return {
4 C& q% ]4 N$ P- e% i9 `$ e6 Q* I - counter: 0
5 X8 B1 N1 S' \5 |4 m$ ^ - }, v7 {1 I. r8 T; p \8 n5 C4 n2 X
- },( \7 D' q, s/ Z8 W' W3 P# v2 s( L1 W
- methods: {
8 f9 W s& m8 `* m, R - incrementHandler: function () {
7 v1 v3 y* e2 [ - this.counter += 1
) u7 U& ?7 M, _ P& N& o4 S - this.$emit('increment')
& J9 _& d# n* m& M$ M6 k - }5 ]! N9 ~% I$ `7 W: U
- },
& p" S" u2 @9 E8 ~' H# }; c - })
) G9 ?4 N4 ^; j - new Vue({
0 w7 F$ J- j- M0 ^ - el: '#counter-event-example',% c8 J% r* c0 S) k9 R
- data: {5 r& W! w- c j* O6 l; p$ q2 b
- total: 0% F( x! I- x+ I: o
- },' N4 A Q; x( N3 l% o* \
- methods: {
: j5 l1 e' g: W2 n# t( f - incrementTotal: function () {$ e# X: x o% y m
- this.total += 1- a1 Y* Y. p, b0 h6 _; S
- }7 U9 @1 h3 ?, c8 }2 H' W
- }, Q2 i1 R& G0 g' A# z: T2 ?: C
- })
$ B) r0 N" P. A: T7 } - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册$ d) ]' g3 i& H( ?" L; Y4 b
- Vue.component('child', {
0 b4 `2 B3 k" ^* ]9 C) | - // 声明 props v( a7 s$ F1 S- R2 _9 V" c8 U# Y) G
- props: ['message'],
4 y' G% o3 F3 o) }4 D; c( m5 O4 _ - // 同样也可以在 vm 实例中像 "this.message" 这样使用 c. _ w8 S# r) }1 L3 \
- template: '<span>{{ message }}</span>'4 t x$ l& E1 J+ Z$ r% N+ b
- })+ Z0 ]) ], }- _& x
- // 创建根实例
; e3 F7 {* m. Y: k- i( K: J - new Vue({
# e2 H9 x4 w( ] - el: '#app',
, R; c* S, [: d; i5 [ - data:{
! g4 H- ~/ \* ], { - message:"hello",, S U2 w% c% }0 n% R
- }
7 I T6 t1 N% m3 g5 s% j - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {' Q' d# D3 U2 J! X6 |$ r* c
- incrementHandler: function (v) {
, {8 F/ Z$ y' |) q& C - if(v==1){
5 `4 `& p5 O x' o, C - this.counter -= 16 _) r+ O: y, C5 U+ t! a8 `% U, l. h
- this.$emit('increment',[1])
* x; ^2 H' b* W - }else{) Y: B% c0 y$ b- m
- this.counter += 1; d& t" [$ H) i) ]* [# G$ f
- this.$emit('increment',[2])
/ A1 I; j3 { R: I- [% _( e; N. W: B - }! t) R l$ y0 ~, E
- }! R& h& y1 L* }* w: f" B; l6 \- s
- }
复制代码
3 c/ d, T; ]5 R3 r
B6 j# s; n2 n, W& S9 P
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |