cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
" P6 v, K& w9 i2 b" g
- <div id="app">
/ g$ U9 x9 i1 N0 I/ P J6 a# q - <runoob></runoob>& C' Z. Y' w) F9 a8 z- L
- </div>6 [2 O( s: B3 y |+ o v
- 7 d; k& I, S: {
- <script>
# k# X2 H/ Z1 \ [* \' W/ _ - // 注册 t# ^: Y8 A% a1 k4 o0 A4 m
- Vue.component('runoob', {4 n" K+ J8 ?! z5 r0 }
- template: '<h1>自定义组件!</h1>'
4 e; I0 ?3 |9 W' ?3 p; o/ Z5 e# t6 z - })
- q; K7 ?- x, x' C9 b+ m4 V$ F - // 创建根实例
) P) ]% K- s) }7 P5 t4 J - new Vue({, I+ X/ d) i, e* _6 ? k
- el: '#app'
2 E' \1 \8 I9 y3 h' E - })* M8 s2 C* k: K( l6 _
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
7 M0 S+ \8 W% L' k! t9 t# G0 r
- <div id="app">7 E% _7 g6 h5 q2 g5 p! p
- <runoob></runoob>' S3 P' r; {* V9 E4 A0 _
- </div>7 \7 S! K5 h3 U$ [9 U
- 1 M! }" }$ G& J$ C+ ^$ }
- <script>
, G) T* g) U5 {% o - var Child = {
# p) [8 S0 b7 r/ S K+ t+ A& X - template: '<h1>自定义组件!</h1>'7 a9 j' N0 h' g6 }% V1 a$ t1 F2 c1 @
- }/ [3 x/ H7 O: K. ~' W' v7 \
- 6 c4 }, P3 |! I5 H4 `. g
- // 创建根实例
I* z' f) D: C; w5 f/ x3 I1 } - new Vue({" b% g- f" |9 H6 W
- el: '#app',: Z+ `* a8 ^/ B( a# B' t
- components: { X; f( q9 Q( s9 i3 B0 [
- // <runoob> 将只在父模板可用
+ J9 C+ i" J3 Y7 R- S3 | - 'runoob': Child
$ J% X( K' P( \5 n - }. e% p7 l; L- D
- })& e" l% t8 S8 d' V6 Y0 i Q! H
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例! M6 b2 H; C* f6 V
- <div id="app">
7 g5 d y. _' D7 l" r1 ^ - <child message="hello!"></child>* r! M- Q2 I) z) v1 m: L
- </div>7 l8 T1 `4 ?; n' A- ^
- 1 U4 f& M3 `- P' r/ u
- <script>& v. d, e$ D; g5 q
- // 注册; _" y- l' y- x& v% }0 k' K t
- Vue.component('child', {
) k# u; F+ i" F% @ ^ - // 声明 props9 ~, `# g% [ {, Q& `+ y& H) ^
- props: ['message'],
* {& y) r6 y. N4 f7 k- M - // 同样也可以在 vm 实例中像 "this.message" 这样使用
; `: F+ V- j5 } - template: '<span>{{ message }}</span>'
, T$ {0 ?# f# n$ }, ]5 c. G) h - })
4 z- _3 b4 \+ w& V/ d! R - // 创建根实例
- P# |: L+ K8 c - new Vue({/ F2 y/ I: [+ o; U5 f
- el: '#app'
& D9 w* K) h% n - })
/ H$ V5 n3 m4 Q, @ - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例3 x! H1 y) _: b" n7 V2 A$ B
- <div id="app">
( H+ |8 p$ D9 ^( H6 q' c3 }7 E - <div>
9 O: V0 P% @; D9 e7 {7 \5 X% n0 l - <input v-model="parentMsg">
" Q0 l0 q/ C e+ R4 p - <br>
' l& B: O: H: t7 {" d$ F - <child v-bind:message="parentMsg"></child>
5 o( k6 p0 d7 z7 Z - </div>6 n3 R7 F1 w2 g2 A& K i1 P# K
- </div>! p0 r0 u9 I# ] m3 q0 V z5 L; ~
- 7 o* W# I5 e3 c' Z
- <script>
4 O% [' w* U' z u4 U - // 注册3 D {* x% O8 [) M- A
- Vue.component('child', {8 {! y, Q8 h+ k! {9 x' R! v$ p& o
- // 声明 props
$ a9 q0 ^+ A% }0 @ a8 N& Y; @ - props: ['message'],
# `8 A! \( p8 Z - // 同样也可以在 vm 实例中像 "this.message" 这样使用
2 I6 A( ]* i- d! h& ` - template: '<span>{{ message }}</span>'
2 l8 |' w) U( g8 q9 f - })
. O9 L+ r. ?+ T I/ D - // 创建根实例
+ o2 e/ F. Z* f' |+ a7 R - new Vue({* \+ \" l/ ]% ]% c5 e8 Q
- el: '#app',2 E% P6 c% R3 Y# n4 w
- data: {7 D& S0 x. A$ r. Z( W: f; ]
- parentMsg: '父组件内容'0 `5 X( v& O9 Q( T
- }! _+ u$ x& A" e- t3 A" @, u
- })% j" @8 H& M5 @% t* T* ]9 V \
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
) `: Y7 i* Q$ j+ Y- <div id="app">: G8 I" o# S/ U `' u# ~! W
- <ol>( ?" C( g) ]8 l5 ~' G/ D% m
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>6 f$ x: N' h; S8 ?: u" X- [& j
- </ol>, D9 z3 v4 B; Y2 D i3 [- g8 A# z
- </div># I/ d% f8 z' A5 f o, k- Q
-
$ \+ C& L7 l' x1 a: G: V - <script>
! M# b2 @9 O1 g& @* F' v2 y4 }) u# t - Vue.component('todo-item', {
5 d7 z& h* w/ K: K0 w: a7 N - props: ['todo'],
7 e, } o) X+ }- n0 K+ f0 z: M - template: '<li>{{ todo.text }}</li>'# n& c7 j, J* t# }
- })$ I: c0 n! a# a1 T+ P- t2 C
- new Vue({9 m \) E8 Y5 t1 ^7 G7 y
- el: '#app',
2 R4 N4 m; c" c0 a- g - data: {
7 X* v& {2 @ h; I9 M - sites: [
- p2 w6 z( V, ]& n: {% ^ - { text: 'Runoob' },
+ E# y- N0 w- k# a" g9 o - { text: 'Google' },
& X T, w1 Z3 e/ c' N% q5 ~: w - { text: 'Taobao' }
7 F" i# |8 n2 m- o - ]+ l$ F* b9 ^- N3 A8 ^+ i
- }
6 [+ o7 a8 p) i3 f4 E - })# l4 Z/ j& t' |6 I7 T% X% G0 E
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
% v3 W) }- ~# |# b( ]- Y - props: {
5 {2 {% J) |$ ^. c1 _+ s5 K/ } - // 基础类型检测 (`null` 意思是任何类型都可以)
# ]% d0 i) e' K% n8 b* e$ H: } - propA: Number,) q; b: H( r# h& {3 E
- // 多种类型
- D! z8 s# [& b% ?4 B - propB: [String, Number],1 [/ v7 F! ?. g
- // 必传且是字符串
" l! j2 |0 d! D0 v+ m - propC: {/ t8 i! G, I6 E! n& R+ Y" g" {
- type: String,
* s; ^ N& s$ I" S7 ^" S0 ~, _ - required: true0 c- F1 V3 W) A8 Q
- }," k7 T7 f0 t/ \# T- A
- // 数字,有默认值
. `. d& ~( X' E - propD: {
. R! `3 b0 R; W2 \2 Y - type: Number,
6 t7 k9 E# D0 }! M - default: 100
( u: X2 D- u1 B* j! W& P9 j - },
5 |# E) x$ \+ C; l4 g4 P - // 数组/对象的默认值应当由一个工厂函数返回
. C: B8 S& k" D3 X - propE: {5 B" q! e7 L9 @5 \/ M* _
- type: Object,0 X6 z H- x% l# G) _8 ?5 p/ p8 P
- default: function () {
) Z5 B7 o( J2 u6 C% E - return { message: 'hello' }$ m+ J4 p4 m) T9 `. S5 m
- }
+ i4 Z) O9 B; r; q3 x6 ]- h - },
6 T) v, d9 ~! P( H+ \5 {8 {, g9 \ - // 自定义验证函数
0 W5 [: J& P1 F8 j: R9 a - propF: {
* \$ Y! L1 r- h: k3 i3 N - validator: function (value) {6 E. W9 z3 c8 ]1 \/ h) Q
- return value > 10
% A D% z4 l: ]. i7 p( O - }
Y/ J! x f! { d. N1 [4 [ - }
- t Y8 U( V: b9 @* c _ - }
" J3 z. h, }7 S6 {0 A' j - })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array, E/ N0 S8 t3 N# A
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
4 }" r. h- u" {% e: J& o) d
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例. J& R6 P4 c3 D. {; f* z8 S# T
- <div id="app">6 ]" A! N: _ m2 D
- <div id="counter-event-example">
' f7 V* }/ b5 G6 A8 | n1 j - <p>{{ total }}</p>+ }5 O7 {' ^2 R. X) k
- <button-counter v-on:increment="incrementTotal"></button-counter>4 O/ x% V( c3 V& j8 H; ~/ {
- <button-counter v-on:increment="incrementTotal"></button-counter>
- |" ~7 E8 j9 U6 f6 B - </div> l% `) K; s' ~6 e- G5 p
- </div>
' W* L" r+ Q O% x) E - + \) \2 X1 W$ @/ w3 B# p$ |
- <script>6 Q" [, A4 N5 o. s
- Vue.component('button-counter', {
4 e& _1 G. t/ d- I5 {2 k/ g8 A- } - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',( p) q a0 J: e! t' `
- data: function () {3 H. Y& v/ n( n5 I# [3 h' a
- return {% M4 r7 t3 N: I, B7 P# }
- counter: 08 d& K( z2 e& A
- }9 ^) a% _! ~ W7 W3 `
- },
; J% _5 \6 P4 s% K* n0 H( p3 K - methods: {1 r4 y/ b/ L/ x, \% v- H
- incrementHandler: function () {8 D9 w' ` O( J$ {7 j# w
- this.counter += 11 f t+ N5 F7 K* X1 \" H
- this.$emit('increment')
. R% m7 N1 R+ v* ]3 I - }
+ o/ y9 K1 i, D. m - },2 ?) u5 x7 l* h( }* M0 Q6 w4 U, x
- })
, ?% s, l9 R* `7 _. X: h+ S - new Vue({
, H) ]) @8 w9 y" e% d - el: '#counter-event-example',8 A- A7 Y- S$ o D$ p+ ]; C& D* @0 f" j
- data: { L/ g [: |# ?9 H6 v$ g
- total: 0
. s) [- q7 a8 |( x/ D - },
# |; \6 {$ _2 E1 k7 w7 [- F - methods: {
$ }9 l/ H& b) W. i1 S" G X! ~ - incrementTotal: function () {( A1 J& B9 y2 {( _1 h* U; G
- this.total += 1
! ~, I7 }% ^" U/ t9 T& i! r - }
$ h9 V5 {$ m: k! c! U* l: {% w+ V1 S - }
; O, _/ o4 l3 T8 }, N - })
+ c. K8 L# y" g! \% p - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册' D2 [/ j* ?+ F3 p
- Vue.component('child', {
% t# _- q) v0 R" m7 l* D5 h - // 声明 props: B! a% r1 R1 d) H5 j5 }
- props: ['message'],. a8 ?3 D1 l8 p* G9 k
- // 同样也可以在 vm 实例中像 "this.message" 这样使用 [8 l. H, d2 p, I/ I. b& Q& Q
- template: '<span>{{ message }}</span>'% Y a8 x1 z% U! V. Y* q
- }): m: ]! p/ k7 B
- // 创建根实例, {/ U% G/ ^/ f9 O) x
- new Vue({
7 l# G+ {3 D1 A, W' R - el: '#app',% y- r' P( |& Y( M9 x
- data:{+ [4 n7 K9 s( o6 N
- message:"hello",
' Y2 r$ c3 a0 t4 K( E. M F - }. F% l8 ^2 s: T/ @
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
) S% G( g& T' B X; I5 h - incrementHandler: function (v) {
' e- j$ Z! p1 B# ` - if(v==1){% Z0 J3 O. I4 V
- this.counter -= 1
8 S4 m% |9 s/ T p7 p; e - this.$emit('increment',[1]): d' |$ L; ^2 o: h
- }else{
# a- I( p. z* E# Q - this.counter += 1
1 _' I6 M6 \5 ]' U" X - this.$emit('increment',[2])
& k" X3 |! f# U6 P* p0 P' [ - }
% p! [4 K8 k5 Z1 A. K - }
1 K& ^3 {, h. x; r - }
复制代码 - O1 c$ ^: ^6 N0 S$ H2 `
6 N% \ s( N. \0 A: i9 }
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |