cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
# } ?! u% i! Z. ?0 o% i, ?1 X2 I- <div id="app">
, y. j" M' g2 s* i - <runoob></runoob>
, ]) D# D4 z- a# l- A5 J1 B5 z8 S - </div>
# z2 T& N+ ]4 _' t0 \! X1 I6 d - 7 t: x8 b. Q! Z k- S5 i" Q
- <script>
: w" N6 R% j1 N( A$ j - // 注册" [, ?" ^7 X* v* ~
- Vue.component('runoob', {4 K+ e* w. `) F, l" S! v& A
- template: '<h1>自定义组件!</h1>'4 R- R: P7 c8 ~4 B" ~& J
- })) l+ L2 C3 X1 T0 J
- // 创建根实例
% E) \/ ~9 S, G' s5 r) ]% y& e4 D - new Vue({, z: I8 F: h: Y, }1 R6 F
- el: '#app'+ d* c9 e: v' k* \& m
- })1 z; J- [/ I& i8 B$ ~0 C+ C
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
7 k$ A4 w# l6 L+ F' Y
- <div id="app">
$ ]0 [; C' b* u& `7 J0 @8 s5 {' A: E - <runoob></runoob>$ K) a# _: l" r7 M( K, |& x% T
- </div>
; `) ^6 ]! z8 y, b -
' u2 @& f: p* }$ |0 j9 K% ? - <script>3 i7 X* }# p" ? n- v* g
- var Child = {" i$ g4 R% V. p6 `* u) D9 S9 }
- template: '<h1>自定义组件!</h1>'
" \, J0 B7 G2 U! o' g - }
& A, M. m6 v+ g% D+ v - 1 _" s+ k$ ^/ N6 D0 o# l9 l: b5 B
- // 创建根实例$ C4 ]7 ]% M9 r7 G; Y# v( |3 M
- new Vue({
. V% t& X& A ]7 d4 @ - el: '#app',
4 `1 s0 @7 N7 Y4 A1 Q% r7 z' o/ w - components: {& T5 v) w$ H; k+ t- |9 x
- // <runoob> 将只在父模板可用! ]8 x. x8 W) J+ B5 `
- 'runoob': Child
: m. c* s; D5 V9 i- ]$ G- o - }! c- I' E z) V" `
- })9 g# I' o, l& k1 I4 G
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例+ ]* s; x p. p8 y4 A6 V
- <div id="app">6 s2 M& w1 H% ~2 ?
- <child message="hello!"></child>, G9 ^( d3 k0 c" J5 e) S/ Y
- </div>1 Y' k8 s0 V& D0 [
- $ j% w# n/ s: U$ |) t
- <script>
% w, {# L2 z: z# v8 I - // 注册
$ X! f: l3 c8 w! C - Vue.component('child', {
$ Z' v9 ~8 |* _4 L/ b9 Y - // 声明 props
; @( J0 }: ?, `" n - props: ['message'],: c0 p% S7 W8 \% M7 t
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
) @7 L- V; Y/ E* E; a2 s/ J+ u - template: '<span>{{ message }}</span>'
9 s* C1 b8 H8 o: V+ `. f4 N- a - })
$ \; G) Y; U$ p+ \1 ~" F - // 创建根实例
9 B6 p# L$ n/ S, j6 K - new Vue({+ @4 d6 Y3 V1 W. R+ f2 e, ~
- el: '#app' o/ Z3 [; Z* \9 j" ~! b& `
- })1 W6 x* Y# m7 W4 V, O
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
7 o0 p6 _8 n* D! j; ^- <div id="app">+ s- b8 Y4 U( C {: E4 n, Y2 f% T
- <div>6 L: h3 W9 u+ K
- <input v-model="parentMsg">2 A8 [- y) `+ |2 ~& W
- <br>
) v* H" O1 |( d& v - <child v-bind:message="parentMsg"></child>0 {3 V/ I1 N/ w) R2 M' c* h
- </div>2 E8 L5 X3 P" P, l- u
- </div>
5 c& Z* s. y P3 u$ J1 S! ~2 _0 X - $ k* |- u) j5 W1 K: L1 W [6 J: F
- <script>
4 r* {, f! U+ P! x7 ~$ ^% }1 o - // 注册
% m( j0 P) [ @2 G, ~6 d: K - Vue.component('child', {& p; O8 ]" H, W- U
- // 声明 props
4 c- O+ U6 m0 x( R6 c# a5 P - props: ['message'],7 {* B5 U3 i( X5 {8 }% a8 n2 z
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
3 l- A+ G; y1 \' F - template: '<span>{{ message }}</span>'
* v! M( ` A* y- a* s - })# g+ {8 M& C& T O! _+ v1 L8 m
- // 创建根实例9 e' ]* u2 n5 V+ t( G# Y0 d. U
- new Vue({
. C! C" U7 p+ u$ v - el: '#app',! [# k9 v4 q+ Q& y; A* T
- data: {
\! M/ K$ R2 ~6 J$ f4 N1 i - parentMsg: '父组件内容'3 D: A" x; ?2 [( d* A- {% ^
- }
- k# }, C7 j+ |) Z - })% b' @3 m2 t3 m x1 L9 Y; L2 u
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
- r" A" W3 p1 H: q6 [: T- <div id="app">5 Q% s. p$ h/ s
- <ol>2 H9 P/ _! e& _
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
' i& B& e, C9 f! ^3 l" S, Q+ K - </ol>
. z0 _3 l, \1 P$ H2 Q - </div>
# e3 @# {6 l8 M# Q2 b& [ - 4 u! U: W# o. Z" x" n0 G3 M
- <script>( c8 y. D+ \) @: F% Q f0 \. w7 g
- Vue.component('todo-item', {
' R, Z" D# E2 o - props: ['todo'],
8 f4 H5 Q* e6 ?* m6 q7 j( L - template: '<li>{{ todo.text }}</li>'& d' ]+ k$ ^/ o8 O2 S2 R
- })
3 m6 P( S K" w3 @) J - new Vue({& B$ y5 y) f9 x
- el: '#app',
, d" V& \0 w) ^' V$ y& W - data: {
5 j" F# ?6 q! q: J - sites: [
, |3 D. Y1 i; Q - { text: 'Runoob' },
* V l6 M& K6 T* o/ { - { text: 'Google' },
+ p- d/ H0 ?3 r p& U% ~ P) j5 S - { text: 'Taobao' }8 n4 z4 y* z) N
- ]
0 o" j6 {# I1 ]" R; |" m% n% f - }7 y( t% [7 t! S' _
- })
3 X ~/ h. b3 y6 | - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
* q) S. q' ?* J5 { - props: {
' O9 c9 ]. O" G) |' c* J - // 基础类型检测 (`null` 意思是任何类型都可以)
' v5 j9 _. B' D0 u# m - propA: Number,% |8 T5 p9 g9 S. b
- // 多种类型
) q+ e* A7 [% n+ H/ o0 P - propB: [String, Number],% p( c z( |8 O& C2 X
- // 必传且是字符串6 ~) _& `: A: ^' y0 [. |3 X W
- propC: {
" C/ ^9 _+ `% Z& x) Y; G - type: String,( x8 v2 { P( }9 m; v8 {
- required: true
% I9 Q, J- P% S( [ - },
0 ^: H1 h# W! S) D; \% T- p - // 数字,有默认值
5 l& Z9 ~% T% [" i0 B& q3 x - propD: {, u9 a# [- t8 v8 U7 X( Y5 ~
- type: Number,
: s) Y+ l, |. v8 } - default: 100 N' @+ x3 p* k- I; e; p
- },
: E" W2 ]9 a" o M) C' M - // 数组/对象的默认值应当由一个工厂函数返回
. L, S/ f) D- Y" U m4 p0 @, d% r - propE: {1 m; s* s9 V1 a
- type: Object,
0 F- X8 X+ v( i" _' x - default: function () {- I: q# c5 v1 D8 ^( Q
- return { message: 'hello' }2 ~: z- |1 m% ~% ?3 S
- }
! r+ B, Y; i/ d3 Y - },, e T4 t6 m* ~4 m
- // 自定义验证函数
3 K. d2 H' y# ` - propF: {
8 ]9 F( |& n. i# e! q h- T - validator: function (value) {$ z) n7 p9 O/ u7 a. P6 k( k
- return value > 10: ^. C2 p; j" n* b# Z: J
- }
. H$ t ~0 S0 G. f9 m - }
! Y+ `+ t- F: ~) F( R! {1 Z/ B - }
" Z% i* u c: X. J7 ^0 l: f# Z - })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array2 e( p9 c6 D5 C8 l. t# l
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件1 i4 h c, G8 t6 r
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例0 V! G5 M% c5 ]8 d2 ~3 _% N. S) w
- <div id="app">7 N1 k6 P0 t9 a/ P2 K; h' B
- <div id="counter-event-example">5 X5 @' X( `4 P
- <p>{{ total }}</p>; B! j+ V: S+ O) y% A% e, x
- <button-counter v-on:increment="incrementTotal"></button-counter>7 x+ h* U$ j% e. E5 _
- <button-counter v-on:increment="incrementTotal"></button-counter>
( u/ O& j6 A8 u: _* O) r5 l* V - </div>( k! p1 V+ X+ [( B) |- q% ^- p
- </div>4 R% r: m0 S* K- Z# h$ _. b4 m
- ; i+ g8 |7 l6 v7 t
- <script>
) X' ]" d: }8 {$ s5 X - Vue.component('button-counter', {# F) H; r: H& T$ O$ t# z1 w
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
" i& k8 c9 h) m( T4 U" ~& I6 b/ t( D - data: function () {
. c5 C# f e2 N, k5 E8 a* L - return {
8 n6 K1 b% Z$ d& @9 r - counter: 0
0 e' L2 v M+ C# l- m - }" m+ {2 w& A& h& H! a
- },: \2 K0 u0 K; [- O
- methods: {) a2 Y2 h: V& b2 |
- incrementHandler: function () {
8 ^$ ?7 _* L* _2 f z - this.counter += 1
" m0 H7 f1 W! I1 [ - this.$emit('increment'), F, \- m4 [7 e) ^# D: H
- }5 E7 t9 j v" [; l) _' Y; q
- },
& h) Z: b: V0 w* D: D - })
( q, Y' m1 O W6 N- P+ _! Y - new Vue({
' g! b3 y5 O, l - el: '#counter-event-example',
! C) Y3 q. t- t) H5 a+ p - data: {: g9 e& k0 a' I
- total: 0* F* Q( j( [/ \" H( k
- },* y* b! Q! S4 c, d6 t" b
- methods: {4 i% b% T* a; ]+ `7 K1 c
- incrementTotal: function () {, M" T" Q3 q, _- v. U: c* r
- this.total += 1
( F# J* @) X# B - }
' c7 q7 O1 ~: b. B0 G/ O! h - }: @& |$ Q; h* A+ j8 T: [) P
- })
" \- l; ~; F8 q6 X - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册
r* w% b! m8 H/ F J - Vue.component('child', {
7 ]5 u F! x. q- ~: _. [ - // 声明 props3 o4 ~/ T D8 z4 F& f0 _$ {
- props: ['message'],
* D4 L9 i% e& b( [; ?( d+ K- i - // 同样也可以在 vm 实例中像 "this.message" 这样使用
3 o* V* R# s+ U# S3 t5 x/ I - template: '<span>{{ message }}</span>'# Z7 I4 T# x+ t
- })! s) E2 A4 Y/ u* b) h& M8 A, ^
- // 创建根实例
0 ?# j1 U* t. P" \% v% U# W: O, T) w - new Vue({% t# E F& U% {' K0 L/ b# _
- el: '#app',5 _" ]( U& ^" w- { J( z& k: m2 M3 V
- data:{
9 E, W% ]7 b K7 [, S - message:"hello",
* r" P7 I4 e+ s" N+ Y - }
3 C2 O1 L" a/ C1 x' g - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
! a4 Z; {) ]9 d7 G' ~ ?1 g - incrementHandler: function (v) {, K0 {. k8 F6 y% v4 V
- if(v==1){0 b$ r: s$ L* I9 |
- this.counter -= 1& ^# a q! X. v& z3 D
- this.$emit('increment',[1])
% e. K$ ^$ Z, G6 B) A* }1 w) v1 Z - }else{. c+ M* I1 T+ t! M
- this.counter += 1
# K0 u2 @0 l. Q; \2 |5 P - this.$emit('increment',[2])$ ^. ]" U) b5 c& E9 I& i" a ?- k
- }& i! a5 ~' N& X+ a
- }
% S3 l" [7 o1 c3 p) k- k - }
复制代码
* t/ S4 W# B9 {+ t% T% }! C
" o& G) v7 Z W+ l: B C7 z/ n
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |