什麼是組件:組件就是一些標籤結構的封裝,同時爲這些結構添加須要的業務邏輯,設置你想要的樣式html
一個組件中通常能夠設置:結構,功能和樣式vue
vue-router
使用方便數組
複用服務器
組件的分類:app
全局組件:在vm實例外經過Vue.component來建立的組件,在當前vm實例指定的app模板範圍內都能使用ide
子組件:在組件內部經過components屬性來建立的組件函數
在vue中如何建立組件佈局
組件是可複用的 Vue 實例:這句話告訴咱們組件就是一個vue實例,那麼就意味着在以前建立vue實例中的配置成員在組件中彷佛都能寫,也就說明了如何配置Vue實例就如何配置組件實例ui
經過Vue.component(名稱,{配置})來建立組件
在頁面中經過組件名稱來使用,使用的時候就像使用標籤同樣
重點說明:在vm實例外來建立
<!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="./js/vue.js"></script> </head> <body> <!-- 建立父組件模版 --> <template id="father"> <div> <h2>我是爸爸</h2> <!-- 將子組件放在這裏 --> <son></son> </div> </template> <!-- 建立子組件模版 --> <template id="son"> <h2>我是兒子</h2> </template> <div id='app'> <!-- 將父組件放在這裏 --> <father></father> </div> <script> // 建立一個父組件 Vue.component('father', { template: '#father', data(){ // 注意:這裏若是寫了data函數,內部就必須return一個對象(沒有數據就寫個空對象),不然服務器會爆炸! return { } }, // 使用components建立子組件 components: { // 子組件名稱 son:{ template: '#son', data(){ return {} } } } }) var vm = new Vue({ el: '#app', data: {} }) </script> </body> </html>
常見錯誤:
你的組件的確沒有定義
你定義了,可是定義的位置不對,如放在vm實例後定義就會出現這個錯誤
重點:在組件中如何添加更多 配置
到底能夠添加那些配置
以前vm實例能夠添加的配置這邊基本上都能添加,除了el
el在以前的做用是指定模板,在組件中指定模板是經過template屬性
配置具體應該如何進行
template:指定模板
在template屬性中直接建立模板
使用template標籤建立模板,在template屬性中指定
建立模板結構,設置標識id
<template id='lwtemp'> <p style="color: red">我是隔壁老王~~~~!!!!</p> </template>
在template屬性中指定這個模板
Vue.component('laowang', { // 指定模板 // 沒有語法高亮,沒有代碼提示,沒有層次結構,不方便修改 template: "#lwtemp" })
細節:
這個錯誤告訴咱們組件只能有一個根元素,若是有多個則會出現這個錯誤,如何解決,將這多個元素再包含在到一個根元素中
data:
data必須是一個函數
一個組件的 data 選項必須是一個函數,所以每一個實例能夠維護一份被返回對象的獨立的拷貝
若是不是一個函數,那麼有可能形成組件複用的時候,多個組件指向同一個對象,形成操做其中任何一個組件,其它組件會有莫名其妙的變化
函數有做用域,在一個函數中生成的數據與其它的函數沒有關係,若是使用函數,就能夠作到一個組件內部的數據操做不會影響其它的組件,同時也不會影響組件的複用
data函數中必須返回 一個對象
錯誤信息
1.組件是一個單獨的結構,一個組件默認不能使用另一個組件中定義的成員
緣由:組件中的Data選項必須是一個函數,這個函數還必須返回 一個對象,咱們定義的數據必須寫在這個返回的對象中
緣由:data函數必須返回一個對象,若是沒有成員,也須要返回一個{}
mounted:
watch:
computed:
// vm外面建立組件 Vue.component('laowang', { // 指定模板 // 沒有語法高亮,沒有代碼提示,沒有層次結構,不方便修改 template: "#lwtemp", // 添加設置數據 data(){ return { age:0, myname:'隔壁老李' } }, methods:{ sayHi(){ alert('你好啊') } }, mounted(){ alert('頁面打開馬上執行') }, computed:{ myage(){ return this.age - 0 + 10 } } })
之後真正進行開發的時候,頁面可能會比較的複雜,常常會看到元素嵌套的場景出現,若是你將一些結構封裝爲組件,那麼勢必會形成組件的嵌套,這樣就產生了一個組件相關的組織結構
什麼是父組件,什麼是子組件
外層組件就能夠認爲是父組件
父組件中建立的組件就能夠認爲是這個父組件的子組件
父子只是一個組織結構佈局
爲何會出現父子組件這種結構
建立父子組件
先建立父組件
在父組件內部經過components建立子組件
Vue.component('father', { template: '#father', data() { return { fname: '老王' } }, // 經過components屬性來建立子組件,它是一個對象 components: { // 定義一個一個的子組件 // 3.定義第一個子組件son son: { // 4.能夠寫與父組件相同的成員 template: '#son', data() { return { sname: '小王' } } } } })
建立子組件
組件註冊:若是你從其它地方引入一個組件那麼就必須先註冊才能使用
使用子組件
在某個父組件中建立的子組件只有在這個父組件中可使用
所謂在父組件中使用是指在這個父組件的模板中使用
<!-- 2.父組件模板 --> <template id='father'> <div class="father"> <p>我是父組件:{{fname}}</p> <son></son> </div> </template>
在一個組件中定義的數據只有在當前組件中可使用
父組件中數據要傳遞給子組件來使用
若是要實現父傳子,子組件須要作什麼
在子組件中定義props屬性,它是一個獨立的屬性
props是一個數組
在props中定義的成員就至關於在data中定義的成員
在props通常就是你想定義的屬性的名稱,它們的類型是字符串
這個props至關於一個父組件爲子組件賦值的接口,在父組件中能夠爲子組件的props中定義的成員賦值
若是要實現父傳子,在父組件中須要作什麼
父組件中要使用子組件
在父組件中使用子組件的位置,使用v-bind爲子組件中的prop屬性賦值
大體瞭解子傳父的場景
經過this.$emit能夠發射事件
子傳父在子組件中須要作什麼
添加按鈕事件,在事件處理函數中去發射一個事件
發射事件並傳入相應的數據,它是經過事件發射向父組件傳遞數據
子傳父在父組件中又須要作什麼
父組件中進行指定事件的監聽
發現有指定的事件發射,就監聽並進行處理
在父組件中使用子組件的位置使用v-on進行監聽,在監聽處理函數中有一個默認的參數,這個參數就是從子組件事件發射時傳遞的數據
查看使用場景
爲何不能再使用this
this是指向當前組件,意味着事件只能由father組件進行監聽,與咱們要求不相合
this咱們知道它的本質就是一個vue實例,那麼咱們能不能直接建立一個全局的Vue實例來進行這個場景的事件發射呢?
建立事件總線:new Vue()
事件總線就是說明全部事件都能經過它來進行發射和監聽
說白了,事件總線就是一個單獨的全局的Vue實例
源組件中須要作什麼事情
發射事件,傳遞數據
目標組件須要作什麼事情
監聽事件,接收數據
父傳子demo
<!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="./js/vue.js"></script> </head> <body> <!-- 建立父組件模版 --> <template id="father"> <div> <h2>告訴兒子明天去{{surfing}}!</h2> <son :surfing="surfing"></son> </div> </template> <!-- 建立子組件模版 --> <template id="son"> <h2>我爸爸告訴我明天去{{surfing}}</h2> </template> <div id='app'> <father></father> </div> <script> // 建立父組件 Vue.component('father',{ template: '#father', data(){ return {surfing:'海上衝浪'} }, methods: { }, // 建立子組件 components: { son:{ template: '#son', props: ['surfing'], data(){ return {} }, methods: { } } } }) var vm = new Vue({ el: '#app', data: {} }) </script> </body> </html>
子傳父demo
<!-- 思路: 1.子組件發射事件,傳遞數據 2.父組件中使用子組件的位置進行監聽,經過v-on:事件名='事件處理函數' --> <!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="./js/vue.js"></script> </head> <body> <!-- 建立父組件模板 --> <template id="father"> <div> <h2>I am Father,我兒子的女友是:{{gfname}}</h2> <son v-on:emitname='getname'></son> </div> </template> <!-- 建立子組件模版 --> <template id="son"> <div> <h2>I am Son</h2> <button @click="sendName">點我發送女友楊冪給我爸爸</button> </div> </template> <div id='app'> <father></father> </div> <script> // 建立父組件 Vue.component('father', { template: '#father', data() { return { gfname: '' } }, methods: { getname(data){ console.log(data) this.gfname = data; } }, // 建立子組件 components: { son: { template: '#son', data() { return { gfname: '楊冪' } }, methods: { sendName(){ // $emit能夠發射事件 // this.$emit(事件名稱,事件參數(數據)) // 注意:在子組件函數中發射一個事件並不須要關心誰去作監聽 this.$emit('emitname',this.gfname) } } } } }) var vm = new Vue({ el: '#app', data: {} }) </script> </body> </html>
兄弟組件傳值demo
<!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="./js/vue.js"></script> </head> <body> <!-- 建立父組件模版 --> <template id="father"> <div> <alex></alex> <roger></roger> </div> </template> <!-- 建立2個兄弟組件模版 --> <template id="alex"> <div> <h2>我要告訴我兄弟今天去{{dosomething}}</h2> <button @click="tellinfo">點擊發送短信</button> </div> </template> <template id="roger"> <h2>WoW,我兄弟告訴我今天要去{{dosome}},好興奮!</h2> </template> <div id='app'> <father></father> </div> <script> //建立事件總線bus實例 var bus = new Vue(); // 建立父組件 Vue.component('father',{ template: '#father', data(){ return {} }, methods: { }, // 建立2個兄弟組件 components: { alex: { template: '#alex', data(){ return { dosomething: '釣魚', } }, methods: { tellinfo(){ // 使用事件總線來發送事件 bus.$emit('emitname', this.dosomething) } } }, roger:{ template: '#roger', data(){ return { dosome:'??' } }, methods: { }, mounted () { bus.$on('emitname', data=>{ console.log(data) this.dosome = data }) } } } }) var vm = new Vue({ el: '#app', data: {} }) </script> </body> </html>
能夠實現導航跳轉(頁面跳轉)的一種方式,在vue組件的跳轉都是經過路由來實現的
由於咱們不想實現頁面的跳轉
可是咱們又想展現不一樣的頁面的不一樣的內容
咱們要作什麼
咱們須要作的是,將組件 (components) 映射到路由 (routes),而後告訴 Vue Router 在哪裏渲染它們
基本路由的添加方式
你得路由如何添加:它是一個單獨的結構
經過VueRouter進行路由對象的建立
經過routes進行路由配置
路由和組件如何映射
如何指定你組件內容的展現區域
如何使用路由
掛載路由=注入路由
添加router-view結構,指定路由映射組件的展現區域
demo
<!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="./js/vue.js"></script> <script src="./js/vue-router.js"></script> </head> <body> <div id='app'> <router-link to="/index">首頁</router-link> <router-link to="/product">產品頁</router-link> <h3>路由匹配到的組件將渲染在這裏</h3> <div style="width:600px; height: 400px; border: solid"> <router-view></router-view> </div> </div> <script> // 每一個路由對象映射着一個單獨的組件,因此咱們第一步建立好組件 // 1.建立幾個組件 var Index = Vue.component('index', { template: '<div>首頁</div>' }) var Product = Vue.component('product', { template: '<div>產品</div>' }) // 2.建立路由對象,建立以前不要忘了引入vue-router.js文件 // 經過new VueRouter()來建立路由對象,在構造函數中添加路由配置 var router = new VueRouter({ // 3.添加路由配置 // 咱們能夠配置多個路由,因此使用routes來進行多個路由的配置 routes: [ // 4.添加單個路由配置,俺哥路由都是以對象的方式存在,對於單個路由通常咱們 //會配置下面幾個屬性 { name: 'Index', path: '/index', component: Index }, { name: 'Product', path: '/product', component: Product } ] }) var vm = new Vue({ el: '#app', // 5.注入/掛載路由 router: router, data: {} }) </script> </body> </html>