|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
8 `3 n0 E4 ^2 V: i0 z2 S7 l- <div id="app">0 I$ K. |* `2 h: }. x$ x. F; k1 T
- <runoob></runoob>
# l8 Q7 N$ R. a- F$ p- \ - </div>
. P* Y1 U9 {5 d9 q* O- ?1 b& G - C7 S8 f) M2 M+ Y* j! @$ x2 u
- <script>: G% n5 f/ S" \8 ?( F
- // 注册: f8 K7 _; Y* _
- Vue.component('runoob', {
$ p6 f& t6 l- O4 f$ p- p! U - template: '<h1>自定义组件!</h1>'
, J/ H$ I- V+ |; S& p2 r# G' ^' l - })( R) s7 |" U- N
- // 创建根实例& B% I; k4 s, ^* W4 |3 [/ M
- new Vue({. c9 ]3 Q% S; @2 F% |
- el: '#app'
8 _5 V6 Z w. i; O( _% c5 h! {' V8 H - })5 b% M5 U8 o. u k9 ^# s: _1 T
- </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它: - T4 N- `4 ]" ^4 ~, W
- <div id="app">1 H7 C2 o2 n' s# w$ f
- <runoob></runoob>
2 o n9 l* j9 D5 e' g$ M - </div>" D3 W+ n! l9 O1 F( X
-
, J" s5 T/ U2 {( V - <script>* T! V. P+ \* q" u
- var Child = {
# e! e, s; G; V! Z - template: '<h1>自定义组件!</h1>'7 h1 Q! W6 |! E7 `
- }$ z P, [/ E6 k0 a! L
- , F3 e* v2 T/ u7 W* R& H4 [) C
- // 创建根实例/ z0 j/ ~) O4 _8 k# `
- new Vue({
% y- j; w9 E. F, T! ` - el: '#app',
7 H# U$ [" r; G6 Q, m- x - components: {' Z; _: T% a$ u/ ?6 Q7 c
- // <runoob> 将只在父模板可用" f! f6 v2 B( A0 y1 S- G6 ~) {+ z
- 'runoob': Child! y; @' n" Q: B! D0 W
- }
! w5 u/ j/ f# T' ]9 t. R3 R - })( ~) P/ C# s2 G( u( Q$ ^& y- T
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例
8 p3 q8 ^- S9 D8 P# C3 m7 \6 p- <div id="app"> H* I4 q2 k! p
- <child message="hello!"></child>4 U( Q8 e: w5 x' m1 T
- </div>% ^! J5 S3 O" p9 Q
-
3 Y4 ?0 h" F) m& r' r - <script>
: {8 }$ M' O6 b( W- X - // 注册
( l. H$ i+ ?$ H0 P3 T* ~ - Vue.component('child', {& C2 O7 e+ p- C" a( D
- // 声明 props
: ]1 }9 T) s% k3 c - props: ['message'],3 s! g3 c. g$ z
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
' Y9 m5 e: p. O! W" r - template: '<span>{{ message }}</span>'8 y) E1 p7 C7 y+ N3 q$ R( @. P
- })" a; ]% V. ]0 B& K |2 G2 t
- // 创建根实例! |3 H5 g( Z" u4 S/ t
- new Vue({
, E& A$ r* w n" A1 c$ i - el: '#app'% _5 W1 y k8 o3 L
- })$ q3 F* Y5 x) B6 ?$ _
- </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例. z* w. `# S* H0 ^
- <div id="app">
) I% Q6 t8 m6 ?2 g" b - <div>
( h( ]& M* x4 ^5 b8 o' g - <input v-model="parentMsg">
* Y4 v, c' L2 l7 W" X+ @ - <br>5 f2 g: z" R( j# f% M
- <child v-bind:message="parentMsg"></child>0 W& b; K7 V3 |" J0 h
- </div>/ h4 j1 d( f! u
- </div>
) u8 C6 i, U, \3 O' w& e w, \ -
: W" e/ u2 Q, z( I, X - <script>9 |6 t- ~9 e& m
- // 注册
0 F2 j6 X# c) L3 W! e - Vue.component('child', {
. }' R. F1 ^- N - // 声明 props* |4 y# u- a Y2 n
- props: ['message'],
+ I1 R$ `* c2 q - // 同样也可以在 vm 实例中像 "this.message" 这样使用
# z# _5 D4 G! C' i9 N" X. a2 J) @: j4 e - template: '<span>{{ message }}</span>'
5 |( p( r, {6 n# F% M' f - })
! p r5 s, H* c - // 创建根实例
4 l) l+ {3 _8 O2 p `3 r - new Vue({
. C* t- I- r' M) u/ G - el: '#app',+ c; A& g; O# N( F4 C) R$ o/ k
- data: {0 u& O- F4 l* P8 r; G5 s( L
- parentMsg: '父组件内容'
L: |2 g6 J: b+ X! q+ S+ u$ f4 Q) Z5 N - }
+ d/ }$ a1 A8 q! w, a3 |; ` - })6 p+ N6 u: @+ `' |" _* A
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
3 c w: C) K+ o3 {- Q) a# Z- <div id="app">3 |7 k. m s3 j) q% O" j
- <ol>9 d2 q! K$ H, w* _+ Z1 g
- <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>) z. D% N8 @5 ^0 R8 L: x% O
- </ol>
, |* M2 I/ t7 N2 P - </div>( S( ] B) O9 v: U" e
-
$ ]% f! q# Y ?; { - <script>
9 e3 \! j( A7 G8 q0 } - Vue.component('todo-item', {- C5 G$ o" h0 S
- props: ['todo'],/ C# b0 C9 O- [
- template: '<li>{{ todo.text }}</li>'+ X! [1 Q) Y# N3 |
- })1 |, {" ~6 }# S* g% ?2 C- D
- new Vue({/ P+ P+ V; n/ C$ p) z! @9 E7 }
- el: '#app',
5 V, t0 X+ t4 X/ Q R. R - data: {
4 X; L0 t7 ~ C M5 {! f ~ - sites: [6 ?. q+ ]! i& |6 R& r- E, ^, [
- { text: 'Runoob' },4 C. S' Y9 S6 c% @- I r [- I
- { text: 'Google' },6 N- r" } l/ n8 l `8 s( A4 e
- { text: 'Taobao' }
* [& ^: @- }/ v - ]
) V: l2 m3 v7 N# q) _" I+ b - }
1 A! T0 s; N* w2 a( i - })
0 D' L# E) x- N& ~, F) n - </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
: R& n) a6 K3 N4 {4 Y/ A, o$ [ - props: {
& ]( @# R$ F K! ] - // 基础类型检测 (`null` 意思是任何类型都可以); ]# v; S3 c7 z0 t* h4 W
- propA: Number,
* `3 @( u: K8 V* G& n6 u - // 多种类型/ V% u' J6 j2 `3 \
- propB: [String, Number],, l8 v6 v5 L! s8 x/ O6 o
- // 必传且是字符串
; E& t. c8 [1 T9 v; L - propC: {7 g1 z& \7 n" R( a9 v3 u
- type: String,, w* s, Q$ H) [
- required: true
4 l( l' h8 Q* X! W( Z( G' M - },+ ^; {5 w" v( I! X
- // 数字,有默认值
' g0 t' r; j& z1 j. q, D9 | - propD: {/ m* s5 U2 \+ c, W, w
- type: Number,6 K/ K) ^/ o& `7 i2 N* Z" q' ~
- default: 100
$ H5 |9 w9 M0 }& X9 j - },, X, ?, h' n& N* ~) D8 L1 l
- // 数组/对象的默认值应当由一个工厂函数返回
* t4 J- G* V# h3 Y8 F - propE: {
/ U5 N/ e) R, k' ~) w - type: Object,
. R; U" s0 d6 t0 Q) @: K - default: function () {
& r# n J: `1 w7 L( |: `0 G$ h - return { message: 'hello' }
* C0 F) {- n, F% y - }1 c! _9 b# Q8 w* ^0 d) T
- },8 b; q) c8 p" A% C/ {8 _
- // 自定义验证函数& R* I0 L# E5 [+ I# \
- propF: {
& d: e. q$ S' ` - validator: function (value) {
+ Q) q& O& z; ^- y - return value > 10
$ d3 v9 {8 J- n* f5 F9 F& [7 V - }
: _4 k$ T, l" U% ]9 E - }
$ d. m/ E4 j/ N& T: o3 u# z3 P) v - }6 G- ] [, v/ h+ \
- })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array% [% D$ m9 `7 o) _. `( S
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
' |& [% {' @7 K% C; v
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例
& l2 Y; B( i. w$ @- <div id="app">
3 k& ^+ e+ A2 D' x1 m - <div id="counter-event-example">' }. i1 L; ?7 H: \6 p& y2 E* R5 m
- <p>{{ total }}</p>
. D/ q- _8 r/ k - <button-counter v-on:increment="incrementTotal"></button-counter>
' l& R* u9 S6 Y L( @% K! E - <button-counter v-on:increment="incrementTotal"></button-counter>8 Z# [# }; l" E9 z8 |/ l3 v
- </div>8 p) M( Q+ e/ q) ^1 _7 n, E8 b
- </div>
( I5 i% ^2 Q8 }, ]4 e( k -
1 f7 Q3 l0 M( O1 b: G) j+ c - <script>) h1 B2 i/ \% W8 `" P
- Vue.component('button-counter', {
/ k0 o) U# W [- Q# I4 s1 z - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',% J( B: \% D. P; K, w$ | y1 _
- data: function () {
( p: O: l# o/ J% A - return {
- `% p2 q) H) _ - counter: 0
( d- n0 [7 T$ ?) _" N e) A' r* \ - }. q. u4 S7 l. X* U, l$ f
- },8 V% w7 N6 g) R4 `
- methods: {
* M) w/ T" X5 {* W2 N - incrementHandler: function () {
/ R" _ ]6 m0 \' D- v, g- A/ T - this.counter += 1
* ]9 ]% T1 \& X% C! M - this.$emit('increment')( P8 V8 }4 ]+ x
- }
; R7 H5 e% Q3 T+ Z+ h( Q - },% Z' v7 x; H- \6 @$ S
- })2 e& w2 v6 o. ^
- new Vue({! z: p- d$ o: b5 Y
- el: '#counter-event-example',
6 [) ?3 L9 }4 Q7 L) l9 c* s - data: {
9 e% q/ A. O R - total: 0
4 c( ?( ?6 n& ?0 z+ a2 o - },( H# ^4 ~ K2 {$ x* {$ \
- methods: {: d* p. G/ r& ~$ U4 M
- incrementTotal: function () {: H. V+ m, _: n) f
- this.total += 1
1 ]6 x4 l; K, v( w8 {9 v - }. ^9 i+ P9 q: U$ V) k
- }
( }, Z K' d% f8 T - })
+ |2 R- \0 P* Y8 a+ d7 q* i - </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册
4 H% f/ V: I- a - Vue.component('child', {
3 e2 B, B$ w' B# n& f - // 声明 props; y$ W% |: D3 o
- props: ['message'],
$ J/ j" K; W5 A: x$ [) d - // 同样也可以在 vm 实例中像 "this.message" 这样使用( m! t& {* f3 T& ~
- template: '<span>{{ message }}</span>'
. L* r+ _% f9 a! w+ K1 P8 {& A - })3 t; s# M( p( N6 E u* Y
- // 创建根实例7 k( r/ d# K% {# U8 j" M! s
- new Vue({3 m1 f' |7 T2 f1 h2 Y: }* a8 y
- el: '#app',
6 P- l5 x7 F+ A* K/ i - data:{
' Q: O; q9 ]9 }4 Q - message:"hello",
7 B$ V' c* k& U; t$ G8 i9 M - }! \5 V4 U e% s" h& h5 S9 Q
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {
# |) q3 n7 V9 e/ m9 s3 l) C - incrementHandler: function (v) {
3 H( j& H2 z3 F. d7 V5 c& F - if(v==1){3 C) x/ m: @) R+ x6 e
- this.counter -= 1
% K. X1 ?4 x! W4 t - this.$emit('increment',[1])
/ e) A6 R7 p) U% Y V( u2 T7 k - }else{! p, A: V# [: N- O7 q/ y
- this.counter += 1
; t2 Z5 X+ K1 i5 ? N& u - this.$emit('increment',[2])
8 m/ o3 k4 K* e, w( C5 R - }1 W7 a1 N/ F4 d9 g& |
- }5 _9 ]' L @( S1 F) {
- }
复制代码
+ \, f# l& |5 V/ u+ Z7 v: ?% O* o- C' Z- c. q3 j5 D
|