cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
- p3 i/ K/ }, |; O" k
- <div id="app">
" b- T" C2 L' c" Z# S5 g - <runoob></runoob>
5 H: T) D9 @- X) s+ h - </div>3 X' e! _# w, V9 C
- 1 u0 f, n6 W1 v/ r6 K- J0 T
- <script>
! T; J2 H. o7 n( u4 m5 Q - // 注册$ i+ W: S# E# k5 K$ [5 g) W( c; W0 H
- Vue.component('runoob', {
) B# X6 \# }6 {! A( T - template: '<h1>自定义组件!</h1>'
! ~+ }9 X9 C1 S3 p- L9 L% P( b - }), S0 _5 y5 o' y3 h [6 S" n3 E( Z& \: h
- // 创建根实例* ?8 r& l* C3 w, ~+ V' x
- new Vue({
9 n! { a- w+ [6 F3 L - el: '#app'7 q0 A+ J* g! f, H% l9 {
- })
) X! n- u( X. h8 R5 v - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
) p7 @6 S9 z: u K. n6 h
- <div id="app">
! q6 e0 P$ I% n; J Q - <runoob></runoob>8 Z4 U0 n( O n- A3 N5 P
- </div>
# o6 u3 N5 L7 @; c5 L: v) U4 H - , h" ?8 z H% N. M p
- <script>* q- |% W) v2 g6 x+ o- q/ Y( T3 ?
- var Child = {$ x# ~" U9 y7 ?7 l5 O; d
- template: '<h1>自定义组件!</h1>'3 w0 Y5 s- D* }; m9 E4 Q! C
- }& y. H8 \* b" [& q s$ G
- 4 z! }- E" M! R+ B
- // 创建根实例
7 L: h4 G3 G. X# }# @ - new Vue({1 H3 ~4 H3 P4 `+ Z' I
- el: '#app',
% O) ^- d! p; q7 y - components: {
* c+ B/ e1 r; J! p; \ - // <runoob> 将只在父模板可用
- S/ Y4 |" v# C* l2 k9 T) ^ - 'runoob': Child
- D8 f5 Z: Y: _8 Q o, ?# j! @ - }
+ Q6 f" g; V5 B- i& l" j - })6 e$ a% b# K m1 x
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
& w" e4 A( {: r+ s* ]1 e! ~6 f- <div id="app">* x9 o, u3 z3 f; C6 S: p) Y* H
- <child message="hello!"></child>
; G' M. O& w- D - </div>
- w; t" Z6 S, M3 J! `2 c% }- J -
8 ] b; S& F7 k' m' S" { - <script>
' U- X2 d0 u. G: i - // 注册
" r$ D6 H% f& H# u2 T2 E9 c+ h - Vue.component('child', {
$ ]9 n$ X% _8 v - // 声明 props7 R! r% a z) U
- props: ['message'],' G/ |- Y$ x" F" C
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
& q0 {9 W- I, c) |+ d* A* V v. X- H* o - template: '<span>{{ message }}</span>'
3 L2 |$ l$ B" ~+ K9 b5 J - })7 [- r( @0 j7 I) W9 e- M
- // 创建根实例
, w: S) B3 a; I - new Vue({
' D' G2 D% O0 a. {# S/ u1 F5 {9 D) Z1 M - el: '#app'# @/ |6 R2 z4 f: \0 C
- })
# p' x7 `- P, K/ F! c# ~ - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例/ o+ k1 B5 {" Z" r* H1 a
- <div id="app">/ o' H! X1 J' _9 h5 ?; ?+ Z
- <div>
6 I: c3 m0 u6 V1 L - <input v-model="parentMsg">3 s% Z5 Q* U7 N- ^
- <br>
9 L1 K2 n: ^" q& N6 ]- Z - <child v-bind:message="parentMsg"></child>
( {! D2 n$ b4 R - </div>
- D9 w n a3 P# [8 @9 s - </div>1 s$ l( R, e" \/ R1 Q9 h
-
* k. ^6 P3 K+ e+ I0 S& Q - <script>
0 Z( u1 Q% A8 J% {" R, R - // 注册
. W7 d1 ~3 D& ~: A- Z, ?9 o2 @6 n - Vue.component('child', {; v, E8 [8 c) L, G7 p8 I7 Y
- // 声明 props
- Y( ?# |' _) A. B$ [6 o5 R - props: ['message'],4 t* D- A! V, z, O
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
- u: ?! o* v. b0 d - template: '<span>{{ message }}</span>'
* D1 D" o% R2 \% ^ - })2 X4 @+ ]5 j2 k- K
- // 创建根实例
+ }) G' N) x! i( x5 k - new Vue({: D1 n5 x1 `, @2 W8 I# @) R
- el: '#app',+ [8 q4 J9 z) c# o$ O
- data: {
3 F E+ k4 `" [$ k7 L - parentMsg: '父组件内容'
5 l( G. ]9 L3 N, S( } - }4 J5 @1 r8 z, ], Y
- })
2 O; b3 R7 O: X. q) ]& p - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例) Q: Y6 h# y, l+ g, o
- <div id="app">
) Q9 I' m" F/ A: b( ~& P - <ol>
+ _3 Z+ I3 A# Q/ @ - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
" P j F X d! F6 O; G( [ { - </ol>& \1 [0 w D$ K& i( h
- </div>
7 }! X$ `. K4 m' k9 q$ r7 Y$ Y9 Q' Q -
. [$ a% B% j0 R% m+ t: E9 K, V - <script>
, Q7 C& @5 e& Q1 |' c+ g: @ - Vue.component('todo-item', {- G7 G7 P) ^% G- x8 k4 m A
- props: ['todo'],. O8 E, B2 |1 I& O- G
- template: '<li>{{ todo.text }}</li>'- @5 @& d p3 R1 E
- })
( X$ ]! [ b9 C4 x9 ~ - new Vue({
5 W* r! G# h' m3 {7 D - el: '#app',
6 T% i2 W) ?! f0 h" ` - data: {- L4 n7 K' H* |9 {) s0 x5 a
- sites: [
; g/ @6 i, l0 N7 s - { text: 'Runoob' },
$ [/ r* l2 J. [' q; G - { text: 'Google' },3 K9 s R, c: W' C: B& w& @
- { text: 'Taobao' }
L0 P$ E: |0 M* B" t2 ^ - ]
- A: S+ C1 l2 b! U+ w' A - }" p H- h* g7 d5 T4 ^
- })
" ~0 [# h. y5 o' y t - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
9 L2 i& U- f, \# B" |; e - props: {
d% l9 f0 o- t, R. r4 G- w - // 基础类型检测 (`null` 意思是任何类型都可以)
5 x8 u+ @3 \' Z F3 D - propA: Number,4 J2 A& Z* f3 A7 Z& e3 }: q
- // 多种类型
1 o8 R. y$ P" o: @3 r' A - propB: [String, Number],& n/ F. D& J+ E0 r% i. r4 h
- // 必传且是字符串
% m3 A, z" A6 T% V) r! @- } - propC: {
- Z# w$ q- R# t - type: String,
+ k- q2 X+ |' m; m - required: true4 } S/ h" ?# h
- },
) n2 P# ] e6 r - // 数字,有默认值! Z! m6 p4 ]/ n- B# G _! f7 i% q: m
- propD: {7 |7 M5 A) r3 H; h
- type: Number,$ k1 s) P% d* Z( _! j: h
- default: 100
9 q# N: z1 C) f% G - },
. m# V4 _2 Y( u; H1 `& z! f - // 数组/对象的默认值应当由一个工厂函数返回 i* S% R8 Q, {% U/ y# Q
- propE: {
3 m7 u" a$ _6 g4 ?9 b2 p - type: Object,
# N1 ?" G0 B* p! _$ h+ K - default: function () {
2 s7 e7 T, f2 j* V' N - return { message: 'hello' }! O5 \$ Y8 t5 m- S5 U% X" u
- }0 `/ x! _9 y; m. _
- },
1 ?( w9 \1 C' g9 W, | - // 自定义验证函数
/ i$ {2 r$ r/ P e/ O5 T - propF: {
) V$ r6 b0 g* r3 h( u: A - validator: function (value) {
9 c! k; _! o! l& B* U: V - return value > 10
' m5 e7 R& V; g) v, a5 F - }# N: u" }, e- o a. H' {0 f( n$ n
- }* m& n- O1 i5 T- C4 Z1 Z
- }
7 t# v, F! t: E* [1 G2 n$ p - })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array, N0 W9 n' U! B5 Y& g) z
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
) C. l# S5 l9 H1 a/ Y
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
+ o3 s( A1 s2 T# |) Y) D- <div id="app">
! P- m& f1 r8 V( T - <div id="counter-event-example">
- w) c& m5 y: k9 @4 [$ q) s - <p>{{ total }}</p>+ C: g3 h' K4 c* k. n. q0 R
- <button-counter v-on:increment="incrementTotal"></button-counter>
: ?, u- k# \5 n r! `7 |* y, ~; E - <button-counter v-on:increment="incrementTotal"></button-counter>. k3 t3 [6 S& K n7 p0 n' w
- </div>
# ?) p5 u9 e; ]8 U5 G - </div>/ w5 c8 D8 V4 [0 M3 d+ q+ ?
-
' l$ X# v; U3 M - <script>
. t0 y& j8 b- o( G' @1 r - Vue.component('button-counter', {! @* \4 h. x* `6 f# p5 k8 y
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
8 l$ ^" {) T. l4 M - data: function () {
, u1 c" F# V: [: w - return {
8 J h+ A9 h5 m$ r$ r - counter: 0! v4 @* d$ P/ r
- }
; h6 D5 i- e6 P! u2 U6 [8 D2 ] - },
$ Y. d i, S& \7 i9 C - methods: {8 @2 ]0 j& c' s; Z; X1 x9 |6 p
- incrementHandler: function () {
& E( d; u: J5 `" ?# j2 P( G0 g - this.counter += 1
3 y k. n7 X" W6 e - this.$emit('increment') i2 V2 \# A+ n% G% c8 A8 ]
- }
- s" L8 R) I& Y& A - },
6 w% N3 [' {# q' z4 ` - }) A4 q0 Y" p! s4 l! l4 w9 }
- new Vue({
) Y+ I$ a7 b/ H: V2 d" y" A. \ - el: '#counter-event-example',
' [" t+ k" `' L8 U* @ - data: {& s* x% l. C3 Q! a: z& j/ o
- total: 0
/ c& Y2 V+ g8 ^6 d0 K) q. Q- z - },0 w9 @+ Q2 W3 S. I
- methods: {. F' {7 w9 [: H* n. m' Y# ~
- incrementTotal: function () {' F/ b- d/ \1 i7 w7 Z6 h" w8 E
- this.total += 1
' t3 \0 h9 @/ K6 v5 s9 ?, k - }; b) P; A& S3 ]& ^, x- P
- }$ a) e [# j. H. P; F: d. N8 X
- })
: M& [" F2 w _3 d/ Z - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册' X: U, ?+ F0 j V/ C: j
- Vue.component('child', {
) R$ p# R- M8 c' E3 | _- f& p - // 声明 props
$ r1 ], X5 ?' x& H5 u; \ - props: ['message'],
3 x, F( ^+ A% g6 c' U) Q | - // 同样也可以在 vm 实例中像 "this.message" 这样使用* x `3 M. d) Q' n- t' r$ d
- template: '<span>{{ message }}</span>'" o; \( A: v0 t6 Q$ c0 I
- })
8 t$ v0 F) B( y6 L3 ~; b/ z! f - // 创建根实例
6 f- b3 }' m5 { - new Vue({
# ?3 V$ C' Y5 J( j - el: '#app',6 a; m$ L8 B6 ~4 h$ N7 N! ]
- data:{, S/ F' L# T, s
- message:"hello",
% @: o) b% h+ D$ E- P7 x' t - }8 E M+ q- `4 ` j8 ]7 u1 s& |& E
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
- Q0 U/ X; \" w( T - incrementHandler: function (v) {
6 ^! J: [* k" K4 Q - if(v==1){
2 _# x( {7 H9 p% {* v5 u - this.counter -= 1
! W& F, D3 ^7 |, M5 A - this.$emit('increment',[1])
5 t3 i7 d) T0 R. J9 @ - }else{/ R" Q: @+ [6 ^) u9 K& T4 C+ G
- this.counter += 1
8 A! l. o% E! Y$ Y' D - this.$emit('increment',[2])- H- \0 a3 j7 Y/ l6 ]2 f
- }
- a6 M, P$ W% h5 Z6 } - }
) z3 n0 ~( ]; O+ \ - }
复制代码 ( s. _) m k H/ R2 S8 u
9 k! z& D& T( d' ~; `+ e' T, _8 ?
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |