|
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 注册一个全局组件语法格式如下: - Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件: 全局组件所有实例都能用全局组件。 全局组件实例注册一个简单的全局组件 runoob,并使用它:
k/ o( j- V7 R. x# p- <div id="app">
9 m( b3 O( q7 D v9 B+ P - <runoob></runoob>2 z [, w& \, J! B& K
- </div>1 C* P9 m' X" C! ]( L+ \' C
- ) h& h) Z1 u: |9 y
- <script># |6 G. r+ i" W2 x/ @
- // 注册
4 C5 i/ T# y, t* j& d9 P. h D - Vue.component('runoob', {
) l& S+ v! m, x, U# {& r - template: '<h1>自定义组件!</h1>'& V& [0 f% V# {. S+ C8 H W
- })9 h: d& Z2 d8 F9 f4 N
- // 创建根实例
8 d" E% k8 r! Y1 X3 |* H* z5 E - new Vue({
3 l' k9 o1 m* Z" Z/ ]8 ^ - el: '#app'* W# y2 y4 s$ {$ @0 q, Q1 N
- })
( {$ [2 l/ q. U8 G/ P- C( t. { D - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用: 局部组件实例注册一个简单的局部组件 runoob,并使用它:
# k: p9 T8 Q' s- <div id="app">
9 r% X. v' ]9 n - <runoob></runoob>' U# h, D( }2 }" W
- </div>
' m. ^# O8 A9 l -
3 _0 Y) d& M& {5 R2 C - <script>( s9 Q# ~( H- @2 U/ h6 w% y
- var Child = {
4 l) w: d; Y# m - template: '<h1>自定义组件!</h1>'9 ^4 V. D* `& _+ g5 ^! F
- }+ ^4 |0 u0 z' k$ _6 f
-
: e; ^; Z4 v: D" C7 i S3 ` - // 创建根实例
' k/ Z; j7 d) Y+ l$ U- w - new Vue({ ]: W# U; k/ T* Y e F
- el: '#app',
) V9 E) ?7 c6 I1 g - components: {' K9 [. ~5 G6 |8 m. Z/ t
- // <runoob> 将只在父模板可用1 x% H- K# F: T/ O0 }+ R3 B
- 'runoob': Child
/ Z' W5 g: d/ }% t; Y1 z. A. V* ~8 _# x - }
6 \) }+ |9 U, ^5 ]5 F q - }); q I3 K0 _$ R
- </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop": Prop 实例" o2 I$ T3 e" N+ I, i: l' p% {
- <div id="app">+ b# E/ N* @% g/ P, M/ K
- <child message="hello!"></child>% i) x; i* Y7 g2 L1 g, T
- </div>& S [ L3 I Z
- % W& m! ^7 N7 S# d
- <script>1 J1 c3 n+ i' \8 y* A0 k9 H }
- // 注册
" m! g8 b' d& y5 P - Vue.component('child', {
! t7 ~0 _( [/ u; b+ E) J - // 声明 props2 \$ a$ Y$ F, d9 @0 J
- props: ['message'],
- y" \6 s) A; u* I+ o - // 同样也可以在 vm 实例中像 "this.message" 这样使用
1 K, `' u2 u) L* {# i4 p - template: '<span>{{ message }}</span>'
7 [' Z% I' @% l; A# W - })' s) h4 s/ ~: [
- // 创建根实例
1 V8 @6 G, f. B# _$ H8 j - new Vue({
7 G- n+ b3 Q6 y# ~ l( y - el: '#app'$ w7 Y* S) N& p5 n% m7 v- V
- })
9 F$ ^3 \' u5 L8 f+ z9 o, a0 w - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件: Prop 实例+ \$ N1 q _0 T" U1 Y
- <div id="app">: H2 c$ {3 E2 w, j/ g+ p
- <div>
8 B: M* a& t/ j" \$ l8 v% y - <input v-model="parentMsg">$ K; Z6 h" _/ g9 W6 R
- <br>' N& P/ v/ u3 L0 c2 Y
- <child v-bind:message="parentMsg"></child>
. w3 T! i# }) s9 l) v( {; ] - </div>
$ @5 l/ j" h' e: H) H - </div>- ?. @1 ~* p- E1 _1 l) h9 I
- # i- a( { n4 T: u: B4 i, ]& \
- <script>% ]. e& S' {' p. @/ V3 c" O: E3 p
- // 注册
4 o5 z1 G$ G2 h% c+ e; `- _ - Vue.component('child', {
0 q: a. p/ o* z: ?$ O# M - // 声明 props
* W; i( G3 W( m K7 F - props: ['message'],
: w# B2 y: u. }/ Y7 k+ n# S! u; M - // 同样也可以在 vm 实例中像 "this.message" 这样使用
/ J4 k, w! x2 T% _ - template: '<span>{{ message }}</span>'
2 n5 N' S" g! `3 n) n/ x1 O - }) G U7 H& i! R" d8 l( x7 \) K4 A
- // 创建根实例' N" j! U* C& {9 [+ @, r" y
- new Vue({
. P; M# u5 y$ z6 s8 E- P! t - el: '#app',
0 W. k( `2 G/ ` - data: {' b7 O; V: n4 e3 m6 p" Y
- parentMsg: '父组件内容' c+ q) v9 h A$ m; M
- }0 t: P" u; d! \& H* A3 P3 Z3 ^
- })' w% r' y9 z; y, c5 z
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中: Prop 实例
1 G. T8 h+ [+ }! c2 K2 k, G/ b- <div id="app">9 _# [8 b6 l& U
- <ol>
& Z+ u1 }* S; y; G( S, i - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>" }5 b# {1 d/ s ~2 S% ]* H. m8 _6 \
- </ol>
% n0 o# p+ K- ?$ K4 y& J3 S6 K - </div>% b" v. [9 M4 V) }% I
- * k) O: s) x, d9 r" u* ^& I
- <script>( {5 L2 @. o, {) b
- Vue.component('todo-item', {
3 z* \/ M0 J- |8 b& u2 @ - props: ['todo'],
: b9 O- R W. _4 p# R9 R - template: '<li>{{ todo.text }}</li>'+ i" r6 R2 Q) n# }5 m, e8 ~+ ~& J4 o
- })9 Q0 e' p6 g- c& R! o
- new Vue({& S( T9 \) }( r! v
- el: '#app',5 X; p" |* m. W& }3 {
- data: {
$ N( r' }" @% U, e: b, M - sites: [0 `$ k; S$ m- z$ }, M
- { text: 'Runoob' },/ ]/ p" J5 S+ z; e% L- V f: I
- { text: 'Google' },
7 R6 C! b+ U0 @" w( C2 @ - { text: 'Taobao' }; M3 D/ ~) v! [9 }9 k
- ]
, t* T; d' v5 p; U, b - }
1 Y0 h' {8 c5 [& m/ E/ ^4 S - })" \3 W1 D" |0 S2 y4 t+ B
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 Prop 验证组件可以为 props 指定验证要求。 prop 是一个对象而不是字符串数组时,它包含验证要求: - Vue.component('example', {
2 \5 B/ C$ k2 v; e - props: {0 Y7 `3 v* _/ o( U* F
- // 基础类型检测 (`null` 意思是任何类型都可以)8 V6 i7 H; \$ R# x1 k6 O$ R
- propA: Number,# Q4 w1 h- o R) I8 s6 D
- // 多种类型( i W- q6 E; p/ l/ @" t7 B
- propB: [String, Number],
G+ W" u) d) y. B( R" N+ C. M - // 必传且是字符串
7 s& q$ D( z+ I' t - propC: {
: L9 O) B1 z& e - type: String,! a3 o' { N/ O" b
- required: true
0 g* u- b3 v" N3 s% s: `- s5 E4 c - },; U4 y4 D. G0 K! G) a
- // 数字,有默认值, C- X6 H: C+ a* J7 c8 ]
- propD: {
! n3 T# g" r% F4 g0 W2 c8 ]: u8 f - type: Number,
% @+ _; i K i( | - default: 1003 F2 O* C8 E' u% \% U
- }, U3 H8 Q' ^$ w* u& F( V
- // 数组/对象的默认值应当由一个工厂函数返回3 w) A! H$ z2 b, }6 H5 ]3 B+ C
- propE: {
# x. }8 q: M. M+ {5 a" j - type: Object,: r# p3 @) W1 s
- default: function () {
. [& w4 z( Z* e) s5 b - return { message: 'hello' }/ |# T5 C6 T- D2 J
- }
% B1 Y0 `/ @8 H7 ~0 e- D, @ - },0 b3 o' C n! H& g$ e4 L# V
- // 自定义验证函数1 b6 c- C0 ^1 _; `
- propF: {. Q/ I( N* [1 W
- validator: function (value) {2 s+ |3 R4 r7 h# |$ V" y
- return value > 104 [6 D3 P- z% B/ |! j
- }1 ~! O& u: @5 Q5 _
- }1 q0 p% D3 j/ O
- }
* V v: p) ~5 b - })
复制代码type 可以是下面原生构造器: - String
- Number
- Boolean
- Function
- Object
- Array
$ ?) {# L" m* m: l' Y
type 也可以是一个自定义构造器,使用 instanceof 检测。 自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件! 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即: - 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
' Y) s4 u* F; S/ x
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。 实例1 N* \' E' g' w6 J, L5 q+ D
- <div id="app">
+ I- d: d- w( W" } - <div id="counter-event-example">
, d: o4 j# v/ m: f; q" m9 a0 a - <p>{{ total }}</p>
7 h) B! `/ x+ p1 J# X1 f0 a% E - <button-counter v-on:increment="incrementTotal"></button-counter>
4 @5 E# a3 ~6 m8 y - <button-counter v-on:increment="incrementTotal"></button-counter>8 |, t5 e y$ A0 u
- </div>( v0 `# i$ w: m0 M8 k3 i% C8 A
- </div>
; b/ B! }9 j/ i& s( ] - - o# o; q& x% k1 W- ^
- <script>' i4 w3 _; G' b
- Vue.component('button-counter', {
& @( m0 D( f" ]/ [$ k - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',7 k5 r7 H* T4 ~3 c# U1 E
- data: function () {' T& _9 r- k9 ^5 u1 o$ y3 y2 O
- return {
; v5 m3 G2 Z* G1 y - counter: 0, N' t8 b0 F) x( }9 b& Z$ F
- }
& c& P0 m+ R3 G5 I- H0 Q - },8 r# G [* P/ Z1 J
- methods: {
1 H+ \9 H$ F; W8 s. B& ` - incrementHandler: function () {7 }- ~2 k) R+ Y3 s# P& Z
- this.counter += 1: u; D M/ [, @
- this.$emit('increment'); q8 F& H( K4 {8 O
- }4 i4 N1 W2 a) `9 p0 T. b. W
- },
5 S5 d# `+ P E2 b) @1 u - })9 r+ R. ?4 ? H5 C
- new Vue({
, u. C- H# X4 @2 v' y8 ^# k- p0 o - el: '#counter-event-example',
" H: _& q; D8 k) K - data: {2 M Z* S9 M ]' H" \, A
- total: 0 F5 b7 F$ t/ _7 c Q! H
- }," G0 ?0 b1 g3 `# m
- methods: {- h3 H7 F2 u+ a4 f7 w& c$ U$ S
- incrementTotal: function () {' k2 l# E/ e, n) `) ^
- this.total += 1+ k2 N/ ]: |" p, f, I7 R- H
- }
9 Q9 v* x: Y" X - }
7 R6 B2 L* T8 N0 `$ z - })- v$ P$ V5 L% r8 v- q7 y% Q
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如: - <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下: - // 注册- b" ^% l- w# O7 L- y$ Z
- Vue.component('child', {
0 D, f& M3 {* d1 O8 `2 ]% i0 ? - // 声明 props( U" ~1 V. \5 U3 ?
- props: ['message'],2 U$ _& _3 e# ?; B" b: t
- // 同样也可以在 vm 实例中像 "this.message" 这样使用$ i3 W* ]1 n; B1 `
- template: '<span>{{ message }}</span>'; ^$ F7 c& q6 z7 J0 l( J- P8 s- w
- })* x7 j& |! ?3 C; \
- // 创建根实例0 g; U. H; f$ W7 R' ^
- new Vue({
6 N& n5 q$ H- b - el: '#app',9 K8 H8 c7 F+ W' }3 P+ L; N; M5 Q
- data:{4 H6 F$ Y6 E# I* h
- message:"hello",
# G2 y M0 h# m* M - }
" x, w. x1 _% u | - })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。 比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。 - methods: {3 r0 i H3 e) O1 B+ L! I7 o5 \8 e
- incrementHandler: function (v) {
) }0 z7 L% w1 i! s- Q - if(v==1){
+ `" F! T6 Q2 [# o2 G; R4 ?' _ - this.counter -= 1* ]# j0 C6 U0 x/ B/ F5 M7 Y5 t
- this.$emit('increment',[1])0 q( W" U) u3 c3 X& |% L2 ~
- }else{
E" s; V4 {* A3 u, d$ }; g - this.counter += 19 X; f8 t( N' G+ `5 A
- this.$emit('increment',[2])
" p) q6 v8 E5 o* T: a - }* |( V+ Q1 d* H7 D1 N p2 u
- }: x5 X6 x8 ]/ E+ m* |
- }
复制代码
) N5 c% U4 T# X5 H: r0 J2 N6 j% H2 `1 C% i
|