cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
" g. z5 X$ x5 z0 |$ J, I
- <div id="app">
9 ~+ Q8 N9 Z) ^& a - <runoob></runoob>/ {/ d# G; K u( j9 _
- </div>( y$ H- v" k* S4 S& v3 m/ m
- 3 d5 U: Y1 d* W; T' S, }* ]& f0 M* W
- <script>3 O: K* `) ^7 J. v1 i. X
- // 注册
) H6 p: q/ [ f' r# c1 i- `* P4 ` - Vue.component('runoob', {
4 {6 J8 T: {" e* v: B9 w, a2 e - template: '<h1>自定义组件!</h1>'
' O: n* V" f% |3 y - })
* K7 q2 P E7 ~7 H8 | - // 创建根实例% b5 ?9 f/ ^9 ^) o+ Q
- new Vue({
, Q' [4 \* J0 R& t - el: '#app'
( }( ]# Q* P7 M1 o! z; u - })/ ?$ r, E0 _. e) r, F' r# j
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
/ L1 q+ t/ A4 T
- <div id="app">/ v3 C) G* G6 S+ V* E$ q( `
- <runoob></runoob>" F4 w% c- L3 n- y( G
- </div>
+ `$ @2 w( A2 T4 p, ?, Q. L! d -
5 l ~7 m# d L& h9 b# `1 Y - <script>/ A$ K4 G; f4 C: D' i+ z0 J; W
- var Child = {
! s1 S7 m# o" X - template: '<h1>自定义组件!</h1>'
- f0 |7 |" R% [ - }
! Z0 Y0 L+ U# {! P1 v+ p3 U' o -
7 h; Z5 Y: a7 k+ }6 q: [ - // 创建根实例2 T) g5 m* o* ^' M- c$ X
- new Vue({
% W" o7 F6 N) ]& ` - el: '#app',
7 _% Q3 Q6 m- f' I - components: {' `+ Y; Q; C% S {
- // <runoob> 将只在父模板可用
1 ?9 Z3 E% l# Q - 'runoob': Child
% Z1 ?- V+ G) ~& v. U" F3 h0 ?* W - }
1 i D9 x8 r0 l. L' o; x - })
1 Q' u5 X: O' \ - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例* t% X$ d, f7 n4 q: e
- <div id="app">
% }8 l0 ~& {) V/ @0 B7 L - <child message="hello!"></child>7 C' e; p& v' i# k# h
- </div>
3 N; s5 a! r2 t8 ?$ V -
* L0 p5 h0 Z) R( R0 ? - <script>: S8 i( W% n5 X; `, V
- // 注册, A+ S* w+ [& e9 Q6 H
- Vue.component('child', {. ]4 P& I. r( M$ r7 F" \( d
- // 声明 props7 Y/ s$ f1 \4 R2 h% I4 p6 N
- props: ['message'],# E. u6 f& q; g' G
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
+ w# W4 q6 i% X! r$ e - template: '<span>{{ message }}</span>'% K x8 W' Q2 Z# t# t1 h8 x ^) a
- })$ L$ i7 B; f! @7 V# c! Z" `
- // 创建根实例/ g @% O, I: p5 b0 ^
- new Vue({, M# E- V& u! @) S# L+ Z) ^) y
- el: '#app'; c6 N2 S7 ~& d* {
- })! x1 K2 O) G$ k1 Z2 E& I5 Q
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
: M- B: z+ J9 y! H- <div id="app">
; e9 R) [5 M6 v+ |% z6 n1 g - <div>$ y# }2 l6 d! A& {0 A/ J
- <input v-model="parentMsg">
; _4 r0 c& O3 ^) h4 y - <br>) h$ ~# e2 i* g; {+ x& H
- <child v-bind:message="parentMsg"></child>
& j2 B' y; l. d' \( Y$ k, A - </div> w, w% |3 W% h& E
- </div>+ y7 Y# n4 k9 ?6 _" ^: R, g& y
- , f6 F2 T/ Z7 j4 Q# L1 P
- <script>
5 i% ]$ |. a! M+ P' P" r& Y1 i - // 注册' \$ _- H8 v: F8 n
- Vue.component('child', {
( t- W2 H% P& H. m0 U4 e: H( U7 q - // 声明 props
/ ]5 R4 j: n- w' ~/ L# |0 ~ - props: ['message'],, ]& C9 d9 O6 f6 L6 f
- // 同样也可以在 vm 实例中像 "this.message" 这样使用" A7 i* f$ `1 o9 O
- template: '<span>{{ message }}</span>'
4 t0 m0 D t+ v/ {" W - })
& `2 F0 W4 Z# H- H3 N - // 创建根实例8 p& F! D3 R# o5 _7 y/ p
- new Vue({
* h! T1 Q5 _8 m6 l5 s - el: '#app',
0 w0 u! U/ k" g. x) ]0 ~7 ? - data: {& `- P o( i# z* p8 ` d R
- parentMsg: '父组件内容'9 K* i$ Q3 R, z3 j3 Z8 K+ B& `
- }
) `6 @: c0 u/ K5 m7 V( ` - })0 U1 W: F" l, h R% f( u2 Z
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例4 F+ f* d% l! m& a" F
- <div id="app">- X) P) Z1 _( s# _, E, K D
- <ol>( d4 b( U% V$ U* L) w# k; E
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
9 w9 M7 l1 ], C: w- r - </ol>
" d" L$ e# G% Y: w - </div>
4 m0 a4 a- E% T' k$ Z7 s, K2 X - % b! C+ v$ J1 m$ ^+ e& v
- <script>
2 q, g, j% s5 i# d4 R - Vue.component('todo-item', {
* L9 w6 a9 o% N" T1 m' ?6 U( b* h - props: ['todo'],
- T1 |( J+ B/ I - template: '<li>{{ todo.text }}</li>'
9 |1 O3 C( Y* u" D6 R) P: y* D - }): v. ^ y; G' ?7 |( z& y( S
- new Vue({3 {1 g; [. ]- M0 A: K
- el: '#app',4 u! t3 q2 u& G0 G6 v
- data: {
$ J# x- W4 c4 E0 m7 n2 p - sites: [" Q4 \" n& Z! f9 |% P
- { text: 'Runoob' },2 m" c/ a; F9 h g1 w5 b. F0 j& e
- { text: 'Google' },
2 O# [5 d$ Q/ t) d - { text: 'Taobao' }
7 s% a/ p2 S1 U - ]* E% ~/ w& R: j: ?- M
- }
, \ I+ m J+ [9 {( b( f% y% z - })
) V6 V, p8 I- o3 ]6 p: T+ E# f - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
4 k- k0 d" D0 |- m# k$ W - props: {
/ T* Q0 M$ L+ J( T S W - // 基础类型检测 (`null` 意思是任何类型都可以)2 O- M* s* l1 M) M/ V
- propA: Number,
0 e) A0 G& t0 l - // 多种类型
* \ L' U& u: Y" C, k - propB: [String, Number],5 L6 o; j% @' I. K
- // 必传且是字符串
1 ?6 A7 {3 Z6 b* C9 Q - propC: {
_/ y$ D& ?/ v+ P% Z( s - type: String,
( B! G0 B) x; F5 M - required: true3 C9 W& @. p0 E
- },
, J/ z! l9 X# c& Q2 c, J ] - // 数字,有默认值
- H8 l% _5 x$ t, ?2 R - propD: {
# B+ h5 A; s' b& M. W6 t) g - type: Number,
s; Y) e/ ^% S+ Z( d* ?3 K0 ~ - default: 100 N0 A# |1 N/ v* i9 q8 U6 M8 P
- },8 J+ F0 P2 s" B' _$ M: `$ ^
- // 数组/对象的默认值应当由一个工厂函数返回" k, V+ h, s: Y: y+ Y' o% w0 E
- propE: {
6 F5 G Q* r4 ?7 s1 \ - type: Object,
& i- B# d/ o$ [0 e) T - default: function () {7 Y2 @* C4 ?7 R$ J" U
- return { message: 'hello' }
3 N' ~" k1 k0 r! w" Z/ r - }6 D. U7 L& T1 k# u
- },) O$ A. ]+ x$ g% Z* X' \9 o: C
- // 自定义验证函数
' X3 Y* G. u7 L; @9 A - propF: {
' D) ]4 z3 b3 } - validator: function (value) {
c1 m; p' x( Q( d- I$ O - return value > 10, w3 n+ T5 u6 s& B+ X
- }
8 M( p) \- E2 G. I; f' N - }
# l, P: A: K' J% Y6 c. f - }" ?, U* @% ^8 F+ K7 d* n. ~4 F
- })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
, \+ d6 W" C. r' I; {: W
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件8 Q& t9 M1 @. [5 t4 {
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例 Z: ~+ Y; p2 {" k8 c# E* S
- <div id="app">
. d2 `8 Q' F4 M. f) [# P - <div id="counter-event-example"> I- h' g7 i* V
- <p>{{ total }}</p>
1 T0 k7 h2 {3 d! ~' m - <button-counter v-on:increment="incrementTotal"></button-counter>
~! d9 U0 t+ t8 ~, j7 z - <button-counter v-on:increment="incrementTotal"></button-counter>
" x: x. O* E0 l3 l/ e) r4 Y3 h - </div>* j7 y9 Q h' e' C- k: O
- </div>/ S* Q9 V% Y- X6 O& E& O7 V3 Y8 h
-
" R, L) {# s. M. P# V0 P I+ ] - <script>9 s0 e3 I2 ~! |7 m5 \3 ]
- Vue.component('button-counter', {
$ h& F: h0 G' r$ b: R% g - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
+ T/ J6 S( x) x: S- H# c& P1 d0 S3 C - data: function () {' J) [: }% G; j; e6 ]1 I
- return {$ C/ K' Z" k/ L
- counter: 0; c% Y1 J! G2 R. S: }/ J0 K
- }/ ]+ H# ^( o0 S
- },: n! w" u- D1 j1 v. X; ?
- methods: {
1 ~9 n8 X1 N2 [6 O - incrementHandler: function () {
Q5 b9 C9 A) {! g2 A- T: J0 u" | - this.counter += 14 H. B0 z% ]7 x
- this.$emit('increment')+ i5 g. \5 I2 I) o0 [
- }$ S- c7 f0 y# m1 Y6 A& [8 o* J% o# ?* h
- },
5 w, \( v ]9 T3 W5 M- Q: I1 r - })
0 B" P5 D/ E& {3 o - new Vue({2 H5 i3 Y6 Z" ~
- el: '#counter-event-example',7 ?- B5 e+ U6 i3 h
- data: {
0 H+ n+ V$ O( J - total: 02 [8 _+ g4 ^) x v) ?6 R8 A
- },
" x7 }5 k [& I y$ v" ]2 P - methods: {+ _' z* [. J3 N$ d9 W4 V, V5 _8 R% E
- incrementTotal: function () {
8 {1 o) {) y, g. E - this.total += 1
3 V1 ?' L; P+ z2 @! y" z( a0 t; j - }
: B2 f* Z3 P6 ?. G) Z. A* }# G( H$ d - }
* f+ ^% z; m8 m; ]4 l" Z ]4 L. t* s - })
; ~1 S: n7 M# f - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册" U4 j" T7 h) l
- Vue.component('child', {
9 r/ H' e& w4 ^: G+ ` - // 声明 props
1 e. c( O4 z# v. Y0 G& v2 o2 H - props: ['message'],
. N: R0 W% W6 J: J+ s. |( c# z - // 同样也可以在 vm 实例中像 "this.message" 这样使用
( i3 R+ V; k5 [- {0 C9 o - template: '<span>{{ message }}</span>'
: F* c* Q# Q3 s% ~9 u - })
7 k0 K9 x I" U7 ~9 A - // 创建根实例
: z' b1 y O& i$ S( {& y - new Vue({
8 o6 `9 t; Q# L$ X& n1 @ - el: '#app',3 e3 M$ L+ h: W4 d! p/ p
- data:{
% a r9 |1 B: x- X" N; @: o; o - message:"hello",
. H& H4 F5 ?1 D, ^( V1 t* p - }
% L0 ]3 D/ ^% g7 U8 ?% Z v - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
, K2 s: u3 U T - incrementHandler: function (v) {
( N! r0 G$ m6 d8 R - if(v==1){
' @5 C: _0 u; p% i. r - this.counter -= 1! F+ p8 V0 S! J L. ?+ F
- this.$emit('increment',[1])( {$ O. O' ?, f" E- V2 ]4 y+ a# t/ k
- }else{
4 H6 V& h8 O6 g3 m7 j0 H - this.counter += 16 @: ~1 S+ ^2 {- H
- this.$emit('increment',[2])6 T5 c, r# I1 D& l5 z8 g
- }+ r# w( Y$ N: E! T
- }
6 X4 j0 `/ D4 x, v - }
复制代码 1 |( S/ }( {5 u2 ?/ H. }. ]4 @2 E
1 }3 x: h3 u: G% P5 f- } |' ? Q. s" u
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |