cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
* i; |( k* C* L# g, C7 C* h W# t
- <div id="app"># j- }( F0 {- U$ I, D
- <runoob></runoob>% @+ B: Q0 i8 \# P, `* e( I
- </div>
! W" s4 j- t1 B - # W! `6 p& b9 V
- <script>0 w2 R" p; Y* m; ^3 j! z$ u# c
- // 注册
% l$ M- ] P. e) Q+ Q - Vue.component('runoob', {
1 [. @5 P4 a( C" @$ L- D - template: '<h1>自定义组件!</h1>'
, \8 S% C8 D/ V% E" ~ - })0 x/ d8 p( Y; a0 H6 Z
- // 创建根实例$ u$ [; p4 }! m9 D
- new Vue({$ ? S; Y$ \. H: Z" ] t$ b9 m
- el: '#app'' d: O8 C* @: j6 p4 N0 i4 l
- })
4 m9 G: r% {4 x* \/ y& X- V - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
/ k Q: ?' F4 ?5 [0 C
- <div id="app">& ]; z5 i3 q6 s! n/ ?
- <runoob></runoob>
$ r; H$ m* P% I5 U' F$ m2 | - </div>0 F: a# n8 e. I. K7 g; I
- & s" K5 F+ t/ k4 q2 U
- <script>. U+ r# C) c, E# X
- var Child = {% |; a+ N0 ~2 d/ [; L
- template: '<h1>自定义组件!</h1>'0 k; y% o+ H& C4 {5 \& B
- }) D5 n M8 Y1 n
- ) A% Z; f% H, u7 H8 { d
- // 创建根实例5 g0 G$ q! \- @9 E7 i
- new Vue({4 Q; x+ \3 I: t8 u1 o* P @
- el: '#app',8 S" Q+ z! ]% q3 [3 z8 L
- components: {+ @) A% W( K( @0 m
- // <runoob> 将只在父模板可用+ g. t2 C _2 f K1 V
- 'runoob': Child5 V' f A; Z! m1 u
- }
* k; x# S( a8 i7 ] - }); v2 P9 L6 A; {7 f
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例2 d. N3 f0 N* y
- <div id="app">
3 `% }: ^: E4 m5 x9 T. \1 d) Z' U - <child message="hello!"></child>
( ?# d0 L5 v! G - </div>& z$ ~) m: }8 [8 M' J* r; k
- ; }! y, D) F% s9 j+ I" W& o% d; b
- <script>
! Y, y. ^* M8 V4 A; I( y - // 注册
( m& P5 F9 E# _ d4 ?8 ]0 Y - Vue.component('child', {
8 m8 _1 Z# m( S: q) B% L - // 声明 props
, z3 L+ w2 k8 x" Q6 R - props: ['message'],
: B) ?/ j4 H$ \ - // 同样也可以在 vm 实例中像 "this.message" 这样使用
7 W$ j- ?' b. _0 @4 {/ N* d& T - template: '<span>{{ message }}</span>'
9 L D' d. E1 `: J( {9 A. \3 ^ - })
) h X# x9 N. U - // 创建根实例2 Q7 Y3 v# ]5 U7 @8 Z; @! n& D& n
- new Vue({' T7 c* l4 b4 W& ^- B+ I a
- el: '#app'. l2 e1 E; w0 K* G
- })5 a9 _. z. r- X! e. _
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
! y( `3 Q6 V: l9 J* Z- <div id="app"># C( B7 N+ [: @
- <div>- D. @' Y& S# e4 k
- <input v-model="parentMsg">0 X2 g; I2 a* o/ }( t9 `4 I
- <br>
; c$ r2 Z+ r) [* ^ - <child v-bind:message="parentMsg"></child>+ q( C# n0 g, c c- W
- </div>
# g8 `) O5 f& j' v0 o, V - </div>5 [# `/ k! P/ ^3 }* K
-
, i; O \( T: {& q- l ?7 S - <script>! q& J9 ^/ M* x: ^' G
- // 注册, J/ ]1 K4 a% C1 Q3 P8 G
- Vue.component('child', {' [: w; A2 p+ p% L, e9 r! `" @: i3 ^4 m
- // 声明 props y3 s) B3 Y# ^" O. g: L+ p8 y1 w
- props: ['message'],
/ U/ G- y1 B$ P - // 同样也可以在 vm 实例中像 "this.message" 这样使用
8 B8 _* u; K8 t- f - template: '<span>{{ message }}</span>'- I; i* u% M; O! e8 E2 B
- })$ Z g8 Y. S A b4 Z G/ X _3 j
- // 创建根实例
3 V5 ^; W- p; v& P, f1 ?9 Q, D - new Vue({
( K J$ i, B! L+ J) a - el: '#app',7 [3 z- L- z5 X& \* G' t/ C: J: p; K
- data: {
7 m8 E9 i; o A: U+ Y+ ~0 ?, x - parentMsg: '父组件内容'
, T+ K) c$ G. g5 u$ s$ \ - }# L* A% _! h5 u
- })! ?, D' A+ y3 m
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
7 t, [# E d d: c* h2 U$ T0 L- <div id="app">: F; L% f. {0 R* ?0 @8 s
- <ol>
9 g' V1 c3 z% c! k4 Z u- T U - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>! {8 J+ p" Q1 V: H- F, J
- </ol>
% @, _, z. @* W* ^6 Q8 G5 t# b - </div>
8 r( ]* }$ e# s# ^ l -
- u$ K0 {% j# R# ^4 _ - <script>- N, x4 G: A: b, Y% P
- Vue.component('todo-item', {
6 v7 d. ?0 n' m! [ - props: ['todo'],
, q3 O) f1 |# ?1 }$ D - template: '<li>{{ todo.text }}</li>'
& d) E/ U4 j1 R" b5 ]3 P- X - })
9 z; p; L/ Q! l - new Vue({! K0 _2 E$ O L1 G% u* t* |& L, _; m
- el: '#app',: A6 t0 T$ n2 V$ ] E
- data: {
- ?. Y3 P: z2 e' `" J - sites: [
% L, e2 u( r! h+ Y; E - { text: 'Runoob' },! p" A; A1 A Z$ U1 y+ a
- { text: 'Google' },
1 F. g* ?. J! G6 k7 Q) w" o - { text: 'Taobao' }, v& |5 W- k5 R# m/ i a' m6 f/ ~
- ]" L( t, v2 h) Z1 c; m- B, G5 y: p; h
- }
6 Y4 P% o, R" Y& |) u - })
3 Z( u' \6 j0 X7 ?/ r* I3 H9 u9 U - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {6 p$ g. T H2 L' |
- props: {
" }$ V5 f4 C4 b! f! g - // 基础类型检测 (`null` 意思是任何类型都可以)
5 W: K" N; @ g0 V, I# w - propA: Number,
8 |" C7 }) B, Q - // 多种类型8 h1 X* k- S5 P' `' U, Y; y
- propB: [String, Number],/ r) N% R1 q0 E3 L4 g2 c7 j; O
- // 必传且是字符串+ }; Y$ O' c, W. U- _# E: N
- propC: {1 q1 d* U' v: S8 _4 J( g# h6 t5 y
- type: String,
- E4 C: I( M4 r1 g+ q, J2 k - required: true3 O( X4 ]5 d8 s* Q& Z, ^
- },0 Q% V- T; h- h6 Y- K
- // 数字,有默认值: M( [" ]4 U* a D* T
- propD: {
& [$ A/ t+ a( I) J7 S. H - type: Number,( G: q( O+ _' x/ \6 h- Y) s9 }
- default: 1003 J/ u% R w) \2 s2 A [9 R
- },3 U& L- P$ ]' {$ L/ z( T8 g& `
- // 数组/对象的默认值应当由一个工厂函数返回8 x |. x' C) \, o" w) Q$ c9 L" _* P
- propE: {
$ r" w9 w: d: o) C# ^) d9 I; G - type: Object,0 y8 \$ F" C9 P- V1 U
- default: function () {# `* b, p' t3 ], U3 ?0 C+ ?
- return { message: 'hello' }: U, a2 e+ X1 R4 n% ?
- }. ]) Y/ S: E8 B2 G4 ]+ V, q
- },
! k' g8 @0 f+ ]5 B! \2 G( w - // 自定义验证函数, p' E" S4 \* J, a
- propF: {
$ N1 ~7 c" y0 w0 t- n - validator: function (value) {
2 z' K9 M# y* [) s; b" Z* N - return value > 10
# ~8 a* j, g) h' g3 @ - }
2 b. s2 V: l! |) Z) v' W3 A - }
" I( H! S- K5 [6 Q! d! e - }
+ ]6 O% S9 i6 ]+ o - })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array# Z+ F6 a9 Y$ }3 S
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件 \# x! ^9 v. u8 R m* g
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例) ^0 _' X3 b( J( E, E! D G
- <div id="app">; ?5 h* l8 h4 a& H$ i7 t9 W% A
- <div id="counter-event-example">
( |( d- v6 M8 a9 a, g( d - <p>{{ total }}</p>& j8 U/ s8 x: D3 L- i" A0 }+ H# n
- <button-counter v-on:increment="incrementTotal"></button-counter>$ C3 Y( @1 J# g! S0 b
- <button-counter v-on:increment="incrementTotal"></button-counter>2 S: H2 f @; D: V" i1 n8 Z
- </div>- k' u, {+ g6 A
- </div>
/ R7 N7 H& `. G1 l8 t5 n P% \ -
P8 L6 U9 `+ U: W" X, _ - <script>
2 Q$ q; \5 c6 g' W' D- G - Vue.component('button-counter', {% k# [+ U" G7 }, @( n9 ]) P
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
: l7 i' p# d4 I" r, A0 L - data: function () {
A; `& d: p6 z( l - return {
& T9 X1 q! x0 |9 {9 w. s( a - counter: 0( f6 E5 z! m, z- T
- }
5 J: `! L3 ~! r$ H/ F - },
4 n* ~- C: R: Y - methods: {
3 T! z0 d5 d% v - incrementHandler: function () {, v$ D6 i7 M' p( T
- this.counter += 18 T6 k& d3 \' K+ Z6 a7 H( a
- this.$emit('increment')
. _4 y0 U" g. x) F - }
1 A* t% O! o. F$ b& T1 `9 t! `* [ - },
; S4 Z' b( D0 H- R# w' Y - }): n) ~: g* [" u: b/ b
- new Vue({
. d4 y3 B! ?4 \, v9 {7 C, l# j/ w1 c - el: '#counter-event-example',
_: q" @% a5 ~2 q b5 f4 A" S' [5 J( i - data: {
; F! B: D+ z6 M - total: 0
( @ q0 `3 y z2 Z$ S2 }* t' S - },
8 p( Q. e h1 L - methods: {; s A0 I3 u, o7 {
- incrementTotal: function () {, W$ F. t* U n; v* }
- this.total += 1+ ~2 i2 N+ }+ [0 X
- }
$ E- i8 e" u7 G2 W' ]$ q4 ` - }4 [, q- A. Z. J$ G/ O2 d- s/ S
- })
3 f1 c! a4 Q4 f2 u5 k - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册
8 H. z9 h1 k) j+ W( U - Vue.component('child', {
& c+ }# x6 Y4 ~: @ - // 声明 props
# j# Z6 ? ?' C+ r - props: ['message'], I: w* A; Q+ I) O3 Y2 M* B$ [' t
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
z" P" B L: `- J4 |7 b - template: '<span>{{ message }}</span>'
5 \ A% F3 Z2 ^- t - })/ o9 i, R% p) N6 s- C# }7 u( ]
- // 创建根实例0 k# V2 Y5 C2 S# W
- new Vue({
9 t+ E. v+ ], Z3 H - el: '#app',+ Q* b# e2 ?9 x3 s; e
- data:{
& ?( D; K% T' S R& G5 a+ } - message:"hello",
( C+ g1 K( q% Q+ p* g- | - }
5 f0 P+ a3 q8 O" G: S - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
1 l) {" B# c1 ~( U. D) P - incrementHandler: function (v) {
! S; i- @+ x- | - if(v==1){# Q1 @( ^4 M$ m+ n/ w; q
- this.counter -= 1
, l( y$ W0 O. ]+ e - this.$emit('increment',[1])) H+ O& N) F/ K8 T' C
- }else{
1 y. a- s$ t% k3 `$ [ - this.counter += 17 g! L& B& s) q& N9 h
- this.$emit('increment',[2])
/ i. o9 M6 u, F( x, s1 R - }
( L7 F3 G8 a _' Z" L( ^0 t - }4 C- `, ^4 c; Q" r- x3 [! q0 }
- }
复制代码 ' `* e3 E5 q* `9 N5 G' T9 ?' Z9 p
' i; x# Q9 H5 J) @
欢迎光临 cncml手绘网 (http://cncml.com/) |
Powered by Discuz! X3.2 |