Vue.js 2.x之組件的定義和注冊(cè)圖文詳解
前言
什么是組件
組件: 組件的出現(xiàn),就是為了拆分Vue實(shí)例的代碼量的,能夠讓我們以不同的組件,來劃分不同的功能模塊,將來我們需要什么樣的功能,就可以去調(diào)用對(duì)應(yīng)的組件即可。
模塊化和組件化的區(qū)別
- 模塊化:是從代碼邏輯的角度進(jìn)行劃分的;方便代碼分層開發(fā),保證每個(gè)功能模塊的職能單一
- 組件化:是從UI界面的角度進(jìn)行劃分的;前端的組件化,方便UI組件的重用
全局組件的定義和注冊(cè)
組件Component是 Vue.js 最強(qiáng)大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼。
全局組件的定義和注冊(cè)有三種方式,我們接下來講一講。
寫法一
寫法一:使用Vue.extend方法定義組件,使用 Vue.component方法注冊(cè)組件。
代碼舉例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <div id="app"> <!-- 如果要使用組件,直接把組件的名稱,以 HTML 標(biāo)簽的形式,引入到頁(yè)面中,即可 --> <account> </account> </div> <script> //第一步:使用 Vue.extend 定義組件 var myAccount = Vue.extend({ template: '<div><h2>登錄頁(yè)面</h2> <h3>注冊(cè)頁(yè)面</h3></div>' // 通過 template 屬性,指定了組件要展示的HTML結(jié)構(gòu)。template 是 Vue 中的關(guān)鍵字,不能改。 }); //第二步:使用 Vue.component 注冊(cè)組件 // Vue.component('組件的名稱', 創(chuàng)建出來的組件模板對(duì)象) Vue.component('account', myAccount); //第一個(gè)參數(shù)是組件的名稱(標(biāo)簽名),第二個(gè)參數(shù)是模板對(duì)象 new Vue({ el: '#app' }); </script> </body> </html>
上方代碼中,在注冊(cè)組件時(shí),第一個(gè)參數(shù)是標(biāo)簽名,第二個(gè)參數(shù)是組件的定義。
運(yùn)行結(jié)果如下:
代碼截圖如下:
上圖中,注意兩點(diǎn):
注意1、紅框部分,要保證二者的名字是一致的。如果在注冊(cè)時(shí),組件的名稱是駝峰命名,比如:
Vue.component('myComponent', myAccount);
//第一個(gè)參數(shù)是組件的名稱(標(biāo)簽名),第二個(gè)參數(shù)是模板對(duì)象
那么,在標(biāo)簽中使用組件時(shí),需要把大寫的駝峰改為小寫的字母,同時(shí)兩個(gè)單詞之間使用-進(jìn)行連接:
<my-component> </my-component> Vue.component('my')
注意2、綠框部分,一定要用一個(gè)大的根元素(例如<div>)包裹起來。如果我寫成下面這樣,就沒有預(yù)期的效果:
template: '<h2>登錄頁(yè)面</h2> <h3>注冊(cè)頁(yè)面</h3>'
結(jié)果如下:(并非預(yù)期的效果)
寫法二
寫法二:Vue.component方法定義、注冊(cè)組件(一步到位)。
代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <div id="app"> <account> </account> </div> <script> //定義、注冊(cè)組件:第一個(gè)參數(shù)是組件的名稱(標(biāo)簽名),第二個(gè)參數(shù)是組件的定義 Vue.component('account', { template: '<div><h2>登錄頁(yè)面</h2> <h3>注冊(cè)頁(yè)面</h3></div>' // template 是 Vue 中的關(guān)鍵字,不能改。 }); new Vue({ el: '#app' }); </script> </body> </html>
代碼截圖如下:
上圖中,同樣注意兩點(diǎn):
1、紅框部分,要保證二者的名字是一致的。
2、綠框部分,一定要用一個(gè)大的根元素(例如<div>)包裹起來。如果我寫成下面這樣,就沒有預(yù)期的效果:
template: '<h2>登錄頁(yè)面</h2> <h3>注冊(cè)頁(yè)面</h3>'
結(jié)果如下:(并非預(yù)期的效果)
寫法三
上面的寫法一、寫法二并不是很智能,因?yàn)樵诙x模板的時(shí)候,沒有智能提示和高亮,容易出錯(cuò)。我們不妨來看看寫法三。
寫法三:將組件內(nèi)容定義到template標(biāo)簽中去。
代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <!-- 定義模板 --> <template id="myAccount"> <div> <h2>登錄頁(yè)面</h2> <h3>注冊(cè)頁(yè)面</h3> </div> </template> <div id="app"> <!-- 使用組件 --> <account> </account> </div> <script> //定義、注冊(cè)組件 Vue.component('account', { template: '#myAccount' // template 是 Vue 中的關(guān)鍵字,不能改。 }); new Vue({ el: '#app' }); </script> </body> </html>
代碼截圖如下:
寫法三其實(shí)和方法二差不多,無(wú)非是把綠框部分的內(nèi)容,單獨(dú)放在了<template>標(biāo)簽中而已,這樣有利于 html 標(biāo)簽的書寫。
使用components定義私有組件
我們?cè)谏弦欢沃卸x的是全局組件,這樣做的時(shí)候,多個(gè)Vue實(shí)例都可以使用這個(gè)組件。
我們可以在一個(gè)Vue實(shí)例的內(nèi)部定義私有組件,這樣做的時(shí)候,只有當(dāng)前這個(gè)Vue實(shí)例才可以使用這個(gè)組件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <div id="app"> <!-- 使用Vue實(shí)例內(nèi)部的私有組件 --> <my-login></my-login> </div> <script> new Vue({ el: '#app', data: {}, components: { // 定義、注冊(cè)Vue實(shí)例內(nèi)部的私有組件 myLogin: { template: '<h3>這是私有的login組件</h3>' } } }); </script> </body> </html>
運(yùn)行效果:
當(dāng)然,我們還可以把模板的定義存放在<template>標(biāo)簽中,這樣的話,模板里的html標(biāo)簽就可以出現(xiàn)智能提示和高亮,避免出錯(cuò)。如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <!-- 定義模板 --> <template id="loginTmp"> <h3>這是私有的login組件</h3> </template> <div id="app"> <!-- 調(diào)用Vue實(shí)例內(nèi)部的私有組件 --> <my-login></my-login> </div> <script> new Vue({ el: '#app', data: {}, components: { // 定義、注冊(cè)Vue實(shí)例內(nèi)部的私有組件 myLogin: { template: '#loginTmp' } } }); </script> </body> </html>
運(yùn)行效果不變。
為組件添加 data 和 methods
既然組件是一個(gè)頁(yè)面,那么,頁(yè)面中可能會(huì)有一些功能要?jiǎng)討B(tài)展示。因此,我們有必要為組件添加 data 和 methods。
代碼舉例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <!-- 定義組件的模板 --> <template id="myAccount"> <div> <!-- 在組件的模板中,調(diào)用本組件中的data --> {{myData}} <a href="#" rel="external nofollow" v-on:click="login">登錄1</a> <h2>登錄頁(yè)面</h2> <h3>注冊(cè)頁(yè)面</h3> </div> </template> <div id="app"> <!-- 第一次調(diào)用組件 --> <account> </account> <!-- 第二次調(diào)用組件 --> <account> </account> </div> <script> //定義、注冊(cè)組件 Vue.component('account', { template: '#myAccount', //組件中的 data //【注意】組件中的data,不再是對(duì)象,而是一個(gè)方法(否則報(bào)錯(cuò));而且這個(gè)方法內(nèi)部,還必須返回一個(gè)對(duì)象才行 // 組件中 的data 數(shù)據(jù),使用方式,和實(shí)例中的 data 使用方式完全一樣!!! data: function () { return { myData: 'smyhvae' } }, //組件中的 method methods: { login: function () { alert('login操作'); } } }); new Vue({ el: '#app' }); </script> </body> </html>
上方代碼所示,我們?cè)赼ccount組件中添加的data 和 methods,其作用域只限于account組件里,保證獨(dú)立性。
注意,在為組件添加數(shù)據(jù)時(shí),data不再是對(duì)象了,而是function,而且要通過 return的形式進(jìn)行返回;否則,頁(yè)面上是無(wú)法看到效果的。通過 function返回對(duì)象的形式來定義data,作用是:
上方代碼中,組件<account>
被調(diào)用了兩次(不像根組件那樣只能調(diào)用一次),但是每個(gè)組件里的數(shù)據(jù) myData是各自獨(dú)立的,不產(chǎn)生沖突。
換而言之,通過函數(shù)返回對(duì)象的目的,是為了讓每個(gè)組件都有自己獨(dú)立的數(shù)據(jù)存儲(chǔ),而不應(yīng)該共享一套數(shù)據(jù)。
為什么組件的data必須是一個(gè)function
我們先來看下面這樣的例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <div id="app"> <!-- 第一次調(diào)用組件 --> <counter></counter> <hr> <!-- 第二次調(diào)用組件 --> <counter></counter> </div> <!-- 定義模板 --> <template id="tmpl"> <div> <input type="button" value="讓count加1" @click="increment"> <h3>{{count}}</h3> </div> </template> <script> var dataObj = { count: 0 } // 這是一個(gè)計(jì)數(shù)器的組件, 身上有個(gè)按鈕,每當(dāng)點(diǎn)擊按鈕,讓 data 中的 count 值 +1 Vue.component('counter', { template: '#tmpl', data: function () { return dataObj //當(dāng)我們r(jià)eturn全局的dataObj的時(shí)候,子組件們會(huì)共享這個(gè)dataObj }, methods: { increment() { this.count++ } } }) // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {} }); </script> </body> </html>
運(yùn)行效果如下:
上面的例子中,將組件<counter>調(diào)用了兩次,由于dataObj是全局對(duì)象,導(dǎo)致兩個(gè)組件實(shí)例都可以共享這個(gè)dataObj數(shù)據(jù)。于是,我們點(diǎn)擊任何一個(gè)組件實(shí)例的按鈕,都可以讓count數(shù)據(jù)加1。
現(xiàn)在問題來了,如果我們想讓組件<counter>的兩個(gè)實(shí)例去單獨(dú)操作count數(shù)據(jù),應(yīng)該怎么做呢?我們應(yīng)該修改 data中 return出去的內(nèi)容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <div id="app"> <counter></counter> <hr> <counter></counter> <hr> <counter></counter> </div> <template id="tmpl"> <div> <input type="button" value="讓count加1" @click="increment"> <h3>{{count}}</h3> </div> </template> <script> var dataObj = { count: 0 } // 這是一個(gè)計(jì)數(shù)器的組件, 身上有個(gè)按鈕,每當(dāng)點(diǎn)擊按鈕,讓 data 中的 count 值 +1 Vue.component('counter', { template: '#tmpl', data: function () { // return dataObj //當(dāng)我們r(jià)eturn全局的dataObj的時(shí)候,這個(gè)dataObj是共享的 return { count: 0 } // 【重要】return一個(gè)**新開辟**的對(duì)象數(shù)據(jù) }, methods: { increment() { this.count++ } } }) // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {} }); </script> </body> </html>
運(yùn)行效果:
如上圖所示,每當(dāng)我們創(chuàng)建一個(gè)新的組件實(shí)例時(shí),就會(huì)調(diào)用data函數(shù),data函數(shù)里會(huì)return一個(gè)新開辟的對(duì)象數(shù)據(jù)。這樣做,就可以保證每個(gè)組件實(shí)例有獨(dú)立的數(shù)據(jù)存儲(chǔ)。
組件的切換
使用v-if和v-else結(jié)合flag進(jìn)行切換
代碼舉例:(登錄組件/注冊(cè)組件,二選一)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <div id="app"> <!-- 溫馨提示:`.prevent`可以阻止超鏈接的默認(rèn)事件 --> <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" flag=true">登錄</a> <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" flag=false">注冊(cè)</a> <!-- 登錄組件/注冊(cè)組件,同時(shí)只顯示一個(gè) --> <login v-if="flag"></login> <register v-else="flag"></register> </div> <script> Vue.component('login', { template: '<h3>登錄組件</h3>' }) Vue.component('register', { template: '<h3>注冊(cè)組件</h3>' }) // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel var vm = new Vue({ el: '#app', data: { flag: false }, methods: {} }); </script> </body> </html>
運(yùn)行效果如下:
使用Vue提供的<component>標(biāo)簽實(shí)現(xiàn)組件切換
上面的例子中,我們是通過flag的值來進(jìn)行組件的切換。但是,flag的值只可能有兩種情況,也就是說,v-if和v-else只能進(jìn)行兩個(gè)組件之間的切換。
那如何實(shí)現(xiàn)三個(gè)甚至三個(gè)以上的組件切換呢?這里,我們可以用到Vue提供的<component>標(biāo)簽。
我們先來看一下<component>標(biāo)簽的用法。
基于上面的代碼,如果我想讓login組件顯示出來,借助<component>標(biāo)簽可以這樣做:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="Vue2.5.16.js"></script> </head> <body> <div id="app"> <!-- Vue提供了 component ,來展示對(duì)應(yīng)名稱的組件 --> <!-- 【重要】component 是一個(gè)占位符, `:is` 屬性,可以用來指定要展示的組件名稱。這里,我們讓 login 組件顯示出來 --> <component :is="'login'"></component> </div> <script> // 組件名稱是 字符串 Vue.component('login', { template: '<h3>登錄組件</h3>' }) Vue.component('register', { template: '<h3>注冊(cè)組件</h3>' }) // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel var vm = new Vue({ el: '#app', data: { comName: 'login' // 當(dāng)前 component 中的 :is 綁定的組件的名稱 }, methods: {} }); </script> </body> </html>
上方代碼中,提取關(guān)鍵代碼如下:
<component :is="'login'"></component>
如果我想讓register組件顯示出來,借助<component>標(biāo)簽可以這樣做:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="Vue2.5.16.js"></script> </head> <body> <div id="app"> <!-- Vue提供了 component ,來展示對(duì)應(yīng)名稱的組件 --> <!-- 【重要】component 是一個(gè)占位符, `:is` 屬性,可以用來指定要展示的組件名稱 --> <component :is="'register'"></component> </div> <script> // 組件名稱是 字符串 Vue.component('login', { template: '<h3>登錄組件</h3>' }) Vue.component('register', { template: '<h3>注冊(cè)組件</h3>' }) // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel var vm = new Vue({ el: '#app', data: { comName: 'login' // 當(dāng)前 component 中的 :is 綁定的組件的名稱 }, methods: {} }); </script> </body> </html>
上方代碼中,提取關(guān)鍵代碼如下:
<component :is="'register'"></component>
因此,如果要實(shí)現(xiàn)組件之間的切換,我們可以給<component>標(biāo)簽里的is屬性值設(shè)置為變量即可,來看看代碼實(shí)現(xiàn)。
實(shí)現(xiàn)組件切換的完整代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue2.5.16.js"></script> </head> <body> <div id="app"> <!-- 點(diǎn)擊按鈕后,設(shè)置變量`comName`為不同的值,代表著后面的component里顯示不同的組件 --> <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" comName='login'">登錄</a> <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" comName='register'">注冊(cè)</a> <!-- Vue提供了 component ,來展示對(duì)應(yīng)名稱的組件 --> <!-- component 是一個(gè)占位符, :is 屬性,可以用來指定要展示的組件的名稱 --> <!-- 此處的`comName`是變量,變量值為組件名稱 --> <component :is="comName"></component> </div> <script> // 組件名稱是 字符串 Vue.component('login', { template: '<h3>登錄組件</h3>' }) Vue.component('register', { template: '<h3>注冊(cè)組件</h3>' }) // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel var vm = new Vue({ el: '#app', data: { comName: 'login' // 當(dāng)前 component 中的 :is 綁定的組件的名稱 }, methods: {} }); </script> </body> </html>
效果:
總結(jié)
以上所述是小編給大家介紹的Vue.js 2.x之組件的定義和注冊(cè)圖文詳解,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- VUE注冊(cè)全局組件和局部組件過程解析
- Vue封裝的組件全局注冊(cè)并引用
- 詳解vue 動(dòng)態(tài)加載并注冊(cè)組件且通過 render動(dòng)態(tài)創(chuàng)建該組件
- vue動(dòng)態(tài)注冊(cè)組件實(shí)例代碼詳解
- Vue注冊(cè)組件命名時(shí)不能用大寫的原因淺析
- Vue 組件注冊(cè)實(shí)例詳解
- 淺談Vue組件及組件的注冊(cè)方法
- Vue源碼解讀之Component組件注冊(cè)的實(shí)現(xiàn)
- Vue組件全局注冊(cè)實(shí)現(xiàn)警告框的實(shí)例詳解
- vue 注冊(cè)組件的使用詳解
- 使用use注冊(cè)Vue全局組件和全局指令的方法
- 詳解vue 組件注冊(cè)
相關(guān)文章
vue組件Prop傳遞數(shù)據(jù)的實(shí)現(xiàn)示例
本篇文章主要介紹了vue組件Prop傳遞數(shù)據(jù)的實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08解決vscode進(jìn)行vue格式化,會(huì)自動(dòng)補(bǔ)分號(hào)和雙引號(hào)的問題
這篇文章主要介紹了解決vscode進(jìn)行vue格式化,會(huì)自動(dòng)補(bǔ)分號(hào)和雙引號(hào)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10vue-treeselect無(wú)法點(diǎn)擊問題(點(diǎn)擊無(wú)法出現(xiàn)拉下菜單)
這篇文章主要介紹了vue-treeselect無(wú)法點(diǎn)擊問題(點(diǎn)擊無(wú)法出現(xiàn)拉下菜單),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue3之路由的query參數(shù)和params參數(shù)用法
這篇文章主要介紹了Vue3之路由的query參數(shù)和params參數(shù)用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03解決vue刷新頁(yè)面以后丟失store的數(shù)據(jù)問題
這篇文章主要介紹了解決vue刷新頁(yè)面以后丟失store的數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08vue鼠標(biāo)懸停事件監(jiān)聽實(shí)現(xiàn)方法
頁(yè)面在鼠標(biāo)懸停(不動(dòng))n秒之后,頁(yè)面進(jìn)行相應(yīng)的事件,下面這篇文章主要給大家介紹了關(guān)于vue鼠標(biāo)懸停事件監(jiān)聽的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09分享12個(gè)Vue開發(fā)中的性能優(yōu)化小技巧(實(shí)用!)
一般來說,你不需要太關(guān)心vue的運(yùn)行時(shí)性能,它在運(yùn)行時(shí)非常快,但付出的代價(jià)是初始化時(shí)相對(duì)較慢,下面這篇文章主要給大家分享介紹了十二個(gè)Vue開發(fā)中的性能優(yōu)化小技巧,需要的朋友可以參考下2022-02-02