cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
2 Z8 D1 F1 Y4 U% D. e1 o" w- h
- <div id="app">4 w+ a+ m4 H' F0 J2 Q5 n: _: i
- <runoob></runoob>
/ C0 n+ L, c. R" [! C. @ - </div>" |. ^" r9 H- {2 O. V# x
-
0 ~) b K( z! G; L& J6 D z - <script>+ m: u$ o# v( l* |: Q
- // 注册$ D' J5 `5 S0 ]; Q/ t
- Vue.component('runoob', {
9 s% J. q9 P: Z" }; B - template: '<h1>自定义组件!</h1>'
' ]# d% X6 L5 s$ u6 m7 K - })0 |4 i7 T) C; v! Z2 h5 ?
- // 创建根实例* f8 R! E" b0 _
- new Vue({
& E: b2 ]& m* ?/ K' g& r! W - el: '#app'# C5 ^9 G- w ~* @; L% n
- })- u& r" Q9 \5 {/ Y, d% m
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
3 b' O1 G# ?# K# l7 ~+ _1 r
- <div id="app">9 c8 p5 Y: z5 I7 O9 |& u( E
- <runoob></runoob>
/ ? [9 B2 @- f5 v( _4 e - </div>
; f+ C" d5 P) Y -
. ?3 ]* k$ r2 G5 w' M$ Z2 c - <script>/ ^. @0 L% A: w
- var Child = { g! R" Q4 H% D7 v4 H4 v
- template: '<h1>自定义组件!</h1>'+ P) n5 D$ e0 o3 u
- }# F4 {" Y) E0 ]2 u$ P6 |/ B" B
-
4 h4 g/ g. j" T6 X7 } - // 创建根实例
- G/ \& ^. `9 C- i# H B - new Vue({5 o4 p+ Q# |/ |" r2 Z
- el: '#app',
9 d1 Q- I0 k2 ` - components: {# o" O! I' @2 V) ~# {
- // <runoob> 将只在父模板可用$ q- `3 y6 t0 @, y7 M1 x7 X
- 'runoob': Child
A7 I5 n/ R. I5 i - }! ^0 q( M$ R# Q( a8 [+ B
- })$ I. m& v) u" l: }5 E4 |
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
0 i1 x, H& @. C3 S- <div id="app">, u) @* h) T0 Q
- <child message="hello!"></child>0 a" F* o* O: N
- </div>/ |9 v4 r; w' b2 {4 `
-
/ b( O" d$ N2 ?5 Y2 M5 v2 l$ G6 W - <script>0 Q% b" ^* t" l/ I3 l$ R. l6 h7 b7 M
- // 注册
+ V4 P0 s2 O+ [2 }, k! W7 v - Vue.component('child', {8 z; }/ }1 X3 J& k+ H0 W* Z
- // 声明 props- S; g X0 j, ? G
- props: ['message'],. u; o5 W: q* Q, T
- // 同样也可以在 vm 实例中像 "this.message" 这样使用( g" ^- G1 q% y9 A2 `
- template: '<span>{{ message }}</span>'3 f/ [$ X- D* u0 h7 m
- })
2 [! G3 `/ w/ M7 u - // 创建根实例
: H# I+ E: Q5 V, G0 W/ g4 r - new Vue({
( d. x# {1 s; E* g' b - el: '#app' s) x7 v9 F$ B& v# u0 u8 G3 S
- })
- y0 g: W4 M# g* E" f - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例) }% @4 U4 x. I+ i
- <div id="app">/ v. V3 D6 V0 y8 k, ^- B0 Z( }
- <div>
! @/ c, j$ ]! R9 l! [$ k9 R9 s - <input v-model="parentMsg">3 ~# L: ?4 r' T9 f* F$ d. S/ ~
- <br>4 y3 G6 J1 D0 @, I; Y) [+ Z; a
- <child v-bind:message="parentMsg"></child>5 F: B, J' l- o( D( T) m) T H+ t! [
- </div>
_- s+ B% b3 i - </div>
8 ^& U( \6 u( W3 j+ U7 {, t -
( y) ?' F. i4 I, T" N - <script>% l2 A2 T) W5 j4 I) ^
- // 注册- b) T" L6 x0 ]+ p" M
- Vue.component('child', {
7 t* z7 n! c2 }: T - // 声明 props3 B& G0 o' Q) P' ^* @7 m
- props: ['message'],
4 O4 M2 l4 r) T% C V* W4 { - // 同样也可以在 vm 实例中像 "this.message" 这样使用 P! v* o, {3 W8 v, l6 r
- template: '<span>{{ message }}</span>'6 Y- M5 H l) Q9 B% Q- K' d
- })" e& n1 ]9 Z3 a9 c9 v
- // 创建根实例
% t% V6 S3 a Q5 I- b# S7 X1 W - new Vue({9 ~4 k8 C9 i, n0 E
- el: '#app',! q4 }4 B$ d1 R7 v5 C! Y J5 M
- data: {& L# X7 b+ _0 Q: I
- parentMsg: '父组件内容'
' W7 V7 b$ o, g! d' F - }! \: h. e, G. w4 g
- })$ H4 y" o" {3 f* {, K& c, X
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例2 r6 l6 S' C; }' ~8 ^" p; F! a# T
- <div id="app">
" o! H1 f+ b" v. j3 \& \ - <ol>8 `" r) P* R% [2 `2 u
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
8 t/ A" O& {6 V: Y: w3 t - </ol>1 K n- l3 H% k9 C/ |2 Q7 z" E: `/ v
- </div>
1 X0 s X- ~9 f& O# u7 z2 I5 V - * @8 _4 _& N+ |
- <script>
_# ~7 E/ F, R - Vue.component('todo-item', {
) v, b) K6 ]7 G. G% i( [ - props: ['todo']," V4 l" w' s, G/ W9 k5 r6 c/ n
- template: '<li>{{ todo.text }}</li>'( y) A/ S9 O, M+ ]
- })
3 \- i1 C4 D$ `/ S' e% a P3 m - new Vue({
/ n2 G, {; q4 f1 m. R - el: '#app',
/ j) @! a/ F9 _; _1 g - data: {
3 F; F7 S. A+ |" J4 u- H/ X; T - sites: [: X$ c$ q9 a; w- ~% K
- { text: 'Runoob' },' T) [4 N. V7 T2 R
- { text: 'Google' },
]) L; _- E3 E% l$ d - { text: 'Taobao' }% U( K. Z+ F* ~
- ]$ }- q" v+ B9 ?# @, i
- }
$ p" r( t& M- x0 n( M: Q n - })
+ P: u( u, [/ R# K5 [ - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {. M+ c! m: v0 @9 y" o6 f
- props: {4 u/ t! E0 K. `0 L' m
- // 基础类型检测 (`null` 意思是任何类型都可以)
7 O6 ?- r5 [( v/ K - propA: Number,
2 ~5 ~ C5 S% A - // 多种类型+ l1 K: g" _, G( ^6 A& t* t% r; B$ u& ^
- propB: [String, Number],7 t% D: N/ u! J. _. q0 L
- // 必传且是字符串
/ B1 ?" x7 @6 R ~: `' r - propC: {
& ?# ~2 t) x& i! D8 N' M - type: String,: z( N' m) I5 h, H7 ^1 S/ }6 i
- required: true; }; D2 U8 j7 v* k! }2 v
- },
. J0 C: r6 I, H* t - // 数字,有默认值
9 I& c5 v9 g( ]7 n3 t - propD: {* j$ K' J) D3 j2 h9 F; d/ m/ c
- type: Number, F, \+ q, J# G; }: w1 i
- default: 1000 m8 e* q4 \2 L2 x m/ a
- },
2 F9 p6 d4 T; Y0 K0 x4 {- s' M+ O - // 数组/对象的默认值应当由一个工厂函数返回
2 t1 U3 k7 F$ j+ {6 u3 v - propE: {! `8 U! }* T$ G: T& k+ t( O
- type: Object,4 j t a9 \# w% c- A) G0 m
- default: function () {
' ]: I, @* e- G! q9 [ - return { message: 'hello' }% ?+ D1 U6 a3 r8 K2 w6 p0 r+ S
- }
: j* O7 g. C0 O1 @2 c" J - },
" }& i8 m" K8 N: ` - // 自定义验证函数* g* x) M8 C3 A! l
- propF: {
+ d- t& D, O: g. _! _ - validator: function (value) {9 M9 G' y' _7 t% l* [" E
- return value > 10
0 a1 H* Z' ]% T& a `7 D* S4 J& H - }
5 Q% |* d7 p6 m - }
$ s2 H& O. g T! D: p( b& m - }
5 z8 g, W" Z- Q' }) Y1 j5 z - })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
( u, |& I6 v% k; ?4 Y+ W4 @
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
& X$ Y# o( E7 Z- ?3 X
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例
8 E2 X4 I' S V8 v- <div id="app">
G. Q9 W; h4 E$ x - <div id="counter-event-example">
/ \2 _' ^* J* P; Q" b/ Q: L - <p>{{ total }}</p>
! }0 K% b5 q" b# z' G - <button-counter v-on:increment="incrementTotal"></button-counter>& v" g! H1 {9 }# ?, F0 O0 h
- <button-counter v-on:increment="incrementTotal"></button-counter>
# S6 M, \: p7 i5 q - </div>
- N% ^& j9 R% n$ ?# F - </div>
: V; |, z9 G1 \' g - - H2 L1 ^+ Z' ?# k9 b
- <script>; Y8 @" u$ \' l
- Vue.component('button-counter', {
; W6 c! J# `2 a: S: N - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',& G" J- `- g3 n- E, A1 m
- data: function () {
0 B4 v- L" k' h3 o/ s1 Y& c2 U - return { k4 |( E* A/ f2 E2 X* D# W
- counter: 0
; p" r# ?/ y/ i2 F9 B* g - }
6 r- O. Y2 {6 c5 w* l - },8 F" z2 e' _" n: r; U
- methods: {) P4 l0 }5 O4 N7 E; s
- incrementHandler: function () {
- w% s( p% d) l( }0 d5 H - this.counter += 1. z5 h, _" C( U, B( y
- this.$emit('increment')
/ P4 M& V" o, l# ^. A - }
0 p6 ]- V T. y0 e - },
( R) _/ @, O6 s* @% W7 D - })
' [. Y$ \0 R# b8 W { - new Vue({
7 R2 n1 `; z3 R* x, T" z9 S5 f - el: '#counter-event-example',& S7 z& F0 c; G$ t9 k: l
- data: {- u% K7 ]( R$ _" \& ~
- total: 0
3 m% y g F' A0 k" _ - },5 _/ _6 x: [7 E( r0 z
- methods: {
$ N: c! C7 s; O - incrementTotal: function () {& g4 g8 M' Z4 C: N
- this.total += 1& j# X) |/ ~3 o4 _5 A# G3 I
- }
4 u2 x; Q( f5 k6 b' K, @ - }; X" q& T: a; ?2 m3 i' `
- })
" E/ z0 N% v( q' { - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册
/ A; E( `0 Z6 @ - Vue.component('child', {
5 u7 a1 S0 T6 [; ?. V/ w0 [ - // 声明 props2 k4 F) m" }0 `% K+ R
- props: ['message'],# L" I( A& D# J/ B$ C0 C
- // 同样也可以在 vm 实例中像 "this.message" 这样使用5 l9 d! O4 r# g7 @- q$ D
- template: '<span>{{ message }}</span>'- }) L; e% \+ Q
- })5 }9 z W* @; I6 D
- // 创建根实例1 {" n d0 l( x3 P3 _9 W& l
- new Vue({1 c; z, Z) m- |+ t2 t1 y
- el: '#app',8 g- _2 `/ M$ }! Q9 ~" X( P
- data:{
6 ~$ d" v9 Z+ l1 `/ S: V* w* c3 n - message:"hello",, q3 D1 }) M1 w! B6 B% B1 k; a% G
- }
+ s" K5 J) q+ A; O! z: T8 c - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
4 m. s- @* @9 g - incrementHandler: function (v) {
% W" `$ Q4 M8 n( V$ ~/ w - if(v==1){$ k: \9 _3 W- g/ }# n4 j# u
- this.counter -= 1
3 X E2 Y! ^9 J5 r( L! u - this.$emit('increment',[1])
4 O+ b+ ?7 Z5 Z: i" Q - }else{6 X/ U% J# q. r4 ~3 q0 _ O
- this.counter += 1
; c# i0 k" [7 a+ x( d6 P - this.$emit('increment',[2]); h# k4 {& N& W( A/ F. f2 J2 U
- }
5 j1 Z! P9 P* t9 M3 _' t& U! M: K - }
3 G+ ~9 ^9 t- V. F - }
复制代码 # p* O2 X6 J* X. x5 q% r
- c, N2 T, x% z' e
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |