cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
' a( u5 y3 E) v! O. {5 Y: {
- <div id="app">
! K% n' g3 F( m3 z9 Z) C - <runoob></runoob>
5 p' U3 K: c- V5 Z8 Y0 b1 ` - </div>/ d" P; {1 Q3 Z
-
- ]( O, a/ P z8 r - <script>
/ D3 Q$ f9 M1 Y - // 注册$ u4 B, z$ Q( L' l5 \/ r* j+ s
- Vue.component('runoob', {% l% @. v' c, y: A3 T# \
- template: '<h1>自定义组件!</h1>'& ?- `' p+ ]" m+ N$ M3 o& Y4 l
- })1 v) w0 A M5 ^7 @0 x2 h9 \3 j: @' i, L7 H
- // 创建根实例8 ~7 q' r0 ^# n V" e) @
- new Vue({; [# W& D* Q" J3 S5 Z! s6 O
- el: '#app'8 ?" _" `& w6 R0 H+ S1 i4 M) e
- })* G' |6 C5 C! E) R
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
# k/ T- h5 h. F7 ]* W4 f# Z
- <div id="app">
& b4 Q+ a3 P) g# X+ }9 l& y6 e - <runoob></runoob>
& f$ D# e7 n/ x# E - </div>
2 }& ]9 ?4 L& n& o t - ' Z, S( X: T$ q; J+ h& O4 F$ l" f; y
- <script>
& i1 t& M7 y8 T0 S& W2 b - var Child = {2 h1 A o6 e: d! b! [- @# a
- template: '<h1>自定义组件!</h1>'
* e# b: A% s! S) u - }
! l; Y6 q% n; w# u0 f9 y2 p -
- _/ C9 ?- w) N6 Z4 G. U - // 创建根实例
7 _( }# }9 j/ w- _' P& D - new Vue({
- v$ k! Q/ b; |3 x6 [, A - el: '#app',
! U. X) H0 V$ H - components: {
; E& n5 @1 V% I# O$ ]& `( g: l - // <runoob> 将只在父模板可用7 n* Z" U9 `3 D" B
- 'runoob': Child
3 O6 E' h7 n' {0 m( N - }
- R1 x; H, o! x - })
0 W- J2 o! Q0 K3 n. E. a z - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例; W# L# w1 { D0 O! J
- <div id="app">8 N. W! n: S+ e# p. ], ]
- <child message="hello!"></child>5 r0 H0 j r8 P; u* V, U7 |3 N: g
- </div>/ Y/ w# Z6 y" B' W0 \
-
8 ~; ? Y+ P' t3 M- W8 e# A: ?: W - <script>' n3 G. `& T" ~, N5 P0 Z- r4 n' C$ |
- // 注册
% }5 N3 @3 h$ e - Vue.component('child', {
( ?4 `# u4 F% y9 r7 V( O - // 声明 props
0 x7 s3 N" X7 [( q" \2 ~ - props: ['message'],
, P8 @$ a8 k. D2 \% E - // 同样也可以在 vm 实例中像 "this.message" 这样使用
+ K( t" i B( w - template: '<span>{{ message }}</span>'1 u) x) u- n5 r
- })) ]- c8 T7 o1 e* B% V) }
- // 创建根实例
% a9 F8 Y! D# |. _ - new Vue({; o0 o: M) \) b& ?# T+ Z
- el: '#app'3 W/ Q# [' B% U" f1 l
- })+ K# D6 I( F- `! W
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例- O: L+ t0 q! L
- <div id="app">
Q! l- s% Y# k( \" k0 b - <div>( U: J" E$ J# b/ a
- <input v-model="parentMsg">! ?2 ]( b u% A# {5 p& I' \
- <br>- G6 n W" I ]0 J/ ~9 P1 ?. S
- <child v-bind:message="parentMsg"></child>
4 ]2 H S: e. O, \" x* ~ - </div>/ a3 _0 [2 d: e
- </div>
0 L0 V4 }* W9 F8 a - 6 H' I3 ~9 |: h( b
- <script>
9 R* D- y5 L7 \) g - // 注册
0 N) d/ H# L; c# U( e$ D- M; S - Vue.component('child', {' f9 g4 Y/ E% s2 P6 V# C0 C7 F/ Q
- // 声明 props
. j1 {+ ~: Z& [ - props: ['message'],. N z5 b/ x. U
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
) l6 N7 D& t# x" j: v - template: '<span>{{ message }}</span>'
" C; l" {0 P* [, ~& I$ l - })2 d" R* e5 b) N8 k8 s' B9 y( C
- // 创建根实例
& i0 A! V; l; v. G* @ ` - new Vue({
; f C8 F( r3 \" V - el: '#app',
" o6 V0 t$ _; m+ ^' x. { - data: {
+ N2 _# o3 z5 B' J4 ], {. I - parentMsg: '父组件内容'
4 ?6 p6 F; G5 }/ ? - }
5 ?0 c# `. M k+ Y U! w+ l' X - })
+ m# o' E/ a+ Y! L& I/ t& z - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
; ]) |: f9 N0 m' T4 n- <div id="app">/ e! U' h# j) h5 q1 {2 A* \! J+ D. x: x
- <ol>* i" {0 {. u7 [0 S0 t' b
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>7 | x( F* V! W1 G6 E' T
- </ol>
9 v7 R9 I* V( n7 S. x - </div>
, e4 j. s1 N5 ]$ c& |0 m1 n -
. Q0 d) k! O E _4 a$ M+ Y* G - <script>! A7 B% o8 L& ~
- Vue.component('todo-item', {
; H- R a6 x2 a) C/ M& u - props: ['todo'],
m& x% q/ b0 D; N2 _, c0 _; w$ K - template: '<li>{{ todo.text }}</li>'
- p0 _8 u" G. Q( F - })7 ^9 u$ d% q2 ]3 Z$ s
- new Vue({. u2 N7 `4 ~2 I/ e* T
- el: '#app',
# X4 X2 p( }& W) R- n6 w - data: {6 @: }6 X v8 ^- ~9 V0 \
- sites: [) p4 {; s" x% n) v4 e
- { text: 'Runoob' },+ h+ R. e' H! v, k$ R5 w
- { text: 'Google' },2 p" m& M, n' [/ W Y
- { text: 'Taobao' }, h- d/ H$ q/ e
- ]4 _6 i. U+ P! S- O/ _3 \2 s! m
- }/ i& a! u& E3 e R' Q
- })0 f5 B. f7 x% L/ A7 R) d
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {* y i% t! U& x& \0 [! V
- props: {
! X D+ g/ W9 q% }: s- }. W- a - // 基础类型检测 (`null` 意思是任何类型都可以)* F0 \- L; P4 D" r$ v( S1 N
- propA: Number,
- o1 ^( w3 w2 `& L) g - // 多种类型, | b1 Q# d, W! @, P, _
- propB: [String, Number],& T+ C3 D4 y6 Y8 ` O
- // 必传且是字符串5 F' O3 V7 R6 J8 h/ s
- propC: {, H& d- i4 m! H2 Y: d; h& M2 W
- type: String,. d7 N* |, O {
- required: true
7 G% t; r- N! ^: I - },/ A! F( x" o$ F5 Y$ `
- // 数字,有默认值
+ w: r" [8 u8 d4 D' E2 }% n - propD: {2 r/ w. b7 s3 G# L7 Z
- type: Number,
6 D& @+ ^: G/ V0 @ - default: 100
! a+ e# w/ a' z& J* \0 ~ - },
F% l; k( h) y& [& Y" K+ a: t - // 数组/对象的默认值应当由一个工厂函数返回( I4 `6 \5 i. s, c- [) g1 R% u
- propE: {& l6 e. W8 q/ j: g
- type: Object,
* k" U+ Q& J5 q; ? - default: function () {
& e1 t7 R+ {+ l - return { message: 'hello' }' y9 t4 p% X: f
- }% O( c* e' s" T6 u: d( I }9 T
- },
: r6 w1 R. }8 A+ ]4 X - // 自定义验证函数$ p1 b0 C2 I4 g& p! K: }' E& ]
- propF: {- w* g" `- z9 k/ ^
- validator: function (value) {$ W2 f3 c4 C- b1 l T
- return value > 10$ t. C1 {9 O9 Q" `( J; X9 @8 {
- }
% b3 w) W9 {# I+ S - }
3 M1 z3 m7 F0 D4 ~% c9 | - }/ T' f O$ l: J; h
- })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array" s/ J1 Z. ?7 [5 n4 E$ j9 B" h$ x% W+ a
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件7 [! v3 \0 t$ G$ r: m
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
B4 S, u4 t! p, h" z M# a- <div id="app">
* m0 A( [$ W) c, ^: O+ R - <div id="counter-event-example">
0 w2 I; w* Y6 G/ F* Q - <p>{{ total }}</p>
f) c" _5 p9 | - <button-counter v-on:increment="incrementTotal"></button-counter>8 l, D: c7 I1 `: Y
- <button-counter v-on:increment="incrementTotal"></button-counter>+ L1 r, W% ^4 ~! }: J+ u* ^
- </div>' x" |/ K; _9 K& u, E
- </div>
5 e- V, _; ?6 _ -
: r: e+ v O* Y" ~* [ - <script>
& {8 ~7 b: L* h# t( `* l% i - Vue.component('button-counter', {
& a% T0 g1 e# q( z" u5 [) l2 z - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
3 W( a! G" Z4 A( P8 B' T - data: function () {" t4 g% G3 Y/ Y- e; J7 X9 X
- return {: p# H# Y1 k) E
- counter: 0& ], {* e3 ] @7 s8 n# T
- }
/ p3 b! D' u! f) Z - },
3 H' p6 j; ~. Y7 C& l$ ^; I2 K - methods: {
* o3 }: q! T) H \! D - incrementHandler: function () {( t; |* P# P7 i
- this.counter += 1; }# ?* I. y/ ?' F: D
- this.$emit('increment')
4 U+ j+ T( s+ E2 C9 R! @' ?: b - }
} \; U `/ f( h, ^, b& d S - },' \" Z: l. J- m; w
- })6 r* Y8 A/ Z. D5 C
- new Vue({ }3 A; u; y7 G, R' r6 Y
- el: '#counter-event-example',
5 N8 Q0 a z m0 [0 G" B* U9 P! G - data: {* P! e& c' K$ v
- total: 0
) ~7 @8 L/ [& n5 _ - },
8 X# o2 w o5 V+ \' J$ W - methods: {* K3 e% g S2 x1 t: N( y* ]3 m
- incrementTotal: function () {9 C. F9 q1 Y) ]$ j8 b
- this.total += 1
& j0 [% {+ m9 J8 P& E: _ - }: Z! ? Z: t4 p9 U) C
- }& V& s* p; m% P, ?/ s0 i, K+ {
- })4 d$ g5 D5 o6 J- j
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册3 w( R3 h" l ~7 U' C$ w- D
- Vue.component('child', {* p- Q4 F9 n0 B+ l' [) M
- // 声明 props1 m' u/ p8 j6 y: q
- props: ['message'],
* w3 Y3 ^9 v: ^/ n7 ?& d- B - // 同样也可以在 vm 实例中像 "this.message" 这样使用9 m; A0 b2 k; n) j
- template: '<span>{{ message }}</span>'6 y6 @0 L* ]3 |# a y2 U. b
- })
# O, l: e; `/ d; j6 ~& r - // 创建根实例5 S! R) Y1 s; _2 w% r: X4 d* p* o
- new Vue({
( T$ y' P* W$ t8 ]! `1 d - el: '#app',
, O3 A& m" ]* ]4 v! f - data:{
# K: B5 P/ ^% u) P) M2 k: X' `7 F - message:"hello",
2 Q! a9 g6 J3 l+ `; r2 r1 F - }- z% z/ _) W; z- w% }% A& h
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {$ }0 X% C$ f$ c9 } t3 ?& I1 b
- incrementHandler: function (v) {. n! O) p! k4 u0 n' o3 `- v" W5 Z
- if(v==1){
: V N( ~8 ^- j. E - this.counter -= 1
3 _0 p. I0 v8 u& I3 n" l$ G - this.$emit('increment',[1])
5 H0 V. v. E" L) H9 u! _. h - }else{' j. u: m+ `" x
- this.counter += 1
+ M3 [) b+ y- _5 H1 l - this.$emit('increment',[2])
* }+ H! O4 J7 p# S: Z - } I1 v- Q6 l+ x5 N' c. V5 ^
- }. j+ f1 Y6 {0 o/ q2 n* p4 Q% q
- }
复制代码 3 O' U, s" f+ T( [, s6 S8 R2 i
( W+ p8 y: v+ l& r2 ~- ^+ \, X ^. h
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |