cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
. E1 ^9 T/ T* ], h3 X- <div id="app">
+ G3 o, l1 k4 u3 S5 u$ A; G" l - <runoob></runoob>
. i3 p3 p; I- `8 D, y - </div>
- G) W: I& {" L( R7 g -
2 I' z$ V& O$ l# o6 Z+ I) r. O - <script>+ U% s) {# n$ |% V( L
- // 注册
0 Z4 \+ u7 z& F9 ? ~ - Vue.component('runoob', {
I: {/ H& Y' J) l0 J+ D& S - template: '<h1>自定义组件!</h1>'& t# M' t b! R- S
- }). P; T' L0 r! C! `0 H( a6 o
- // 创建根实例
/ X' f+ ?# a4 g. @ - new Vue({
! g5 H( A8 \% _' i - el: '#app'
% G; I, \9 v) ]" L+ f0 F - })* K! E7 e a& I
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
1 y' [6 P( C9 o- <div id="app">$ @' f) J, Y- v
- <runoob></runoob>; S' g$ g8 j4 \ w: X+ k
- </div>. V+ ?$ ^2 v( A K' X4 _* S1 E7 X
- # D! k# _( y/ |, G- g; r3 _0 _
- <script>, Z/ b% ^* {, _3 d5 l$ U4 P+ x7 O2 j
- var Child = {
7 v6 k5 o2 ~4 T" c8 F `7 _6 P V - template: '<h1>自定义组件!</h1>'
! W2 o* n5 h. ] H, o" Y0 `8 J - }# o ~3 ?1 F( K1 B6 Z6 }1 r
-
( m F1 t7 v: R; R& L5 p - // 创建根实例% V) h: i! a6 d5 ^( I
- new Vue({
; v. l) M% R, g/ q: l* e" ^2 c - el: '#app',, R! Z& [" _7 ?2 d" I7 k
- components: {
- E' U8 J- d* B. q' G0 { K - // <runoob> 将只在父模板可用% o7 L: A3 l1 \/ {6 m
- 'runoob': Child
* _3 Y+ n9 W9 s0 h* x8 Q - }
, B( D9 y0 c. \8 e' A - })3 s% b z# H F7 `
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
0 W6 l/ M0 R% G% D/ W- <div id="app">! n0 D7 a) T. l
- <child message="hello!"></child>5 ]# k; W0 k9 k2 Q
- </div>
' b* M) v1 x8 n/ t4 i( [8 c/ j# o - 1 q* A ?: F$ x" | X+ U! |- Q" y* q4 `
- <script>
: I! C: }% h0 a9 Q3 e! b8 q3 f0 C - // 注册: U9 A' L- s9 d4 M( T
- Vue.component('child', {! O5 P; c3 V k0 Z0 R
- // 声明 props/ N1 C, X1 A5 l5 S* h) M. Z/ L. `
- props: ['message'],2 |% L' u0 B( R
- // 同样也可以在 vm 实例中像 "this.message" 这样使用1 ~' j$ w# R7 n5 T3 W" \/ F
- template: '<span>{{ message }}</span>'1 C# |' v, V% J) G- g
- })
9 W0 c5 k$ Q' J: B5 n - // 创建根实例: V( h8 I1 L b# v4 `2 a9 z
- new Vue({
5 H, `# I$ w' U2 [- u - el: '#app'
4 q1 \/ U; ^; C4 N. _/ ^) g0 _$ d - })
8 B( I# ?4 }* }* a! n) y( X2 t - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
& X3 D; g0 U" ?/ H- <div id="app">1 e& C0 _8 \' Q" z
- <div>
1 S$ ?: e$ ]9 m" Y - <input v-model="parentMsg">& z" c1 t L+ _
- <br>4 g( X! @; e) z8 D% P
- <child v-bind:message="parentMsg"></child>9 W+ i" v% ^% Z! b- k2 h: X
- </div>4 x m* E' _( f; b# B
- </div>
& E' b0 a/ F0 {9 h+ U( j - ' d' g7 h- f0 q* u/ Q$ I6 I4 \6 [
- <script>6 Q+ ^2 |& p" W* c u$ ^) ~
- // 注册
1 S, i* i; i- A% @, V: w7 G - Vue.component('child', {7 w( ]( f6 m- W3 y M# x
- // 声明 props3 C% q h1 |% ~0 f, ]1 ^! V- b
- props: ['message'],
: R" z* }% X u5 @ - // 同样也可以在 vm 实例中像 "this.message" 这样使用% o. X# I m4 b
- template: '<span>{{ message }}</span>'$ r) @- J$ X0 w$ B( D5 y9 v7 j* `
- })" a& H _% c+ m* [! r) x
- // 创建根实例
8 k7 _/ I" Q: j( V q - new Vue({
9 r6 n- i: P. l) Q - el: '#app',4 }7 s: b3 I) {+ y* l3 Y
- data: {' A" r, t/ h" C- g3 T6 L
- parentMsg: '父组件内容'( l+ J5 } X1 n. X* W) N# X
- }' K; C+ n# j- b+ r
- })$ @8 o5 p( j1 z3 s( D2 q" r1 k
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例) I, G+ D: {6 V
- <div id="app">0 x/ R7 o" s: |1 {3 v, H
- <ol>
4 `, j) _* z* l/ C& R1 L- b - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
3 s! }) m! z6 n: _0 y" q" Y" \ - </ol>
- A1 m5 h6 a+ }7 K7 R9 m+ ~ - </div>& \8 s1 k5 m3 T4 t3 G
-
/ A, h6 ?7 B& ~5 G/ e& } - <script>
: {0 {3 O& n: t! a9 m - Vue.component('todo-item', {; v0 I) Z0 U$ a: s8 |: p: I8 D
- props: ['todo'],- D9 Y' r+ g U! s7 J" Z
- template: '<li>{{ todo.text }}</li>'
$ d" O; P" n0 _" K& r0 g - })& O/ y& z6 v% Y% q# S
- new Vue({
5 o' c% \/ @6 b p2 S* F8 R$ s) u - el: '#app',
7 W7 K* a3 _* a' \& D3 | - data: {% l3 I' U7 ^' V- T
- sites: [
# T0 o4 {8 [5 R T: ~ - { text: 'Runoob' },5 S5 R. f; O# h5 `! c% ]& S
- { text: 'Google' },
0 T9 W- r0 s2 N5 @, @ - { text: 'Taobao' }4 q6 o# [# |' c6 y7 Q/ s) I" a
- ]
8 G0 w! ~+ R! m5 k- Z - }
$ L |( B: h: n - })
! s$ J7 Z- q, i6 \ - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
# p4 c4 a4 u' ~6 o! S9 ~ - props: {* Y8 L, b$ S1 d8 @5 D+ P3 A& C
- // 基础类型检测 (`null` 意思是任何类型都可以)
0 _( x/ e3 E' D7 b6 Q9 ^ - propA: Number,' R0 H) p7 J0 f0 q! H+ L) L
- // 多种类型
, g+ Y! \( V7 @1 O/ G - propB: [String, Number],
, W* A+ S+ z0 E( }; s" R3 n) i - // 必传且是字符串
5 Y( m. \/ l' L. ]( V - propC: {9 ?( Z# n. [* n; i/ O3 ?3 X* f
- type: String,- R+ E0 F& `$ ?" X
- required: true
9 v; t! q' R+ N' E7 x+ q - },# ?+ v, Z6 _% w& d+ x( y; T
- // 数字,有默认值' V. I s0 y4 f5 ^) F/ b/ x
- propD: {
" @$ r3 C# I V - type: Number,+ d S6 c/ o, @* I& z# a0 _; P
- default: 100) L% M1 i3 L. y' W/ }
- },
5 E8 A5 H2 o$ A6 n( ~ - // 数组/对象的默认值应当由一个工厂函数返回
0 W/ R9 f ^* R- B% t5 ]; x' q - propE: {1 I4 G0 a" s( y" Q
- type: Object,$ I* X9 f- Y: |2 Q& t, g% Z! y
- default: function () {
0 W3 O3 ?% y1 ` o - return { message: 'hello' }4 r* y5 X# r% r& K( ]! |
- }* T8 c5 m; ~) g u$ B* o3 r
- },. |( @: [9 J. g" I2 u
- // 自定义验证函数8 o" q, e: O0 P' I
- propF: {, T2 |0 @ P* ?4 q" }# e& i
- validator: function (value) {; ~* j% I; Z0 b' L2 C1 |
- return value > 100 L% m6 h4 m! Y, A4 ^/ ^1 {
- }+ F. T) q( z2 M8 W# n# @- `) E
- }% L/ u z7 j% k6 ?" ?
- }
$ [. N9 C! N- ^% h5 r0 E9 ~( o7 G - })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
5 [" X" K. T3 {9 J' |6 _4 m
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件* @: F- }5 I! [5 t2 n
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例& g$ n# a/ \( I& n# n- U* V/ I
- <div id="app">
5 J/ h! k) u2 o) t1 k) L7 P - <div id="counter-event-example">
2 `( i0 x- V; O9 J" `% D - <p>{{ total }}</p>
% T5 }# I8 V" W- n! ` - <button-counter v-on:increment="incrementTotal"></button-counter>
% Y, V& m2 d0 c - <button-counter v-on:increment="incrementTotal"></button-counter>/ v7 P: ]4 H8 Z( H- `3 I
- </div>
! d0 T/ [/ H7 X) L - </div>
; C' d3 {0 S$ ^/ R5 c7 }! u* E1 ~ -
3 c B# O: _2 Z7 H1 S r. ]0 S3 c - <script>
0 C$ |! r3 m. M* x - Vue.component('button-counter', {/ k; D! Z4 Z4 H% t3 d% H# O
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',, j1 z$ A% W' p, A7 Q9 b
- data: function () {5 g/ v. O" N, @9 R5 ?4 P# t0 m9 y
- return {0 {0 r+ G5 u* g# J7 |
- counter: 05 P \% c. x# P7 K/ O+ o
- }# }( ]+ ~8 Y6 T% o& C4 L0 b$ T% o! O
- },
# m3 T5 h% R2 Z% r0 C - methods: {0 Q4 x1 I1 [( U
- incrementHandler: function () {
/ r0 U& T8 \; ?. v. q) L6 ` - this.counter += 1/ G' L; s+ \7 p V) V4 c
- this.$emit('increment')
) v6 O" K: c2 \5 F$ z- ^1 i" s - }* `8 T1 D* {1 @3 {, y3 w3 A( V
- },
" U) R, v0 ]9 u8 m - })
# }6 Y% w( c/ S5 @3 T$ f, m - new Vue({
6 V6 E( X+ u1 a6 N. }, g - el: '#counter-event-example',: z$ F, J; L( n" [, t% u
- data: {+ n% X0 r& m; a: W
- total: 0
2 C9 _8 C2 h! e9 T" l! ] - },! g0 i$ a( W; i9 {# ]
- methods: {! H$ x) K- X$ y
- incrementTotal: function () {
6 H7 I+ o4 ?, p$ a5 f4 I - this.total += 1
8 [/ C& e: ]- \ - }
% G" {6 R" e3 w" I q - }
. z) i. k4 |7 x a! H; o - })" \* ^6 W: r7 U" U6 ]
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册
; K1 ]0 ?6 E6 q' _: K - Vue.component('child', {) n1 Y0 C1 c4 J" G( k' Q
- // 声明 props+ D7 s; A+ I' x. O0 x
- props: ['message'],/ \8 Z/ d: V) k0 D, h
- // 同样也可以在 vm 实例中像 "this.message" 这样使用5 v1 `+ D9 q- M5 T
- template: '<span>{{ message }}</span>'* G( O3 [: Y; ]$ m; l: O( L. ^
- })
# _+ C* T4 n* k2 G9 u7 t& o - // 创建根实例
/ _4 c9 Q: M7 h8 e# | - new Vue({
$ Z- O/ E* G7 O3 [) Q3 Q) ` - el: '#app',! f0 X1 u) I! A- b4 c' h
- data:{" _5 u; Q) q" d" @( `
- message:"hello",- g- `; s2 i4 H( M! D) N3 s. R
- }' G% p/ s) h T1 [; R! v: B
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {" Q7 g% k, H4 M
- incrementHandler: function (v) {* I; E0 o# ?( z# w" ]+ ~" F. t
- if(v==1){
7 c! L/ Q. l/ d; M5 k - this.counter -= 1
% {; k7 t. x' g: H$ F0 W; q - this.$emit('increment',[1])
( L' M1 @8 i( V9 { - }else{
5 d) u* Q( K1 G7 @% ^" s: ]$ ~ - this.counter += 1
4 z& o# m, B" L) J. R - this.$emit('increment',[2])9 ~( R2 Y% j' K( A8 y4 n5 R: H% a
- }$ p9 Z5 ^% Z$ u8 B9 {+ d
- }' X2 Y t- F P8 Y' }* F
- }
复制代码 ! ~, I3 G& [1 B) p6 c H
% q" u4 a5 H `: i
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |