組件: 顧名思義, 也就是組成的部件, 即整體的組成部分
這個(gè)組成部分是可以缺少的,但是其存在的意義是無(wú)可替代的
這個(gè)組成部分也是可以復(fù)用的
全局方法一:
大致可以分成三步
1.在我們引入vue.js之后,Vue會(huì)被注冊(cè)為一個(gè)全局對(duì)象,我們使用對(duì)象本身的方法進(jìn)行組件的創(chuàng)建
------使用Vue這個(gè)全局對(duì)象的component方法進(jìn)行全局注冊(cè)一個(gè)組件
2.創(chuàng)建根實(shí)例,進(jìn)行視圖的綁定
3.組件的顯示
-----將組價(jià)的名稱(chēng)作為標(biāo)簽寫(xiě)在視圖內(nèi)部,就能夠完成組件的顯示
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--3. 定義的組件名作為標(biāo)簽存在,將組件顯示在頁(yè)面上-->
<my-component></my-component>
</div>
</body>
</html>
<script>
//1. 使用vue這個(gè)全局隊(duì)形內(nèi)置的components方法進(jìn)行組件的創(chuàng)建
//在components這個(gè)方法中有兩個(gè)重要的參數(shù),第一個(gè)參數(shù)是組件的名稱(chēng),第二個(gè)參數(shù)是組件的內(nèi)容
Vue.component('my-component', {
//在這里使用一個(gè)父標(biāo)簽將組件包裹起來(lái)
template: '<div><a href="#">注冊(cè)</a><a href="#">登錄</a></div>'
})
//2. 創(chuàng)建根實(shí)例,也就是實(shí)例化一個(gè)vue對(duì)象,進(jìn)行視圖的綁定
var vm = new Vue({
el: '#app'
})
</script>
全局方法二
使用全局的Vue.extend()構(gòu)造器進(jìn)行注冊(cè)
Vue.extend()類(lèi)似于繼承,通過(guò)這個(gè)構(gòu)造器擴(kuò)展(繼承)之后,相當(dāng)于Vue對(duì)象本身添加了一些這個(gè)對(duì)象原先沒(méi)有的東西
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入門(mén)之extend全局方法</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="app"></div>
</body>
</html>
<script>
//通過(guò)構(gòu)造器創(chuàng)建一個(gè)組件,相當(dāng)于在vue這個(gè)全局對(duì)象本身上添加了一些新的內(nèi)容,作用相當(dāng)于構(gòu)造函數(shù)
//----繼承自vue,但是比vue本身更強(qiáng)大
var myVue = Vue.extend({
template: '<div>這是通過(guò)構(gòu)造器創(chuàng)建出來(lái)的組件</div>'
});
var app = new myVue({
el: '#app'
});
</script>
局部方法一
大致分成兩個(gè)部分
1.穿件跟實(shí)例
2.在跟實(shí)例內(nèi)部定義組件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--3. 這是我定義的組件 占位標(biāo)簽-->
<my-component></my-component>
</div>
</body>
</html>
<script>
//1. 創(chuàng)建根實(shí)例
var vm = new Vue({
el: '#app',
//2. 在根實(shí)例內(nèi)部創(chuàng)建組件
components:{
'my-component':{
template: '<div><a href="#">注冊(cè)</a><a href="#">登錄</a></div>'
}
}
})
</script>
組件注冊(cè)的其它方式1
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--這是我定義的組件-->
<my-component></my-component>
</div>
<template id="my-template">
<div>
<a href="#">注冊(cè)</a>
<a href="#">登錄</a>
</div>
</template>
</body>
</html>
<!--
注意組件的模板替換了自定義元素糜芳,自定義元素的作用只是作為一個(gè)掛載點(diǎn)。
----這可以用實(shí)例選項(xiàng) replace 改變锰蓬。
-->
<script>
//1. --定義 + 注冊(cè) 組件構(gòu)造器
Vue.component('my-component', {
//將template的內(nèi)容提取到一個(gè)標(biāo)簽中,通過(guò)id來(lái)獲取
template: '#my-template'
})
//2. 創(chuàng)建根實(shí)例
var vm = new Vue({
el: '#app'
})
</script>
組件注冊(cè)的其它方式2
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--這是我定義的組件-->
<template>
<div>
<a href="#">注冊(cè)</a>
<a href="#">登錄</a>
</div>
</template>
</div>
</body>
</html>
<!--
自定義的標(biāo)簽只是自定義組件的一個(gè)掛載點(diǎn),自定義組件會(huì)將其替換掉
----直接使用自定義的組件將自定義的標(biāo)簽替換
-->
<script>
//2. 創(chuàng)建根實(shí)例
var vm = new Vue({
el: '#app'
})
</script>
組件內(nèi)部的data
組件內(nèi)部的data屬性必須是一個(gè)函數(shù)
以全局注冊(cè)的組件為例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--全局的組件-->
<ab></ab>
<!--局部的組件-->
<my-component></my-component>
</div>
</body>
</html>
<script>
//自定義指令
//Vue.directive('指令名',{})
//定義組件 參數(shù)1:組件的名稱(chēng) 參數(shù)2: 對(duì)象
Vue.component("ab",{
template:
`<ul>
<li>{{name}}</li>
<li>{{age}}</li>
<li>{{sex}}</li>
</ul>`,
//data屬性的屬性值是一個(gè)函數(shù)----函數(shù)內(nèi)部返回一個(gè)對(duì)象
data:function(){
return {
name:"首頁(yè)",
age:"聯(lián)系我們",
sex:"新聞"
}
}
})
//2. 創(chuàng)建根實(shí)例-----并在根實(shí)例下面創(chuàng)建一個(gè)局部的組件
var vm = new Vue({
el: '#app',
//局部組件
components:{
'my-component':{
template: `<ul>
<li>{{name}}</li>
<li>{{age}}</li>
<li>{{sex}}</li>
</ul>`,
data:function(){
return {
name:1,
age:2,
sex:3
}
}
}
}
})
</script>
父子組件通信
父組件將數(shù)據(jù)傳遞給自組件使用prop 子組件將其內(nèi)部發(fā)生的事情通告給父組件使用emit
復(fù)雜的父子組件的props
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<parent></parent>
</div>
<template id="parent">
<div>
<div>我是父組件</div>
<child :message="message"></child>
</div>
</template>
<template id="child">
<div>
<div>我是子組件</div>
<span>{{message}}</span>
</div>
</template>
</body>
</html>
<script>
var vm = new Vue({
el: '#app',
//我是父組件
components:{'parent':{
template:"#parent",
data:function(){
return {
message:"hello world"
}
},
//我是子組件
components:{'child':{
props:['message'],
template:"#child"
}}
}}
})
</script>
字面量語(yǔ)法 vs 動(dòng)態(tài)語(yǔ)法
使用字面量語(yǔ)法傳遞數(shù)字,有時(shí)候會(huì)出現(xiàn)問(wèn)題
單向數(shù)據(jù)流
數(shù)據(jù)從父組件傳遞到子組件,但是不會(huì)反過(guò)來(lái)傳遞
數(shù)據(jù)傳遞-注意事項(xiàng)
在 JavaScript 中對(duì)象和數(shù)組是引用類(lèi)型只锭,指向同一個(gè)內(nèi)存空間惕蹄,
如果 prop 是一個(gè)對(duì)象或數(shù)組唆迁,在子組件內(nèi)部改變它會(huì)影響父組件的狀態(tài)民逼。
自定義事件
每個(gè) Vue 實(shí)例都實(shí)現(xiàn)了事件接口(Events interface)糊余,即:
使用 $on(eventName) 監(jiān)聽(tīng)事件
使用 $emit(eventName) 觸發(fā)事件
類(lèi)似于我們注冊(cè)(vue中是$on)點(diǎn)擊事件,通過(guò)鼠標(biāo)點(diǎn)擊觸發(fā)(vue中是emit)
document.onclick = function(event){
console.log(111)
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<style>
#dv1,
#dv2 {
width: 500px;
height: 100px;
}
#dv1 {
border: 1px solid red;
margin: 50px auto;
}
#dv2 {
border: 1px solid green;
margin: 50px auto;
}
</style>
</head>
<body>
<div id="app2">
<component2></component2>
</div>
<div id="app1">
<component1></component1>
</div>
</body>
</html>
<script type="text/javascript">
//1. 創(chuàng)建一個(gè)空的公共的vue對(duì)象
var bus = new Vue();
//2. 在vm1實(shí)例中創(chuàng)建組件1,定義$emit來(lái)發(fā)送數(shù)據(jù)
var vm1 = new Vue({
el: '#app1',
components: {
component1: {
template: `<div id="dv1" v-on:click="add">
<div>點(diǎn)擊我,觸發(fā)自定義事件,進(jìn)行數(shù)據(jù)的傳遞</div>
<div>當(dāng)前的數(shù)據(jù)是:{{num}}</div>
</div>`,
data: function() {
return {
num: 0
}
},
methods: {
add: function() {
this.num++;
bus.$emit('test', this.num)
}
}
}
}
})
//在vm2實(shí)例中創(chuàng)建組件2,定義$on來(lái)接收傳遞的數(shù)據(jù)
var vm2 = new Vue({
el: '#app2',
components: {
component2: {
template: `<div id="dv2" v-on:click="result">
<div>點(diǎn)擊我,進(jìn)行自定義事件的注冊(cè)</div>
<div>傳遞過(guò)來(lái)的數(shù)據(jù)是{{getData}}</div>
</div>`,
data: function() {
return {
getData: 0
}
},
methods: {
result: function() {
//this問(wèn)題
var vm2This = this;
bus.$on('test', function(num) {
vm2This.getData = num;
//事件的解綁問(wèn)題
bus.$off("test")
})
}
}
}
}
})
</script>
slot
有時(shí)候,我們需要對(duì)組件進(jìn)行局部的修改,
vue提供了一種方式來(lái)混合父組件的內(nèi)容與子組件自己的模板
這個(gè)過(guò)程被稱(chēng)為 內(nèi)容分發(fā) 也就是slot
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入門(mén)之extend全局方法</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--父容器輸入標(biāo)簽,會(huì)將slot標(biāo)簽替換掉-->
<my-slot>
<h3>這里是父容器寫(xiě)入的</h3>
</my-slot>
<!--父容器綁定數(shù)據(jù)到子容器的slot,會(huì)將slot中的數(shù)據(jù)替換掉-->
<my-slot>{{ email }}</my-slot>
<!--父容器什么都不傳內(nèi)容-->
<my-slot></my-slot>
</div>
</body>
</html>
<script>
// 反引號(hào):可以定義多行字符串秀又。
var temp = `
<div>
<h1>這里是子組件</h1>
<hr>
<slot>slot標(biāo)簽會(huì)被父容器寫(xiě)的額外的內(nèi)容替換掉单寂,如果父容器沒(méi)有寫(xiě)入任何東西贬芥,此標(biāo)簽將保留吐辙!</slot>
</div>
`;
Vue.component('MySlot', { // 如果定義的組件為MySlot,那么用組件的時(shí)候:<my-slot></my-slot>
template: temp,
});
// 初始化一個(gè)Vue實(shí)例
var app = new Vue({
el: '#app',
data: {
email: 'flydragon@gmail.com'
}
});
</script>
具名slot
元素可以用一個(gè)特殊的屬性 name 來(lái)配置如何分發(fā)內(nèi)容蘸劈。多個(gè) slot 可以有不同的名字昏苏。
具名 slot 將匹配內(nèi)容片段中有對(duì)應(yīng) slot 特性的元素
仍然可以有一個(gè)匿名 slot ,它是默認(rèn) slot 威沫,作為找不到匹配的內(nèi)容片段的備用插槽贤惯。如果沒(méi)有默認(rèn)的 slot ,這些找不到匹配的內(nèi)容片段將被拋棄
動(dòng)態(tài)組件
通過(guò)使用保留的 元素孵构,動(dòng)態(tài)地綁定到它的 is 特性,我們讓多個(gè)組件可以使用同一個(gè)掛載點(diǎn)烟很,并動(dòng)態(tài)切換
如果把切換出去的組件保留在內(nèi)存中颈墅,可以保留它的狀態(tài)或避免重新渲染
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<h3>動(dòng)態(tài)組件</h3>
<!-- 定義三個(gè)temp模板,用于切換 -->
<template id="temp-tab01">
<div>this is tab01</div>
</template>
<template id="temp-tab02">
<div>this is tab02</div>
</template>
<template id="temp-tab03">
<div>this is tab03</div>
</template>
<div id="dr01">
<!-- 導(dǎo)航欄 -->
<div class="border cf">
<ul>
<li>
<a href="javascript:void(0);" @click="toggleTabs(tab01Text);">{{tab01Text}}</a>
</li>
<li>
<a href="javascript:void(0);" @click="toggleTabs(tab02Text);">{{tab02Text}}</a>
</li>
<li>
<a href="javascript:void(0);" @click="toggleTabs(tab03Text);">{{tab03Text}}</a>
</li>
</ul>
</div>
<!-- 點(diǎn)擊導(dǎo)航后要切換的內(nèi)容 -->
<div class="border" style="height: 100px;">
<!-- 如果把切換出去的組件保留在內(nèi)存中雾袱,可以保留它的狀態(tài)或避免重新渲染恤筛。為此可以添加一個(gè) keep-alive 指令參數(shù) -->
<component :is="currentView" keep-alive></component>
</div>
</div>
</body>
</html>
<script>
//通過(guò)使用保留的 <component> 元素,動(dòng)態(tài)地綁定到它的is屬性芹橡,我們讓多個(gè)組件可以使用同一個(gè)掛載點(diǎn)毒坛,并動(dòng)態(tài)切換:
//擴(kuò)展組件tab01
var tab01 = Vue.extend({
template: "#temp-tab01",
});
//擴(kuò)展組件tab02
var tab02 = Vue.extend({
template: "#temp-tab02",
});
//擴(kuò)展組件tab03
var tab03 = Vue.extend({
template: "#temp-tab03",
});
//新建vue實(shí)例
var dr01 = new Vue({
el: "#dr01",
data: {
tab01Text: "tab01", //導(dǎo)航欄文本1
tab02Text: "tab02", //導(dǎo)航欄文本2
tab03Text: "tab03", //導(dǎo)航欄文本3
currentView: 'tab01', //默認(rèn)選中的導(dǎo)航欄
},
//局部注冊(cè)組件
components: {
tab01: tab01,
tab02: tab02,
tab03: tab03,
},
methods: {
//綁定tab的切換事件
toggleTabs: function(tabText) {
this.currentView = tabText;
}
}
});
</script>