cncml手绘网
标题: Vue.js 组件 [打印本页]
作者: admin 时间: 2018-7-4 11:28
标题: Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
- Vue.component(tagName, options)
复制代码tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
全局组件所有实例都能用全局组件。
全局组件实例注册一个简单的全局组件 runoob,并使用它:
4 c* N, |2 D Q' D
- <div id="app">: ^7 O: C% l9 W$ R( \
- <runoob></runoob>
& Q! j& `# H3 q3 P - </div>. ?, u7 F# \- ^. v; B
- ' ]) p; y6 y% |( R! }
- <script>
% O1 z" g6 P' F4 _ - // 注册
; E- Q( d& T( B$ B - Vue.component('runoob', {
1 W" X' N4 Z, r8 f - template: '<h1>自定义组件!</h1>'% y" `' K- H' W8 k
- })( w; X+ u1 I, z, N
- // 创建根实例
+ A2 \/ P% x" v `4 ] - new Vue({8 m3 ?- Y$ \) ~! D' p5 g+ t+ ^# S
- el: '#app'
/ x" g5 B0 E3 d" s4 V - })
# Q, b( C1 y. t& A! j - </script>
复制代码 局部组件我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例注册一个简单的局部组件 runoob,并使用它:
0 J7 M+ v# a+ z- A+ p" D& e- <div id="app">
* [8 [1 B2 G# c - <runoob></runoob># q$ p4 \6 n4 `7 T9 H
- </div>
$ x9 |; X( U, c0 O - + `1 d- N$ L+ I q, G
- <script>2 U( F( W: |8 R& ]2 r; S6 k
- var Child = {& {. g8 A {5 h! y: S, e% s
- template: '<h1>自定义组件!</h1>'
/ M F1 i. U2 o B0 w% B - }" `- j" \1 e6 E& E% H
-
|1 L9 p U- g - // 创建根实例
3 Q1 s! q0 n" n$ r' P - new Vue({
, h# ~) A* ~1 }6 S t% Q - el: '#app',
2 h+ B# V3 ~( V- ~% T - components: {$ U, F6 Z+ v' ^9 P; q
- // <runoob> 将只在父模板可用7 d0 u F: U1 a( [7 ^# E8 _
- 'runoob': Child7 @( B$ z- O: f
- }
$ Z% P( Y9 Y8 I - })
+ L3 R. j8 o: U2 j4 K6 L - </script>
复制代码 Propprop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Prop 实例
4 m" m- C+ ?9 Z6 S! M0 S- <div id="app">" h2 q3 z# m! b
- <child message="hello!"></child>
; h: E7 s8 q* c" y8 ^; @ - </div>
3 H3 t. g5 o0 K4 Y2 L$ Y! z -
+ p' J5 T* ~# S$ Q - <script>
0 n2 Z) O& W$ x" M3 i - // 注册3 ~! z9 Q: Z7 |0 M8 F) |
- Vue.component('child', {! M; Z# p% g& m& Y
- // 声明 props3 \) }$ M/ {8 p* N2 I" L
- props: ['message'],
$ t9 C+ g2 {7 z/ S. y3 p) q1 h - // 同样也可以在 vm 实例中像 "this.message" 这样使用) u/ I2 }. Y1 a* ]9 L; d/ v
- template: '<span>{{ message }}</span>'9 l# o9 b9 p( v8 K9 L
- })* w! b+ r+ P/ {& p" R2 W( a
- // 创建根实例
/ E/ w* r$ n! }* i4 t4 _ - new Vue({) Q6 M/ k8 ^0 f2 @
- el: '#app'
% ] m, W" ]; b. c& I - })
8 C( ~/ c J( j. S+ j. q0 c - </script>
复制代码 动态 Prop类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop 实例
( A6 i+ I6 c% M. `9 u3 } `- <div id="app">" e: w& y+ D3 p; N7 f5 s
- <div>/ l! F# [) C( T* `# n+ {
- <input v-model="parentMsg">
3 ^- `, Q; v$ j4 r8 U - <br>
) x, T7 J8 N Z( { t% k - <child v-bind:message="parentMsg"></child>
* `" V9 b) g' t' C3 o - </div>3 P& k/ {4 j2 O, ]$ l. ? b
- </div>; B! d. x' T7 }3 ?
- ) j$ i0 y$ R) ]/ c: p1 A' S
- <script>
1 L1 |' s: k3 O1 Y) {. @ - // 注册& Q; b6 T; T, J! y
- Vue.component('child', {
. G% Z6 e V ?5 N! y$ h, H% Y - // 声明 props
) t u4 C3 o. V - props: ['message'],) B% O6 j& t0 N/ ^
- // 同样也可以在 vm 实例中像 "this.message" 这样使用
" ?2 W+ [* g0 N u2 f6 P8 M - template: '<span>{{ message }}</span>'
" _' C( \5 z4 t. b6 | - })% Q9 d& A0 j6 {! m1 W
- // 创建根实例8 Q, ^! f6 C' D# X `
- new Vue({
# y+ j! m- v6 {( K+ Q2 | - el: '#app',7 A5 t0 w/ e! V, T$ `# V
- data: {
F2 S \& [4 c$ K! J - parentMsg: '父组件内容'4 s( F" i% m# G, R
- }
' p$ J' C7 Z& l - })! @' c' t- w4 n! o h1 a
- </script>
复制代码以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
Prop 实例* Z6 J/ M3 r7 Z) o5 c
- <div id="app">( v0 M8 c7 l4 v: V* w
- <ol>
' q; O6 j: x. K# X3 f - <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
' ]4 i( F# k/ T4 ^4 c; F: D9 E - </ol>
_$ P% ^! ~' d6 \& K# K - </div> s. \" H: q6 _" x2 \4 X
- - F! P h: Z6 r4 C* \# ]
- <script>
1 {0 V0 `7 d3 m* Y t - Vue.component('todo-item', {& e$ n% s4 N! X T6 B
- props: ['todo'],* B- t! ?- c, _# g P
- template: '<li>{{ todo.text }}</li>'
`: a' w* z. l# j$ p( i - })
, K* i( R% T( H, Y% P1 n - new Vue({
e, B9 F4 F( k% h9 } - el: '#app',6 z! O7 I6 R ~0 M! d: C* f4 ~/ n
- data: {; Q! m# u2 j8 [2 F8 X6 w" e5 ?
- sites: [* `, Q2 i' l; q# W" {; w
- { text: 'Runoob' },! w7 b& v: R* e
- { text: 'Google' },
; l' K# P6 H9 P& w& r1 l# M. O - { text: 'Taobao' }
8 p. g, j! y( G% l/ A6 P - ]
F0 q0 {; J( \3 a& x- O' C# K - }- D _- O) u1 N& ]8 z" Q
- })2 I& }2 O3 b' | R% I; ^/ I
- </script>
复制代码注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证组件可以为 props 指定验证要求。
prop 是一个对象而不是字符串数组时,它包含验证要求:
- Vue.component('example', {
$ v3 ]; ]; _% s/ I% H - props: {. \ B. c2 |, i0 T- X! h
- // 基础类型检测 (`null` 意思是任何类型都可以) Z2 [' ` y6 S# x/ v
- propA: Number,7 j2 \+ Z4 b) F& K& {
- // 多种类型% M& |& @( o9 { Y* j
- propB: [String, Number],& h% r! o( Q2 d- ]" ~
- // 必传且是字符串! S6 ~, m; l7 W8 Q; _# L$ _9 w9 d
- propC: {- L- b$ Q) l8 |
- type: String,
8 R/ H" Z6 D1 }8 y8 \- n - required: true5 c, E8 c% g# g/ f3 y
- },
" l* o$ k* N4 F3 Z d" K - // 数字,有默认值+ i! X: P7 m' g6 n
- propD: {
5 J& P" \4 `+ ]5 I" ~3 y - type: Number,
! w: ` \# E+ p" d$ \ - default: 1003 t% ^3 T5 ~( Z! s; B/ t
- },
- x- [( U% a8 u# U - // 数组/对象的默认值应当由一个工厂函数返回1 d% ]; ]9 [( q* Q/ `5 S& |1 }' _
- propE: {
7 f! c0 Y0 I; e }6 \) r) b - type: Object,
' ^3 [/ c" K" I8 l - default: function () {* q, r: P9 O+ B$ a& {) e$ T
- return { message: 'hello' }5 t* M$ W3 E' b [. v- r Z
- }$ U- i8 f& k! m
- },, |0 w: O$ Q4 W& k% F
- // 自定义验证函数
7 o; f( w4 G/ ?% \+ r7 `8 Z - propF: {
# ?2 N$ s4 V. X$ M1 d* q8 y- V - validator: function (value) {: \' Q8 o* M, l5 W, ]( q; e. S/ R W
- return value > 10% V5 A/ h! E" L
- }
. l& f' m" `7 G# g4 ~ - }
8 ?1 E% o, [5 d3 i - }" `; n. s& f0 U6 e
- })
复制代码type 可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
5 i: G1 {) ?* s& d; h: o
type 也可以是一个自定义构造器,使用 instanceof 检测。
自定义事件父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件1 t4 N' t# }) U$ k
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
实例, e3 y6 {# J% `, _; l
- <div id="app">: c7 m# p$ M) S9 b0 ?9 n& c. R
- <div id="counter-event-example">
. S: Y0 g! A( u3 B! s% z3 j - <p>{{ total }}</p>1 i* K( V* _# z+ W
- <button-counter v-on:increment="incrementTotal"></button-counter>3 D/ l/ P$ p, }" r. u4 ]
- <button-counter v-on:increment="incrementTotal"></button-counter>
i2 E% U( c! B - </div>, x1 g/ ], I; w) {4 C: q& L
- </div>
0 e7 X. Q5 N" g1 J8 L; ] - ( v. g' U: ^2 h( G t
- <script>: W: o: Q- Y2 p* F9 D/ _: s0 @
- Vue.component('button-counter', {
8 n9 }/ c6 Z8 s3 ^ - template: '<button v-on:click="incrementHandler">{{ counter }}</button>',6 z) P$ i* ~" I2 W; G
- data: function () {
. m( z }1 @9 a - return {0 |7 [1 Y7 L e/ J
- counter: 0
/ a- k/ B9 K1 ]* H5 k - }
' Z' B9 S r2 P5 Q' D$ J$ \, u - },2 X9 k6 r% j g) M
- methods: {
: Y% X1 ~+ }: j+ [5 } - incrementHandler: function () {
- R( i" T4 |9 {6 A - this.counter += 1
: Y! O6 T: \% u- F/ I - this.$emit('increment'). ]9 l" F. K" n3 x
- }; ~" l; I5 L/ x+ `: e7 B* M, N
- },
' K; p; p) A j3 D8 |$ \$ a3 _ - })3 e9 d! ^3 @: w2 {
- new Vue({
' e3 r: d) G: `: G# Q+ Z E6 w - el: '#counter-event-example',- B4 k% c: D2 q( w
- data: {! K& }* x4 B. q/ K
- total: 0
' h- O3 G) M& w# Z6 p - },
: o; E. y" X- c) T/ C4 `& n - methods: {
0 O5 j* j4 ~. z( d - incrementTotal: function () {
$ p) a% U5 w8 p; q - this.total += 1. c2 y2 _) X' H: Q
- }
4 B$ n7 @: E" f/ k6 | - }
4 y! A; \; X1 G% H% X& ] - })) a& i- Y0 k& M+ \
- </script>
复制代码如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
- <my-component v-on:click.native="doTheThing"></my-component>
复制代码父组件给子组件传值的时候,如果想传入一个变量,写法如下:
- // 注册$ W% F1 B' e# O* C
- Vue.component('child', {
* ]) y2 }. ]0 P - // 声明 props
% I8 T6 k) J7 z1 n0 U% k - props: ['message'],% P4 n, s0 N3 k* y. @8 V
- // 同样也可以在 vm 实例中像 "this.message" 这样使用0 V: ?+ k6 {, z* V& c4 q4 H
- template: '<span>{{ message }}</span>'% Q" `+ W) U/ K; X3 K
- })
$ p1 M2 ^( v& r - // 创建根实例
1 o6 Q t/ y$ ~3 q2 d$ F- p - new Vue({" E! y# [+ _$ I; f3 D3 l
- el: '#app',/ Y6 F- r5 n/ E/ |, j
- data:{
& @$ b4 k0 D) t3 U - message:"hello",
! r5 W* @3 P) \2 `* ~* Y3 ` - }8 }1 G5 l( R6 v* C8 c' q' ]) n
- })
复制代码子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加参数数组。
比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。
- methods: {
5 z+ h! W3 @' m+ X - incrementHandler: function (v) {
+ A6 C! I+ I+ m4 K) [ - if(v==1){
& x5 Z. Y( c9 Q: ]1 y; ] - this.counter -= 1' E3 p! [: m- O( {0 _
- this.$emit('increment',[1])
8 n- Y( q" n( u0 g - }else{+ e+ @/ f2 L% U0 w; P
- this.counter += 1
5 A& |' C8 u8 Z0 | - this.$emit('increment',[2])
& _" k5 R8 c$ X4 k - }
; r4 P X7 s+ m3 }' S) ` - }
$ K5 {4 d4 l: }7 ]8 U1 t R. O* Q8 _ - }
复制代码
|0 f+ W5 K4 q5 X5 w; i& O
I @0 m" z/ g0 E, a8 Z" a' ?1 R( w
欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |