cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
9 Q b+ d( _+ {
- <div id="app">
$ Z7 @& x0 {. ~3 S9 X; x1 { - <runoob></runoob>7 j8 N8 [! N0 I; H
- </div>
' ~3 [8 R$ X3 M6 y" J |" [ - 6 [. H4 e9 H4 H8 n4 d8 ], | h& O- Q
- <script>$ T; H& l4 j. b
- // 注册8 r; E2 Z3 x" x9 Q9 t
- Vue.component('runoob', {/ T2 G2 [8 m5 Y w5 ~' b7 N# Y
- template: '<h1>自定义组件!</h1>'; @( J5 B4 q1 Z# ?2 l0 S$ K
- })5 ?, O1 {/ u) q8 F1 Y: \ `
- // 创建根实例
4 W& O; y3 H7 k, W; P: M' b( _8 L - new Vue({/ d7 V! _0 H6 O6 ]
- el: '#app'/ _8 r% c8 p3 _- [
- })
- W7 w$ f8 `" R( k - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
* u$ z9 y- z) ?# l! J. p6 N% q
- <div id="app">
! i8 X% M6 W$ \; ^9 l - <runoob></runoob>
. P& V% |; _+ N# Y - </div>- p8 p+ G. F' f8 t( k# c
- . ^- {6 u" E+ k% \' \
- <script>: K+ ^7 C* V+ X" p+ U1 w" N
- var Child = {5 b2 n7 p7 `) B
- template: '<h1>自定义组件!</h1>'5 M' q+ [* O/ {" `; l; [! l; O
- }6 U F) B1 ]3 O n& e
-
$ i; Q/ a5 Q) o; W - // 创建根实例
# R% B' S- `7 j. e$ u: r( D - new Vue({0 I2 I; y$ K, m8 x# h
- el: '#app',- Q' O/ @5 z# p& x, ^1 H
- components: {4 D8 ?, s1 a. L
- // <runoob> 将只在父模板可用
/ G' y- U' M: ^; G - 'runoob': Child
0 `( ~/ j- G, A& U) ?! d - }- G6 U; b3 e* d0 D
- })
9 F2 O1 ~: V4 U Z+ d: L - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
, K6 e! w" v# ^& e, W- <div id="app">8 G8 c! N3 a2 X9 { d( ` x- \, \
- <child message="hello!"></child>* o2 C: B5 N; C
- </div>
9 W9 i) ?. b' `+ ?9 s6 X - ! r( O. w. h* T6 m# x! u6 A9 M. _+ A( }
- <script>3 d8 x" r( ~ |
- // 注册
5 S: D# X0 N7 I0 F' J - Vue.component('child', {
+ b( R/ d- Y0 Q* i5 d8 p! T - // 声明 props& n6 M P* O+ a3 y0 k. T P
- props: ['message'],
) F# F3 G0 p' g. }7 g. M - // 同样也可以在 vm 实例中像 "this.message" 这样使用
, f. u. n# s$ {9 F - template: '<span>{{ message }}</span>'
9 F1 K$ `' G7 I$ X) z. d' | - })0 |- ?2 z& N; T2 e
- // 创建根实例
& j) ]$ E1 R% f/ b0 V% L! l - new Vue({
3 B* u/ C8 N; K O - el: '#app') p, e" j2 w7 \9 U3 V
- })- O+ F9 v) _! }/ H6 o! i
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
' }4 V8 U3 N% o/ x G- <div id="app">
. u A5 M: {7 B/ | - <div>
5 a) L; ~4 x: i4 l I! L - <input v-model="parentMsg">
/ G* J- D2 u" z1 h( U - <br>
: e+ A. p- E6 m* r9 @$ y - <child v-bind:message="parentMsg"></child>: m( x+ o+ b% ^8 J
- </div>0 J7 @7 Y9 A- J3 e M' t) l3 [. J
- </div>8 N1 r9 K3 ~* m3 G d. p" ^3 |9 t7 A" G
-
7 l0 T8 V0 d* ]$ c - <script>
M# h }0 u+ _8 H - // 注册
- r }8 M& _3 ?2 J" Q. v - Vue.component('child', {1 V% u4 z4 o! y& p. Z0 }+ c
- // 声明 props) H7 Y" a i# A4 d4 N* e# e# m( U
- props: ['message'],
8 F4 ~! q g, X# [ - // 同样也可以在 vm 实例中像 "this.message" 这样使用
9 i0 h1 I2 z4 V8 b - template: '<span>{{ message }}</span>'1 v3 q# g& z& M( p
- })
7 V' N. K% z( B& [4 k, c( i - // 创建根实例9 c' n1 X. E- Q; t6 p2 Y; c. r
- new Vue({) q5 ~5 B( p8 h% H
- el: '#app',
/ P G9 d1 I- d% B- Y- n( ?: c3 I - data: {9 i" I- n2 p. D2 K7 A1 I
- parentMsg: '父组件内容'
0 f% [8 y* m) Z6 y4 y/ w - }$ ]" N# [: m+ }
- }). q4 G: N5 k- ]
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
; k" W1 I8 V1 w) w/ O" X; t8 Q- <div id="app">
6 C6 j7 C5 @) J' d" R - <ol>
' v' e( u' T8 r" e! h0 z1 \+ e - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
" x! j) I7 P& Y0 w' ~4 Q - </ol>9 |4 D# B9 ?! w N4 I
- </div>; r% H* L0 Z: e; M2 X: G1 |
- 7 b5 `3 H9 P1 {0 @2 O( x) w) {( U
- <script>3 Y; n w R; N& V
- Vue.component('todo-item', {
) E, U% _7 \9 }: S/ N7 }9 Z - props: ['todo'],
4 J( N5 j9 [% e$ [ - template: '<li>{{ todo.text }}</li>'& w p8 Y4 B" k+ P
- })' P" D6 z0 M( d+ L, R6 Y+ w$ @
- new Vue({0 u! j6 N& a% V
- el: '#app',
. |) z/ P5 u3 p& W - data: {0 h' q* V. ?/ V
- sites: [& N% y: [3 R! `- [; @& G) D$ }
- { text: 'Runoob' },
2 P( ^; z c1 V% |3 A0 s" w" {* m - { text: 'Google' },
0 W8 [; y+ |/ K' b# Q2 M2 K1 j8 z - { text: 'Taobao' }5 x c. W% T0 r/ [1 p
- ]* g; C5 U$ F* d4 i; ~! C3 g
- }
$ Q- n- ^/ d& [/ k8 A. x" S# X - })
( G* Z" J) H& q7 k; x - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
+ o: ^( u9 c4 v( } - props: {/ T3 {# w4 S% T) w
- // 基础类型检测 (`null` 意思是任何类型都可以)" n1 {7 \0 ^! G* h4 i8 t% v) X7 ?
- propA: Number, K% I. |% I5 h8 H$ a) T- k
- // 多种类型 k4 }1 f% k2 R, _( |: `
- propB: [String, Number],
/ x; F* Y7 ?+ ^3 S" Y o# O7 V - // 必传且是字符串
4 r' z) R) P; o* D - propC: {/ y9 A9 F5 T. h& @
- type: String,% @8 \9 n3 L" c$ h3 [, U0 F# ^7 A9 [2 E
- required: true
: c4 ?2 V/ q/ w. Y( c' a& y - },
. e# p6 {# `6 v3 r0 P6 X, ]- j - // 数字,有默认值8 w5 T5 Y: y# f1 e4 s( v! z2 ?- C
- propD: {9 ] K% }! K: O3 I
- type: Number,
; {" o% ^/ h$ g" ~+ C$ @ ~ - default: 100) e0 k; N' j# Q0 M, e; Z& y
- }," V/ A/ @) [8 V% K' F4 u
- // 数组/对象的默认值应当由一个工厂函数返回( Q7 n& m% O* F4 U1 u* t6 ]
- propE: {
1 e' C1 I+ |3 ?) r - type: Object,
9 M7 L9 G1 U- | - default: function () {. Y1 l2 ?* C! G+ D) i. c" n U* R
- return { message: 'hello' }* Y: w2 o! H+ T: O
- }- @; e Q8 E$ r; l2 O& j! o
- },! J2 y% k% ?4 ]
- // 自定义验证函数
3 H8 ?% N% o" k! G! }) ? - propF: {
& ~( E8 j# S" g. W! F3 e' Q - validator: function (value) {8 P1 D+ Z0 @6 s
- return value > 10
0 B3 j! S6 Q0 X0 M2 v& y - }
0 c" f3 x4 |: K4 h - }
* s- X" h5 T r. Q; {2 F7 M8 m% i9 G1 P - }$ a6 \! q) _5 ?( v& D
- })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array) r' F9 ?$ Q5 E
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件4 c0 W+ b) _9 R! d3 r. ^
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
' U" ]0 X6 |8 A$ _/ L- <div id="app">4 t8 P+ e! J% X9 c
- <div id="counter-event-example">9 S2 L6 T w3 A! W
- <p>{{ total }}</p>& S; T' Y% v( T, w
- <button-counter v-on:increment="incrementTotal"></button-counter>
7 ?( O$ J/ g6 }& l$ n+ _8 M - <button-counter v-on:increment="incrementTotal"></button-counter>' X" D0 c% I0 p6 u! e! V
- </div>' \4 Z- }+ g5 j
- </div>+ ~* j; h8 r+ i4 V
- $ Z4 v W/ }/ a! U; n
- <script>& c4 d$ C% M5 [# p9 f( v
- Vue.component('button-counter', {: ]6 E. W' C; a2 Y* Q6 S! Z6 s
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
* t g% i# D7 Z, z$ L* n - data: function () {
- X7 k4 d0 |5 J/ x, e( K - return {
- R- c; f: J0 _( U# w - counter: 0
, ~- s4 q" U6 L, H- ^ - }4 H$ M0 O3 a" t# q
- },5 V/ z) q% e, {) T
- methods: {
5 T% k; \1 O6 E: u - incrementHandler: function () {! `. C& T, T; R) s, ^
- this.counter += 1
# A& I; C& n8 H/ M, u+ u# g* t - this.$emit('increment')
5 o4 `/ g( w8 O3 b I/ a2 f - }! ^) m# g& @" ~4 A
- },
1 i1 U, t8 b: c! i. V5 V5 x - })
& s: x7 h! h* ?; B - new Vue({. r# @1 T6 u j; {" m) S1 D
- el: '#counter-event-example',
7 U% K g ~6 m; t2 R% a& B8 } - data: {" \, V8 S' y) T" C5 }% D
- total: 0
0 ~+ D& B9 ?+ `+ _8 g - },% P( M- {0 e5 \! ?2 u
- methods: {
8 X* N: m0 S C) P5 V - incrementTotal: function () {
& F7 P Z/ E+ g% C$ g0 p3 L' u8 T - this.total += 1
: z4 @2 y, d. _) \3 S$ l- T - }
% z$ E" c3 E6 G( r& O5 g# X3 L - }" ~: I& ^# P/ W9 | H
- })
, a/ d- ^& `4 O; d% x. q5 d% ` - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册! R/ g, B+ ?0 ^% L
- Vue.component('child', {% }1 I! X4 E- C5 u5 F& v/ G
- // 声明 props
! |3 j% x; y+ A* {/ ~# s - props: ['message'],& l' Z5 p: U) h* E
- // 同样也可以在 vm 实例中像 "this.message" 这样使用, l/ @; l& |9 @& y- k
- template: '<span>{{ message }}</span>'
p3 K" z5 [0 e% ~ - })
4 `, f3 U$ ?" W" U! H4 r: W4 F - // 创建根实例
* E1 ?$ F5 I8 Z) P6 L% a' B - new Vue({
; F2 G. U/ y- t8 S3 c3 I6 I( M - el: '#app',* C! Z3 m M$ {" R0 } P3 d
- data:{5 _6 z: Z3 j/ W p0 A. i
- message:"hello",
6 b* ]- i9 s( V! {7 H - }: c! p6 m/ N; l8 J# i! O6 k+ |
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
' X' f' x$ G$ E, V( { - incrementHandler: function (v) {
d( {& K2 t3 K: ]# p1 s - if(v==1){1 |) |$ p) ?( U) U& ~2 d
- this.counter -= 1
; Z" b/ ^' D/ n. z - this.$emit('increment',[1])6 n1 B9 o4 x% a6 }8 e( f
- }else{3 A5 h) c g$ a
- this.counter += 1: k- S2 |8 ?* R1 }
- this.$emit('increment',[2])
( X: e! H0 f& ^ |+ q" s P - }) g9 g* T/ ` _0 e2 \( X
- }
2 \' Y( w( w& k D$ \% {# }! o. u - }
复制代码 " v7 }5 }9 ~3 |1 O7 W4 Y0 q7 ~. U
' U0 s4 X) t5 w* g1 M( l4 `
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |