可復(fù)用性的組件詳解
使用組件的原因
作用:提高代碼的復(fù)用性
組件的使用方法
- 全局注冊
<div id="app">
<my-componet></my-componet>
</div>
<!-- 對應(yīng)的內(nèi)容<div id="app"><div>我是一個(gè)全局組件</div></div> -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// Vue.component(tag, {
// template: '<div></div>'
// })
// 注冊組件 第一個(gè)參數(shù) 標(biāo)簽名 第二個(gè)是要渲染的魔板
Vue.component('my-componet', {
template: '<div>我是一個(gè)全局組件</div>'
})
var app = new Vue({
el: '#app',
data: {
}
})
</script>
- 優(yōu)點(diǎn):所有的
Vue
實(shí)例都可以用 - 缺點(diǎn):權(quán)限太大坪圾,容錯(cuò)率降低
- 局部注冊
<div id="app" style="border:2px solid red ">
<!-- 全局組件 -->
<my-componet></my-componet>
<!-- 局部組件 -->
<app-componet></app-componet>
</div>
<!-- 對照試驗(yàn) 全局組件和局部組件 -->
<div id="bpp" style="border:2px solid green;margin-top:5px; ">
<!-- 全局組件 -->
<my-componet></my-componet>
<!-- app局部組件 只能在所注冊的實(shí)例中使用 這里不會(huì)顯示 -->
<app-componet></app-componet>
</div>
<!-- 對應(yīng)的內(nèi)容<div id="app"><div>我是一個(gè)全局組件</div></div> -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// Vue.component(tag, {
// template: '<div></div>'
// })
// 注冊全局組件 第一個(gè)參數(shù) 標(biāo)簽名 第二個(gè)是要渲染的魔板
Vue.component('my-componet', {
template: '<div>我是一個(gè)全局組件</div>'
})
var app = new Vue({
el: '#app',
// 局部組件
components: {
'app-componet': {
template: '<div>我是app局部注冊的一個(gè)組件組件</div>'
}
},
data: {
}
})
var bpp = new Vue({
el: '#bpp',
data: {
}
})
</script>
- 注意
vue
組件的模板在某些情況下會(huì)受到html
標(biāo)簽的限制,比如<table>
中只能還
有<tr>
,<td>
這些元素异雁,所以直接在table
中使用組件是無效的,此時(shí)可以使用is
屬性來掛載組件
<table>
<tbody is="my-component"></tbody>
</table>
組件使用的小技巧
- 推薦使用小寫字母加-進(jìn)行命名(必須)
child,
my-componnet
命名組件
- 推薦使用小寫字母加-進(jìn)行命名(必須)
-
template
中的內(nèi)容必須被一個(gè)DOM元
素包括 框咙,也可以嵌套
-
- 在組件的定義中跟畅,除了
template
之外的其他選項(xiàng)—data
,computed
,methods
- 在組件的定義中跟畅,除了
-
data
必須是一個(gè)方法data:function(){}
小實(shí)踐:
-
<div id="app">
<!-- 推薦使用小寫字母加-進(jìn)行命名(必須) -->
<my-component></my-component>
<!-- 點(diǎn)擊任何一個(gè) 都會(huì)執(zhí)行 可用組件方式解決 -->
<button @click="plus">{{count}}</button>
<button @click="plus">{{count}}</button>
<hr><br>
<!-- 組件方式解決 及 data必須是一個(gè)方法實(shí)踐 兩次點(diǎn)擊的按鈕 對象是不一致的 -->
<btn-component></btn-component>
<btn-component></btn-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
count: 1
},
//組件
components: {
'my-component': {
// `template`中的內(nèi)容必須被一個(gè)`DOM元`素包括 ,也可以嵌套
template: '<div><span>組件小技巧</span></div>'
},
'btn-component': {
template: '<button @click="count++">{{count}}</button>',
// 組件中的data`必須是一個(gè)方法
data: function() {
return {
count: 0
}
}
}
},
methods: {
plus: function() {
return this.count++
}
}
})
</script>
使用props傳遞數(shù)據(jù) 父親向兒子傳遞數(shù)據(jù)
- 在組件中使用
props
來從父親組件接收參數(shù)堕扶,注意,在props
中定義的屬性梭依,都可以在組件中直接使用
2. propps來自父級稍算,而組件中data return的數(shù)據(jù)就是組件自己的數(shù)據(jù),兩種情況作用域就是組件本身役拴,可以在template糊探,computed,methods中直接使用
-
props
的值有兩種河闰,一種是字符串?dāng)?shù)組科平,一種是對象,本節(jié)先只講數(shù)組 - 可以使用
v--bind
動(dòng)態(tài)綁定父組件來的內(nèi)容
先看個(gè)小栗子:
在父組件里向子組件傳遞消息:
<div id="app" style="border:2px solid green;height:200px;">
<h5 style="text-align:center">我是父組件</h5>
<child-component msg="我是來自父組件的內(nèi)容"></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// 一個(gè)父組件
var app = new Vue({
el: '#app',
// 定義一個(gè)子組件
components: {
'child-component': {
// 在組件中使用props來從父親組件接收參數(shù)姜性,
props: ['msg'],
// 注意瞪慧,在props中定義的屬性,都可以在 組件中直接使用
template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
}
},
})
</script>
可以使用v--bind
動(dòng)態(tài)綁定父組件來的內(nèi)容:小栗子
在父組件里向子組件傳遞消息:
<div id="app" style="border:2px solid green;height:400px;">
<h5 style="text-align:center">我是父組件</h5>
<child-component msg="我是來自父組件的內(nèi)容"></child-component>
<br>
<hr>使用v-bind進(jìn)行數(shù)據(jù)動(dòng)態(tài)綁定 把input中的msg傳遞給子組件
<input type="text" v-model="parentmsg">
<bind-component :msg="parentmsg"></bind-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// 一個(gè)父組件
var app = new Vue({
el: '#app',
//父組件定義的內(nèi)容
data: {
parentmsg: '今晚的月亮真圓啊'
},
// 定義一個(gè)子組件
components: {
'child-component': {
// 在組件中使用props來從父親組件接收參數(shù)部念,
props: ['msg'],
// 注意弃酌,在props中定義的屬性,都可以在 組件中直接使用
template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
},
'bind-component': {
// 在組件中使用props來從父親組件接收參數(shù)印机,
props: ['msg'],
// 注意,在props中定義的屬性门驾,都可以在 組件中直接使用
template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
}
},
})
</script>
使用不使用v-bind
的區(qū)別 :
在父組件里向子組件傳遞消息:
<div id="app" style="border:2px solid green;height:400px;">
<h5 style="text-align:center">我是父組件</h5>
<child-component msg="我是來自父組件的內(nèi)容"></child-component>
<hr><br>
<!-- v-bing 對照試驗(yàn) 傳遞數(shù)組 -->
v-bind對照試驗(yàn) 傳遞數(shù)組
<!-- msg.length 是7 -->
<child-component msg="[3,6,7]"></child-component>
<!-- 使用v-bind可以識別為數(shù)組 msg.length 是3 -->
<child-component :msg="[3,6,7]"></child-component>
<br>
<hr>使用v-bind進(jìn)行數(shù)據(jù)動(dòng)態(tài)綁定 把input中的msg傳遞給子組件
<input type="text" v-model="parentmsg">
<bind-component :msg="parentmsg"></bind-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// 一個(gè)父組件
var app = new Vue({
el: '#app',
data: {
parentmsg: '今晚的月亮真圓啊'
},
// 定義一個(gè)子組件
components: {
'child-component': {
// 在組件中使用props來從父親組件接收參數(shù)射赛,
props: ['msg'],
// 注意,在props中定義的屬性奶是,都可以在 組件中直接使用
template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
},
'bind-component': {
// 在組件中使用props來從父親組件接收參數(shù)楣责,
props: ['msg'],
// 注意竣灌,在props中定義的屬性,都可以在 組件中直接使用
template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
}
},
})
</script>
單向數(shù)據(jù)流
解釋 : 通過 props
傳遞數(shù)據(jù) 是單向的了秆麸, 也就是父組件數(shù)據(jù)變化時(shí)會(huì)傳遞給子組
件初嘹,但是反過來不行。
目的 :是盡可能將父子組件解耦沮趣,避免子組件無意中修改了父組件的狀態(tài)屯烦。
應(yīng)用場景: 業(yè)務(wù)中會(huì)經(jīng)常遇到兩種需要改變 prop
的情況
一種是父組件傳遞初始值進(jìn)來,子組件將它作為初始值保存起來房铭,在自己的作用域
下可以隨意使用和修改驻龟。這種情況可以在組件data
內(nèi)再聲明一個(gè)數(shù)據(jù),引用父組件的prop
- 步驟一:注冊組件
- 步驟二:將父組件的數(shù)據(jù)傳遞進(jìn)來缸匪,并在子組件中用props接收
- 步驟三:將傳遞進(jìn)來的數(shù)據(jù)通過初始值保存起來
小栗子:
<div id="app" style="border:2px solid green;height:400px;">
<my-component msg="我是父組件傳遞的數(shù)據(jù)"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// 步驟一:注冊組件
Vue.component('my-component', {
// 步驟二: 將父組件的數(shù)據(jù)傳遞進(jìn)來翁狐, 并在子組件中用props接收
props: ['msg'],
template: ' <div>{{count}}</div>',
data: function() {
return {
// 步驟三: 將傳遞進(jìn)來的數(shù)據(jù)通過初始值保存起來
// <!-- props的值可以通過this.xxx 直接進(jìn)行獲取-->
count: this.msg
}
},
})
var app = new Vue({
el: '#app',
data: {
}
})
</script>
另一種情況就是
prop
作為需要被轉(zhuǎn)變的原始值傳入。這種情況用計(jì)算屬性就可以了
步驟一:注冊組件
步驟二:將父組件的數(shù)據(jù)傳遞進(jìn)來凌蔬,并在子組件中用props
接收
步驟三:將傳遞進(jìn)來的數(shù)據(jù)通過計(jì)算屬性進(jìn)行重新計(jì)算
小栗子:
<div id="app" style="border:2px solid green;height:400px;">
<my-component msg="我是父組件傳遞的數(shù)據(jù)"></my-component>
<hr> <br>
<!-- 需求 :通過input中輸入的數(shù)據(jù)動(dòng)態(tài)改變div的寬度 -->
<!-- 傳遞的數(shù)據(jù)僅僅是一個(gè)數(shù)據(jù) 需要計(jì)算屬性重新計(jì)算拼接 -->
<input type="text" v-model="width">
<width-component :width="width"></width-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// 場景一 步驟一:注冊組件
Vue.component('my-component', {
// 步驟二: 將父組件的數(shù)據(jù)傳遞進(jìn)來露懒, 并在子組件中用props接收
props: ['msg'],
template: ' <div>{{count}}</div>',
data: function() {
return {
// 步驟三: 將傳遞進(jìn)來的數(shù)據(jù)通過初始值保存起來
// <!-- props的值可以通過this.xxx 直接進(jìn)行獲取-->
count: this.msg
}
},
})
// 場景二 步驟一:注冊組件
Vue.component('width-component', {
// 步驟二: 將父組件的數(shù)據(jù)傳遞進(jìn)來, 并在子組件中用props接收
props: ['width'],
template: ' <div :style="style"></div>',
data: function() {
return {
}
},
computed: {
style: function() {
// return 出來的就是直接拼接好的style
return {
width: this.width + 'px',
background: 'red',
height: '300px'
}
}
}
})
var app = new Vue({
el: '#app',
data: {
width: 0
}
})
</script>
數(shù)據(jù)驗(yàn)證
vue
組件中camelCased
(駝峰式) 命名與kebab-case
(短橫線命名)
- 在
html
中,myMessage
和mymessage
是一致的,,因此在組件中的html
中使用必須使用kebab-case
(短橫線)命名方式砂心。在html
中不允許使用駝
峰P复省!<品 G账!躁倒! (謹(jǐn)記) - 在組件中, 父組件給子組件傳遞數(shù)據(jù)必須用短橫線荞怒。在
template
中,必
須使用駝峰命名方式秧秉,若為短橫線的命名方式褐桌。則會(huì)直接保錯(cuò)。 - 在組件的
data
中,用this.XXX
引用時(shí),只能是駝峰命名方式象迎。若為短橫線
的命名方式荧嵌,則會(huì)報(bào)錯(cuò)。
小栗子:
<div id="app" style="border:2px solid green;height:400px;">
<!-- 會(huì)報(bào)錯(cuò) Unknown custom element: myComponent 在組件中的`html`中使用必須使用`kebab-case`(短橫線)命名方式砾淌。在`html`中不允許使用駝峰@泊椤!-->
<myComponent myMsg='lalalalal'></myComponent>
<!-- 正確方式 在組件中, 父組件給子組件傳遞數(shù)據(jù)必須用短橫線汪厨。-->
<my-component my-msg='lalalalal'></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
Vue.component('myComponent', {
props: ['myMsg'],
// 在template中赃春, 必須使用駝峰命名方式, 若為短橫線的命名方式劫乱。 則會(huì)直接保錯(cuò)织中。
template: ' <div>{{abc}}</div>',
data: function() {
return {
// 在組件的data中,用this.XXX引用時(shí),只能是駝峰命名方式锥涕。若為短橫線的命名方式, 則會(huì)報(bào)錯(cuò)狭吼。
// abc: this.my - msg
// 正確的寫法
abc: this.myMsg
}
},
})
var app = new Vue({
el: '#app',
data: {
a: '100',
b: '666',
c: true
}
})
</script>
驗(yàn)證的 type 類型可以是:
? String
? Number
?Boolean
? Object
? Array
?Function
栗子:
<div id="app" style="border:2px solid green;height:400px;">
<input type="text" v-model='d'>
<br>
<type-component :a='a' :b='b' :c='c' :d='d' :e='e' :f='f' :g='g'></type-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
// 數(shù)組驗(yàn)證
Vue.component('typeComponent', {
// 約定值的類型
props: {
a: String,
b: [String, Number],
// 必須是布爾類型 默認(rèn)值是true typr required default
c: {
type: Boolean,
default: true
},
d: {
type: Number,
// 必選項(xiàng)為true 必須傳值進(jìn)行渲染
required: true
},
// 不向子組件傳遞 就會(huì)取默認(rèn)值 default
e: {
type: Array,
default: function() {
return ['666e', 333]
}
},
//自定義驗(yàn)證函數(shù)
f: {
validator: function(value) {
return value > 10
}
},
//驗(yàn)證選項(xiàng)必須為function
g: {
type: Function
}
},
template: ' <div>{{a}}-----{层坠} -----{{c}}----{eapyjqs} ------{{e[0]}}----{{f}} -----{{g}}</div>',
data: function() {
return {}
},
})
var app = new Vue({
el: '#app',
// 與上面的props中的選項(xiàng)對應(yīng)
data: {
a: '100a',
// String或者是Number
b: '666b',
// 默認(rèn)值為true
c: '',
// Missing required prop: "d"
d: 66622,
// 數(shù)組
e: [],
//自定義驗(yàn)證函數(shù) value > 10 就是 88 > 10 就會(huì)渲染
f: 88,
// 驗(yàn)證類型為function
g: console.log("我是一個(gè)函數(shù)")
}
})
</script>