16-組件的創建(注:Vue的自定義事件中的變量不能用駝峰體)
vue的核心基礎就是組件的使用,玩好了組件才能將前面學的基礎更好的運用起來。組件的使用更使我們的項目解耦合。更加符合vue的設計思想MVVM。
那接下來就跟我看一下如何在一個Vue實例中使用組件吧!
這里有一個Vue組件的示例:
Vue.component('Vheader',{ data:function(){ return { } }, template:`<div class="header"> <div class="w"> <div class="w-l"> <img src="./logo.png"/> </div> <div class="w-r"> <button>登錄</button><button>注冊</button> </div> </div> </div>` })
組件是可復用的Vue實例,並且帶有一個名字:在這個例子中是 <Vheader>
。我們可以在一個通過 new Vue
創建的 Vue 根實例中,把這個組件作為自定義元素來使用:
<div id="app"> <Vheader></Vheader> </div>
var app = new Vue({ el:'#app', data:{ } })
效果顯示:
因為組件是可復用的 Vue 實例,所以它們與 new Vue
接收相同的選項
全局組件
代碼示例:
一個關於彈一彈的代碼實例<!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="D:\VsCode_projectsfiles\vue_file\inputfiles\vue.js"></script> </head> <body> <div id = 'app'>
// 使用組件 <tan></tan> </div> <script> //定義一個全局組件 Vue.component('tan',{ template:`<button v-on:click='jumpOut'>彈出靚白肌膚</button>`, methods:{ jumpOut:function(){ alert(666); } } }) var vm = new Vue({ el:"#app", }) </script> </body> </html>
組件的復用
<div id="app"> <Vheader></Vheader> <br> <Vheader></Vheader> <br> <Vheader></Vheader> </div>
效果顯示:
給Vheader組件中添加一個按鈕,綁定數據屬性count,然后你會發現點擊按鈕時,每個組件都會各自獨立維護它的 count
。因為你每用一次組件,就會有一個它的新實例被創建。
在創建組件過程中第一個參數是組件的名字,第二個參數是跟new Vue實例一樣的options。跟實例對象不同的是有兩點:
關於組件名的起名:https://cn.vuejs.org/v2/guide/components-registration.html
1、組件中沒有el,因為el僅僅的是綁定Vue的根元素。
2、data屬性不再是返回對象,而是返回一個函數。而且必須返回一個函數。
注冊自定義組件
代碼如下:
注冊一個自定義的全局組件
<!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 = '../../inputfiles/vue.js'></script> </head> <body> <div id = 'app'> <tan></tan> <tan></tan> <tan></tan> <tan></tan> <tan></tan> <tan></tan> </div> <script> //注冊一個自定義組件 Vue.component('tan',{ template:`<button v-on:click='jump'>彈奏魚尾紋{{count}}</button>`, //這里的data必須是一個方法,每次調用一個注冊好的組件時,都會觸發一個data方法 data:function(){ return { count:0 } }, methods:{ jump:function(){ this.count += 1 } } }) var vm = new Vue({ el:"#app", data:{}, }) </script> </body> </html>
ok。介紹到這里相信大家都明白了組件的創建了。
那么通常一個應用會一顆嵌套的組件🌲的形式來組織。
例如,你可能會有頁頭、側邊欄、內容區等組件,每個組件又包含了其它的像導航鏈接、博文之類的組件
如果說就拿上面那個導航的例子,我們把整個Vheader組件看作是全局注冊的組件。
不管怎樣,比如有A、B、C三個全局注冊的組件。
如果我們使用webpack這樣的構建系統,它會掃描我們整個文件。大家會發現全局注冊的組件意味着哪怕是你不想去使用了,webpack仍然很賣力的將這些組件構建在結果中。這會造成用戶下載JavaScript的無謂的增加。
到此我們僅僅的是通過Vue.component
實現全局注冊的組件,那么局部組件又是如何玩的呢?
注冊局部組件
代碼示例:
<!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="../../inputfiles/vue.js"></script>
</head>
<body>
<div id="app">
<tan></tan>
<tan></tan>
<tan></tan>
<tan></tan>
<tan></tan>
</div>
<script>
// 注冊一個局部組件
const tanComponent=({ template:`<button v-on:click='jump'>跳一跳{{count}}</button>`, data:function(){ return { count:0 } }, methods:{ jump:function(){ this.count += 1; } } }) var vm=new Vue({ el:'#app', data:{}, methods:{}, components:{ tan:tanComponent } }) </script> </body> </html>
當然,我們也可以使用JavaScript對象來定義組件:
var A = {/*......*/}; var B = {/*......*/}; var C = {/*......*/};
然后在compoents選項中定義你想要使用的組件:
new Vue({ el: '#app' components: { A B } })
在對象中放一個類似A
的變量名其實是A:A
的縮寫,即這個變量名同時是:
- 用在模板中的自定義元素的名稱
- 包含了這個組件選項的變量名
父組件向子組件傳值
示例一:
<!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="../../inputfiles/vue.js"></script> </head> <body> <div id="app"> // 通過在外圍定義的"name"的值綁定給template中的“name"(下面加引號的時外部的name值) <tan v-bind:name="name"></tan> </div> <script> // 注冊一個局部組件 const tanComponent={ template:`<button v-on:click='jump'>{{name}}{{count}}</button>`, data:function(){ return { count:0 } }, // 父組件向子組件傳值/外面向里面傳值 必須定義props的屬性 props:{ name:String }, methods:{ jump:function(){ this.count += 1 } } } var vm=new Vue({ el:"#app", data:{ name:"彈指一揮間" }, methods:{}, components:{ tan:tanComponent } }) </script> </body> </html>
配上一張圖:
示例二:
通過Prop像子組件傳遞數據
上面咱們看到了我們做的導航欄。如果你不能向這個組件傳遞某一篇博文的標題或內容之類的我們想展示的數據的話,它是沒有辦法使用的。這也正是 prop 的由來。
Prop 是你可以在組件上注冊的一些自定義特性。當一個值傳遞給一個 prop 特性的時候,它就變成了那個組件實例的一個屬性。為了給導航欄傳遞一個標題
Vue.component('Vheader',{ data:function(){ return { count:0 } }, props:['title'], template:`<div class="header"> <div class="w"> <div class="w-l"> <img src="./logo.png"/> <span>{{title}}</span> </div> <div class="w-r"> <button>登錄</button><button>注冊</button> </div> </div> </div>` })
<div id="app"> <Vheader title='路飛學城'></Vheader> </div>
另外我們還可以使用 v-bind
來動態傳遞 prop。
單個根元素
可能有很多同學在寫代碼的時候往往會在組件中這樣去寫:
<h3>{{ title }}</h3> <div v-html="content"></div>
然而如果你在模板中嘗試這樣寫,Vue 會顯示一個錯誤,並解釋道 every component must have a single root element (每個組件必須只有一個根元素)。你可以將模板的內容包裹在一個父元素內,來修復這個問題,例如:
<div> <h3>{{ title }}</h3> <div v-html="content"></div> </div>
這里面有提到了v-html:雙大括號會將數據解釋為普通文本,而非 HTML 代碼。為了輸出真正的 HTML,你需要使用 v-html
指令。
通過事件向父組件傳遞數據
示例一:
<!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="../../inputfiles/vue.js"></script> </head> <body> <div id="app"> <p>總消費量:{{totalCount}}</p> <tan v-bind:name="name" v-on:tank='add'></tan> </div> <script> const tanComponent={ template:`<button v-on:click='jump'>{{name}}{{count}}</button>`, data:function(){ return { count:0 } }, props:{ name:String }, methods:{ jump:function(){ this.count += 1 this.$emit('tank') }, } } var vm=new Vue({ el:"#app", data:{ totalCount:0, name:"古劍奇譚", }, components:{ tan:tanComponent }, methods:{ add:function(){ console.log(this.totalCount) this.totalCount += 1; } } }) </script> </body> </html>
示例二:
看個例子,比如現在我想點擊導航的某個按鈕,想讓導航上的字體變大。那么我們需要:
在其父組件中,可以通過添加一個postFontsize數據屬性來支持此功能。
var app = new Vue({ el:'#app', data:{ postFontSize:16 }, methods:{ clickHandler(){ this.postFontSize ++; } } })
它可以在模板中用來控制所有導航欄上文字的字號。
<Vheader title='路飛學城' :style="{ fontSize: postFontSize + 'px' }"></Vheader>
現在給導航欄上添加一個按鈕來放大字號:
<div class="w-r"> <button>登錄</button><button>注冊</button><button>放大文字</button> </div>
然后再讓添加的按鈕干活!
<button @click='largeHandler'>放大標題</button>
methods:{ largeHandler(){ this.$emit('luffy-title-size') } }
然后我們可以用 v-on
在導航欄組件上監聽這個事件,就像監聽一個原生 DOM 事件一樣:
<Vheader title='路飛學城' @luffy-title-size='clickHandler(res)' :style="{ fontSize: postFontSize + 'px' }"></Vheader>
另外我們還可以使用時間拋出一個值:
在導航欄組件中:
methods:{ largeHandler(){ this.$emit('luffy-title-size',1) } }
在父組件中:
methods:{ clickHandler(size){ this.postFontSize +=size; } }
此時這個size就是導航欄組件傳過來的數值1.
關於組件的注意事項及補充:
(1)關於組件的替換
如果如圖:替換的標簽是內層標簽,需要依賴外層標簽,那么就需要用這種方式再定義 is="組建名稱"來正常使用該標簽。
(2)關於子組件觸發原生事件:
在子組件中觸發父組件中的方法:
<!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="../../inputfiles/vue.js"></script> </head> <body> <div id = "app"> <tao v-on:click.native='taozou'></tao> </div> <script> var vm=new Vue({ el:"#app", data:{}, methods:{ taozou:function(){ alert("哈哈哈,成功逃課!!!") } }, components:{ tao:{ template:`<button>哈哈哈,逃課嘍</button>` }, }, }) </script> </body> </html>
好的,同學們,介紹完組件的基本使用、組件注冊、父子組件傳值,那么vue的基礎內容就給大家介紹完了。
那么,接下來我們就得聽官網的話,學完了基礎,我們就開始使用vue-cli這些腳手架工具來一鍵搭建我們的項目。