cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
- X& N2 T2 i. k9 M; d, g; `- H
- <div id="app">; G" L* S: F5 O! }3 E- n1 w, M
- <runoob></runoob>' k* k4 u3 m \9 n
- </div>
1 ?2 @# ~; d7 Z; B$ g& F/ O - % D. s9 M" m, E5 z! f1 g
- <script>
0 @4 \$ e' u4 j - // 注册 i9 V$ o) c' W
- Vue.component('runoob', {
+ M' T* C- ^' r9 k4 y' K - template: '<h1>自定义组件!</h1>'
U* i. K! F5 m& T/ z - })
6 d5 t/ \$ {) _# Z3 G6 k( ` - // 创建根实例: d2 @' J8 T5 N- Z$ [6 r) }
- new Vue({
/ c' ?& t3 S) @& F0 i0 e* \( p& u - el: '#app'0 B( T+ h: [) u2 u9 l0 d& {: P
- })
/ z/ b) s9 V9 ], D$ E: ~ - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
) c \" l* A. v8 m" G, F- <div id="app">
' L& d* b4 Y# S v - <runoob></runoob>
/ e- Z6 r. E0 u$ ]" u! o - </div>4 N, e) w- s+ c; F/ g8 f2 V8 M
-
. A4 ?' n+ u' B# ]% t% A - <script>
0 L) h- L; Q) z - var Child = {
; |8 k9 r, }+ x. |' ^- E4 p4 _ - template: '<h1>自定义组件!</h1>'
& V, Z( A( C' R P - }3 {2 S* J4 s) c' m4 A9 O& a, p* S
-
3 P% n& x B: S5 v! I - // 创建根实例
# K3 ?3 a- ^0 w' i - new Vue({4 T/ b7 U' e1 A' x* f2 {5 L
- el: '#app',+ j# [7 y, q, S1 ~) m
- components: {
6 \' `, h1 M: o - // <runoob> 将只在父模板可用# l7 y7 _, [. V0 i# L+ j' a
- 'runoob': Child' s5 \; C) [* Z+ B3 u% p6 u- {
- }; N. N. @1 J8 h7 q
- })
2 C# d: `- I0 t9 v, f - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
( e8 r3 e/ J3 M- <div id="app">$ A5 R$ e( f; b! h; `( |; E3 n
- <child message="hello!"></child>8 q. q2 i& z6 b' w' P# R
- </div>
8 O) O( K/ r% T. | g - 1 f8 r( Q3 M+ N
- <script>
2 z- z* z% s }4 F9 u: n- @ - // 注册
& I! P( |; Y9 N- K. ^ - Vue.component('child', {3 l V3 a$ S0 s
- // 声明 props7 J* o9 S# v! d& B
- props: ['message'],
; O' o/ Y0 I; Y: m - // 同样也可以在 vm 实例中像 "this.message" 这样使用
1 }8 u2 h& W. x - template: '<span>{{ message }}</span>'
# V! v) O, A5 w - })
! a1 A4 a# K( h0 r" p2 L" T& G x& z - // 创建根实例9 P5 e1 ~( p* R6 }$ T# B/ m
- new Vue({
, h0 S. T7 G! X# O7 e9 Z2 O - el: '#app'
! }- X8 W) y( x/ x# F+ @ - })) I2 w* I9 @3 [
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例: ~$ s9 i; ^# E, r2 [0 S" u* Q) D
- <div id="app">9 B) O. l/ X. i( c; \7 Z
- <div>
* [4 t0 _; i0 F+ B# |; U - <input v-model="parentMsg">
) }; A, T/ V1 v, X# Y G - <br>
4 |# j# D, n7 [. k. S! V2 Y - <child v-bind:message="parentMsg"></child>
8 I* k2 C ?1 J) f6 ~& ~# t - </div>
( Z4 O5 L7 [8 T# s% g9 E - </div>
9 g4 a5 q4 p! X# n0 @ -
& _, y" w& K3 _% V$ @- K - <script>
( m4 |3 v8 c$ ?2 u6 N$ a - // 注册3 A& B( \+ q) W8 k6 d1 J: D
- Vue.component('child', {
3 e0 P) o6 ~: b' _) o0 ~7 r - // 声明 props( v4 B6 R9 l$ ?! G6 H4 U
- props: ['message'],
% c+ w1 z( G2 W$ O; H - // 同样也可以在 vm 实例中像 "this.message" 这样使用 s) k3 F2 O7 O2 L6 C& K4 }
- template: '<span>{{ message }}</span>'+ y+ W: t8 C5 M7 [& \
- })
3 c C$ x! i4 t2 ^( ~ - // 创建根实例 h- @2 u( ?; \) A$ N
- new Vue({) a$ {$ ^8 y# W& @! V# _* O
- el: '#app',/ H3 s0 z& J3 z9 g+ ?# ]& @' E
- data: {5 C8 T: D( y/ Q2 j: O
- parentMsg: '父组件内容'
# Y6 q4 ` V0 |- ^7 s" ?0 \ - }+ q/ W* n8 {: |
- })
/ [% r' g8 ~! \4 W( x - </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例
6 E7 Y# n" ^& t0 o7 W4 p! W% ~. h- <div id="app">
- y/ ^' ?5 l$ J: S# f- z3 G - <ol>3 \, j/ U+ i8 @- ^! P, e2 V- L
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>7 w9 W3 ^8 e6 T9 q: f/ v
- </ol>
( i8 r5 v( I, o E9 Y - </div>* y3 ~8 Y3 @9 w2 a7 ]7 B
-
' c8 \; P8 H; C0 _( i - <script>
6 }& @3 Z/ U5 {) v, C; [1 \ - Vue.component('todo-item', {
# e' W6 E) z. f, V - props: ['todo'],. |4 _6 u" S' m+ q$ Z
- template: '<li>{{ todo.text }}</li>'
7 o+ O; j* ?2 }6 _+ x/ H - })
) i4 w4 m, A9 h4 h/ q" u - new Vue({
7 |! D0 G" @) U s' [( f: a7 P7 y - el: '#app',
& n6 t* `8 h- X% D4 p: Q0 z5 x - data: {! d" B" h G6 J0 U5 }4 Q" s) O; n
- sites: [
% G9 v2 i" Y. k4 @ - { text: 'Runoob' },
) {: j- q" m8 k0 A. d! x - { text: 'Google' },
3 u6 {! h6 u0 @1 F8 E4 \+ h - { text: 'Taobao' }& R+ W, W3 W7 k! X% n
- ]
4 r% e" ? \/ k7 c0 J; ], K - } |! [1 B$ F1 p0 z* N4 j
- })
5 V% |5 l* L& ~7 X - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
( J/ M/ w% B/ V - props: {! A* ?+ D1 R. \: l% Y2 N
- // 基础类型检测 (`null` 意思是任何类型都可以)9 g5 c% [4 a- b4 N
- propA: Number,6 A- ~/ f- X3 n2 O
- // 多种类型
8 w1 `) X6 d. a& j/ Z& i* n - propB: [String, Number],2 F& W/ x4 P2 D, n! [9 m( @
- // 必传且是字符串& A( Y) K( \; `# X L
- propC: { ^- u* m7 P, l& |+ O6 t
- type: String,' k( @: m& {4 l: j1 h! O5 J
- required: true
1 i0 G8 | p8 @* r - },
$ Q z1 N( n+ J, v* ~ - // 数字,有默认值
: S* M a+ _" I e6 ]. C - propD: {
' }6 O3 U; x3 j - type: Number,
+ t) j) O; u2 ~3 E$ Y# u4 e; \/ d3 S - default: 100
' d, h- B$ W5 y - },- U. m0 @! J9 }0 f
- // 数组/对象的默认值应当由一个工厂函数返回5 V) A% h/ X: E1 k: L- P! O
- propE: {) A/ ~2 Z# @9 X* L0 m& f7 h: i
- type: Object,% `0 }" e/ _2 d2 d
- default: function () {2 s+ u$ c8 v; ~% R+ B; H. M
- return { message: 'hello' }
! o# j: \3 t$ y+ f# ?# q: J - }
3 }( w* U) l4 _' d4 ?+ x8 z, u - },
+ V9 }* X7 F ?% h1 r$ ~& Q* H8 r0 V - // 自定义验证函数+ k2 u. I( P# \1 x
- propF: {
9 H; X% g r7 z" d- D ~6 ?" _ - validator: function (value) {. b. Z" g6 T# m- w! W1 L' X
- return value > 10
0 q+ a9 N7 e7 J# c/ ]" A - }$ Y y3 r& K( [4 j8 ?' L
- }
1 T* g. n0 B) m! X; W3 x9 L4 i - }* c4 e- A( [$ q# {8 ]# x' T
- })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array1 s! p. E. Y" s$ k
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
" Q$ \4 R6 ?) D, {! f2 a
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
/ V2 z4 ?1 @8 T- <div id="app">
( ?: Q2 p8 c/ Z" [5 e$ O8 ]: C% }/ [0 J) Q - <div id="counter-event-example">
: n8 ?( v- w+ R, c1 P- S% D) k, I. B - <p>{{ total }}</p>
" k6 u/ T8 Z1 w2 f6 M - <button-counter v-on:increment="incrementTotal"></button-counter>, T! t" T; i# A7 {% E
- <button-counter v-on:increment="incrementTotal"></button-counter>2 p- e c+ ?- q8 V' v
- </div>
7 |- N m+ h. a/ a% ~ - </div>$ K1 q% s. K: F5 r
-
; g/ a9 ^* x+ G: P- x - <script>* d# G- [, z& |9 z4 d
- Vue.component('button-counter', {& C# R4 m- A" G# ?" ^7 F
- template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
6 F/ S6 m! @% v - data: function () {
0 Q# b( I& S) h* U5 Z+ C) V E* b2 e - return {
% v* P4 A$ e% Z - counter: 0 k& g! T! w7 r) ~
- } U! n$ t# S% {$ P7 M& _
- },! u1 D' y% d; c4 l
- methods: {
0 v- I i" [$ Z/ o+ q - incrementHandler: function () {$ ]. Z. v2 s c8 e/ H( y
- this.counter += 1
7 r1 m Z; t* Z6 V- u - this.$emit('increment')( g9 @/ G0 _. k3 X C* j3 g7 l4 Q) g0 v
- }% R* D% w, I! S. X3 S4 S9 J
- },% q. n( H% W( J; n) o1 E, A1 y
- })9 |) i% Z; W8 b$ b! A1 B/ R3 z N
- new Vue({
3 `, V, _1 w( F4 e9 D: S' c - el: '#counter-event-example',
7 k. v+ X8 Q% k" {1 d7 d& \ - data: {
3 D& [& N6 @ v% l5 }( P - total: 0* z% _. i0 O8 k9 e* f8 |, B* h
- },
, s5 v2 H. g( j S* j" _2 K - methods: {/ F; |* A9 M2 {; O
- incrementTotal: function () {
$ F; A3 H' o7 w9 @ - this.total += 16 |+ X" S6 g, V4 M' G9 Z( j& s
- }+ x4 ~% {6 ^; \; Z- ^+ `2 U8 D! p
- }, T$ S) e: t% w' i
- })
. z: h8 s8 v i& {! R - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册
, W/ I+ S, p8 a( ~3 E - Vue.component('child', {
2 f( z3 I6 R( }% O1 b1 @ - // 声明 props% M+ c) D6 F" M) T# q8 E$ x& u
- props: ['message'],
/ ^3 z. h3 d- U# F8 y* E' H - // 同样也可以在 vm 实例中像 "this.message" 这样使用
) j2 Q2 z% Z4 {0 w+ T6 R" M - template: '<span>{{ message }}</span>': L/ W5 `8 }: b# K6 i! W& p! V0 P
- })
0 w! ^% ]6 r3 o: V - // 创建根实例
7 t* Q+ ?& j, l; q: N - new Vue({
: I, \/ k9 H: c2 o. V - el: '#app',' S" t5 M5 s% H% Z& u/ e& Y, d
- data:{
0 k6 {- }6 |. {7 C+ N# L | - message:"hello",' }* P# ]. ?; X
- }
& W# B0 r+ j; l6 N% _ - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
4 X, q0 ] L5 ~/ ?6 q3 t( Y - incrementHandler: function (v) {
: ]+ ~8 x' O% `$ t0 c( g - if(v==1){
' {. [( {# _" o$ u) W, P - this.counter -= 1
! [1 b8 }9 S9 E$ n0 Z$ s# B# i* R - this.$emit('increment',[1])/ I* W2 W' c: w: |- O
- }else{2 }. @ E2 F$ m, `
- this.counter += 14 H) H& G( H1 u
- this.$emit('increment',[2]), D& G% n8 N3 w
- }
# ~- ~# P7 `/ X0 w7 L* S+ I - }( J9 ^& U k% _! p8 u
- }
复制代码 ! F) W, J- s' K8 _" A
4 z; n, b) A& [. D: h/ _# r6 B
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |