vue組件的定義
● 組件(Component)是Vue.js最強(qiáng)大的功能之一
● 組件可以擴(kuò)展HTML元素,封裝可重用代碼
● 在較高層面上,組件是自定義元素,Vue.js的編譯器為他添加特殊功能
● 有些情況下,組件也可以表現(xiàn)用 is 特性進(jìn)行了擴(kuò)展的原生的HTML元素
● 所有的Vue組件同時(shí)也都是Vue實(shí)例,所以可以接受相同的選項(xiàng)對(duì)象(除了一些根級(jí)特有的選項(xiàng)),并提供相同的生命周期鉤子
vue組件的功能
1)能夠把頁(yè)面抽象成多個(gè)相對(duì)獨(dú)立的模塊
2)實(shí)現(xiàn)代碼重用,提高開(kāi)發(fā)效率和代碼質(zhì)量,使得代碼易于維護(hù)
Vue組件封裝過(guò)程
● 首先,使用Vue.extend()創(chuàng)建一個(gè)組件
● 然后,使用Vue.component()方法注冊(cè)組件
● 接著,如果子組件需要數(shù)據(jù),可以在props中接受定義
● 最后,子組件修改好數(shù)據(jù)之后,想把數(shù)據(jù)傳遞給父組件,可以使用emit()方法
組件使用流程詳細(xì)介紹
1、組件創(chuàng)建---有3中方法,extend()? ? ? <template id=''>? ? ? <script type='text/x-template'? id=''>
A、調(diào)用Vue.extend(),創(chuàng)建名為myCom的組件,template定義模板的標(biāo)簽,模板的內(nèi)容需寫(xiě)在該標(biāo)簽下
var myCom = Vue.extend({
? ? template: '<div>這是我的組件</div>'
})
B、<template id='myCom'>標(biāo)簽創(chuàng)建,需要加上id屬性
<template id="myCom">
? ? <div>這是template標(biāo)簽構(gòu)建的組件</div>
</template>
C、<script type='text/x-template' id='myCom'>,需加id屬性,同時(shí)還得加type="text/x-template",加這個(gè)是為了告訴瀏覽器不執(zhí)行編譯里面的代碼
<script type="text/x-template" id="myCom1">
? ? <div>這是script標(biāo)簽構(gòu)建的組件</div>
</script>
2、注冊(cè)組件----有2中方法,全局注冊(cè),局部注冊(cè)
A1、全局注冊(cè):一次注冊(cè)( 調(diào)用Vue.component( 組件名稱(chēng),為組件創(chuàng)建時(shí)定義的變量 ) ),可在多個(gè)Vue實(shí)例中使用。
我們先用全局注冊(cè),注冊(cè)上面例子中創(chuàng)建的myCom組件
Vue.component('my-com',myCom)
A2、全局注冊(cè)語(yǔ)法糖:不需要?jiǎng)?chuàng)建直接注冊(cè)的寫(xiě)法
Vue.component('my-com',{
? ? 'template':'<div>這是我的組件</div>'
})
'my-com'為給組件自定義的名字,在使用時(shí)會(huì)用到,后面myCom對(duì)應(yīng)的就是上面構(gòu)建的組件變量。
A3、如果是用template及script標(biāo)簽構(gòu)建的組件,第二個(gè)參數(shù)就改為它們標(biāo)簽上的id值
Vue.component('my-com',{
? ? template: '#myCom'
})
B1、局部注冊(cè):只能在注冊(cè)該組件的實(shí)例中使用,一處注冊(cè),一處使用
var app = new Vue({
? ? el: '#app',
? ? components: {
? ? ? ? 'my-com': myCom
? ? }
})
B2、局部注冊(cè)語(yǔ)法糖:
var app = new Vue({
? ? el: '#app',
? ? components: {
? ? ? ? 'my-com': {
? ? ? ? ? template: '<div>這是我的組件</div>'
? ? ? ? }
? ? }
})
B3、<template>及<script>創(chuàng)建的組件,局部注冊(cè)
var app = new Vue({
? ? el: '#app',
? ? components: {
? ? ? ? 'my-com': {
? ? ? ? ? template: '#myCom'
? ? ? ? }
? ? }
})
3、調(diào)用組件
只需要在調(diào)用組件的地方,寫(xiě)上組件名字的標(biāo)簽即可
<div>
? ? /*調(diào)用組件*/
? ? <my-com></my-com>
</div>
4、栗子
A、全局注冊(cè):新建一個(gè)html文件,引入vue.js,并且定義2個(gè)vue實(shí)例app1和app2
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>vue組件</title>
? ? <script src="vue.js"></script>
</head>
<body>
? ? <div id="app1">
? ? ? ? <my-com></my-com>
? ? </div>
? ? <div id="app2">
? ? ? ? <my-com></my-com>
? ? </div>
? ? <script>
? ? ? ? /*創(chuàng)建組件*/
? ? ? ? var myCom = Vue.extend({
? ? ? ? ? ? template: '<div>這是我的組件</div>'
? ? ? ? });
? ? ? ? /*全局注冊(cè)組件*/
? ? ? ? Vue.component('my-com',myCom);
? ? ? ? /*定義vue實(shí)例app1*/
? ? ? ? var app1 = new Vue({
? ? ? ? ? ? el: '#app1'
? ? ? ? });
? ? ? ? /*定義vue實(shí)例app2*/
? ? ? ? var app2 = new Vue({
? ? ? ? ? ? el: '#app2'
? ? ? ? });
? ? </script>
</body>
</html>
顯示效果:
可以看到,全局注冊(cè)的組件在實(shí)例app1和實(shí)例app2中都可以被調(diào)用。
B、局部注冊(cè):將創(chuàng)建的組件注冊(cè)到實(shí)例app1下
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>vue組件</title>
? ? <script src="vue.js"></script>
</head>
<body>
? ? <div id="app1">
? ? ? ? <my-com></my-com>
? ? </div>
? ? <div id="app2">
? ? ? ? <my-com></my-com>
? ? </div>
? ? <script>
? ? ? ? var myCom = Vue.extend({
? ? ? ? ? ? template: '<div>這是我的組件</div>'
? ? ? ? });
? ? ? ? // Vue.component('my-com',myCom);
? ? ? ? /*局部注冊(cè)組件*/
? ? ? ? var app1 = new Vue({
? ? ? ? ? ? el: '#app1',
? ? ? ? ? ? components:{
? ? ? ? ? ? ? ? 'my-com':myCom
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? var app2 = new Vue({
? ? ? ? ? ? el: '#app2'
? ? ? ? });
? ? </script>
</body>
</html>
可以看到只渲染了app1實(shí)例下的組件,app2實(shí)例雖然調(diào)用了該組件,但是因?yàn)檫@個(gè)組件沒(méi)有在其內(nèi)部注冊(cè),也沒(méi)有全局注冊(cè),所以報(bào)錯(cuò)說(shuō)找不到該組件。
C、template 和script標(biāo)簽創(chuàng)建組件
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>vue組件</title>
? ? <script src="vue.js"></script>
</head>
<body>
? ? <div id="app1">
? ? ? ? <my-com></my-com>
? ? ? ? <my-com1></my-com1>
? ? </div>
? ? <template id="myCom">
? ? ? ? <div>這是template標(biāo)簽構(gòu)建的組件</div>
? ? </template>
? ? <script type="text/x-template" id="myCom1">
? ? ? ? <div>這是script標(biāo)簽構(gòu)建的組件</div>
? ? </script>
? ? <script>
? ? ? ? Vue.component('my-com1',{ //全局注冊(cè)
? ? ? ? ? ? template: '#myCom1'
? ? ? ? });
? ? ? ? var app1 = new Vue({
? ? ? ? ? ? el: '#app1',
? ? ? ? ? ? components:{
? ? ? ? ? ? ? ? 'my-com':{
? ? ? ? ? ? ? ? ? ? template: '#myCom'? //局部注冊(cè)
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? </script>
</body>
</html>
顯示效果:
5、異步組件
vue作為一個(gè)輕量級(jí)前端框架,其核心就是組件化開(kāi)發(fā)。我們一般常用的是用腳手架vue-cli來(lái)進(jìn)行開(kāi)發(fā)和管理,一個(gè)個(gè)組件即為一個(gè)個(gè)vue頁(yè)面,這種叫單文件組件。我們?cè)谝媒M件之時(shí)只需將組件頁(yè)面引入,再注冊(cè)即可使用。
當(dāng)項(xiàng)目比較大型,結(jié)構(gòu)比較復(fù)雜時(shí),我們一般選用vue-cli腳手架去構(gòu)建項(xiàng)目。因?yàn)関ue-cli集成了webpack環(huán)境,使用單文件組件,開(kāi)發(fā)更簡(jiǎn)單,易上手,尤其是在對(duì)組件的處理上。對(duì)于原生vue.js,我們就得將組件構(gòu)建在同一個(gè)html的script標(biāo)簽下或者h(yuǎn)tml的外部js中,所有組件集中在一塊,不容易管理,這也是原生vue,js的一點(diǎn)不便之處
vue.js可以將異步組件定義為一個(gè)工廠函數(shù)。
使用$.get獲取本地文件會(huì)跨域,所以要將項(xiàng)目部署到服務(wù)器中
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>vue組件</title>
? ? <script src="vue.js"></script>
? ? <script type="text/javascript" src='jquery-3.1.1.min.js'></script>
</head>
<body>
? ? <div id="app1">
? ? ? ? <head-com></head-com>
? ? </div>
? ? <script>
? ? ? ? Vue.component('head-com', function (resolve, reject) {
? ? ? ? ? ? $.get("a.html").then(function (res) {
? ? ? ? ? ? ? ? resolve({
? ? ? ? ? ? ? ? ? ? template: res
? ? ? ? ? ? ? ? })
? ? ? ? ? ? });
? ? ? ? });
? ? ? ? var app1 = new Vue({
? ? ? ? ? ? el: '#app1'
? ? ? ? });
? ? </script>
</body>
</html>
顯示效果如下:
6、Vue中的props數(shù)據(jù)流
通過(guò)在注冊(cè)組件中申明需要使用的props,然后通過(guò)props中與模板中傳入的對(duì)應(yīng)的屬性名,去取用這些值
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>vue組件</title>
? ? <script src="vue.js"></script>
? ? <script type="text/javascript" src='jquery-3.1.1.min.js'></script>
</head>
<body>
? ? <div id='app'>
? ? ? <my-component name="jiangjiang" come-from="guilin"></my-component>
? ? ? <!-- 然后在模板中通過(guò)屬性傳值的方式進(jìn)行數(shù)據(jù)的注入 -->
? ? </div>
? ? <script>
? ? ? ? Vue.component('my-component', {
? ? ? ? ? props: ['name', 'comeFrom'],? ? //在注冊(cè)組件的時(shí)候通過(guò)props選項(xiàng)聲明了要取用的多個(gè)prop
? ? ? ? ? // 在注冊(cè)組件的模板中使用到props選項(xiàng)中聲明的值
? ? ? ? ? template: '<p>我叫:{{name}}, 我來(lái)自:{{comeFrom}}</p>',
? ? ? ? ? created: function () {
? ? ? ? ? ? console.log('在created鉤子函數(shù)中被調(diào)用')
? ? ? ? ? ? console.log('我叫:', this.name)
? ? ? ? ? ? console.log('我來(lái)自:', this.comeFrom)
? ? ? ? ? }
? ? ? ? })
? ? ? ? new Vue({
? ? ? ? ? el: '#app'
? ? ? ? })
? ? </script>
</body>
</html>
注意:
A、props取值的方式
在注冊(cè)組件的模板內(nèi)部template,直接通過(guò)prop的名稱(chēng)取值就Ok
template: '<p>我叫:{{name}}, 我來(lái)自:{{comeFrom}}</p>'
不在注冊(cè)組件的模板內(nèi)部template,用this.prop的方式
console.log('我來(lái)自:', this.comeFrom)
B、在template選項(xiàng)屬性中,可以寫(xiě)駝峰命名法,也可以寫(xiě)短橫線命名法
? ? ? 在HTML(模板)中,只能寫(xiě)短橫線命名法
原因:vue組件的模板可以放在兩個(gè)地方
a、Vue組件的template選項(xiàng)屬性中,作為模板字符串
b、放在.html中[? 用script? template標(biāo)簽創(chuàng)建的組件 ],作為HTML
問(wèn)題在于HTML不區(qū)分大小寫(xiě),所以在vue注冊(cè)組件中通用的駝峰命名法,不適用于HTML中的Vue模板,在HTML中寫(xiě)入props屬性,必須寫(xiě)短橫線命名法(把原來(lái)props屬性中的每個(gè)prop大寫(xiě)換成小寫(xiě),并且在前面加“-”)
將6中的
? ? <div id='app'>
? ? ? <my-component name="jiangjiang" come-from="guilin"></my-component>
? ? ? <!-- 然后在模板中通過(guò)屬性傳值的方式進(jìn)行數(shù)據(jù)的注入 -->
? ? </div>
改成
? ? <div id='app'>
? ? ? <my-component name="jiangjiang" comeFrom="guilin"></my-component>
? ? ? <!-- 然后在模板中通過(guò)屬性傳值的方式進(jìn)行數(shù)據(jù)的注入 -->
? ? </div>
顯示效果,第二個(gè)沒(méi)有顯示
異步組件的實(shí)現(xiàn)原理;異步組件的3種實(shí)現(xiàn)方式---工廠函數(shù)、Promise、高級(jí)函數(shù)
異步組件實(shí)現(xiàn)的本質(zhì)是2次渲染,先渲染成注釋節(jié)點(diǎn),當(dāng)組件加載成功后,在通過(guò)forceRender重新渲染
高級(jí)異步組件可以通過(guò)簡(jiǎn)單的配置實(shí)現(xiàn)loading? resolve? reject? timeout? 4種狀態(tài)