本文講解vue中的組件開發
先上代碼:
1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<span :style='{"font-size":fontSize+"px"}'>{{startMsg}}</span>
<br> 請輸入組件描述:
<input type="text" v-model='inputDes'>
<!-- 父組件要接受值,就要監聽子組件規定的事件,要獲取到參數值,使用規定的$event -->
<btn-counter :des='inputDes' @add-size='addSize($event)'></btn-counter>
<br>
<!-- 兄弟組件之間傳值:使用事件中心,$on(監聽事件),$off(銷燬事件),$emit(觸發事件),mounted(模板已加載完畢準備就緒) -->
<lingbug-tom des='我是tom,點我可以給jerry增加'></lingbug-tom>
<br>
<lingbug-jerry des='我是jerry,點我可以給tom增加'></lingbug-jerry>
<br>
<button @click='destroyEventHub'>銷燬兄弟間傳值事件</button>
<!-- 父組件向子組件傳值:插槽slot(一般用戶固定文本,但是一些內容需要父組件動態傳遞,如:異常信息) -->
<error-box>自定義異常信息</error-box>
<error-box>用戶名已存在</error-box>
<error-box></error-box>
<!-- 具名插槽:可以有多個插槽,通過name來指定 -->
<error-box-detail>
<h1 slot='title'>異常標題:要註冊的用戶名已存在</h1>
<p>異常詳情:用戶名lingbug已存在,請修改後重試!</p>
<h3 slot='remark'>建議修改爲ling-bug or lingbug1</h3>
</error-box-detail>
<!-- 如果內容比較多,可以使用template包裹起來 -->
<error-box-detail>
<template slot='title'>
<p>異常標題:</p>
<p>要註冊的用戶名已存在</p>
<p>用戶名:lingbug</p>
</template>
<template>
<p>異常詳情:</p>
<p>用戶名lingbug已存在,請修改後重試!</p>
</template>
<template slot='remark'>
<p>修復建議:</p>
<p>ling-bug or lingbug1</p>
</template>
</error-box-detail>
<!-- 作用域插槽:子組件可以將數據傳遞給父組件讓父組件進行處理 -->
<user-list :list='userList'>
<!-- 使用規定的slot-scope來獲取子組件的插槽數據 -->
<!-- 注意:vue版本低於2.6無法使用作用域插槽 -->
<template slot-scope="slotProps">
<span v-if='slotProps.info.age >= 18' style="color: orange;">姓名:{{slotProps.info.name}},性別:{{slotProps.info.sex}},年齡:{{slotProps.info.age}}</span>
<span v-else>姓名:{{slotProps.info.name}},性別:{{slotProps.info.sex}},年齡:{{slotProps.info.age}}</span>
</template>
</user-list>
</div>
</body>
</html>
<!-- <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> -->
<script src="./vue-2.6.11.min.js"></script>
<script src="./index.js"></script>
2.js
// 註冊全局組件
Vue.component('btn-counter', {
props: ['des'],
data: function() {
return {
clickCount: 0,
fontSize: 10
};
},
// 這個template的語法是ES6的語法
template: `
<div>
<span>組件描述:{{des}}</span>
<button @click="selfclick">我被點擊了{{clickCount}}下</button>
<button @click='$emit("add-size",fontSize)'>增大字體</button>
</div>
`, //子組件向父組件傳值,使用規定好的$emit(事件名,參數)
methods: {
selfclick: function() {
this.clickCount += 2;
}
}
});
// 初始化一個vue實例作爲事件中心
var eventHub = new Vue();
// 兄弟組件之間傳值:使用事件中心,$on(監聽事件),$off(銷燬事件),$emit(觸發事件),mounted(模板已加載完畢準備就緒)
Vue.component('lingbug-tom', {
props: ['des'],
template: `
<div>
<span>{{des}}</span>
<button @click='addCount'>{{count}}</button>
</div>
`,
data: function() {
return {
count: 0
};
},
methods: {
addCount: function() {
eventHub.$emit('add-jerry', 2);
}
},
mounted: function() {
eventHub.$on('add-tom', r => this.count += r);
}
});
Vue.component('lingbug-jerry', {
props: ['des'],
template: `
<div>
<span>{{des}}</span>
<button @click='addCount'>{{count}}</button>
</div>
`,
data: function() {
return {
count: 0
};
},
methods: {
addCount: function() {
eventHub.$emit('add-tom', 1)
}
},
mounted: function() {
eventHub.$on('add-jerry', r => this.count += r);
}
});
// 父組件向子組件傳值:插槽slot(一般用戶固定文本,但是一些內容需要父組件動態傳遞,如:異常信息)
Vue.component('error-box', {
template: `
<div>
<span>程序有異常發生,Error:</span>
<slot>沒有異常</slot>
</div>
` //如果父組件不傳遞內容,可以使用slot裏面的默認內容
});
// 具名插槽:可以有多個插槽,通過name來指定
Vue.component('error-box-detail', {
template: `
<div>
<header>
<slot name='title'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name='remark'></slot>
</footer>
</div>
`
});
// 作用域插槽:子組件可以將數據傳遞給父組件讓父組件進行處理
Vue.component('user-list', {
props: ['list'],
// 插槽:將數據綁定到slot上,這樣父組件中就可以獲取到數據
// 注意:vue版本低於2.6無法使用作用域插槽
template: `
<div>
<ul>
<li :key='user.id' v-for='(user,index) in list'>
<slot :info='user'>
{{index}}.姓名:{{user.name}},性別:{{user.sex}},年齡:{{user.age}}
</slot>
</li>
</ul>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
startMsg: 'Hello World~',
inputDes: '',
fontSize: 5,
userList: [{
id: 1,
name: '張三',
sex: '男',
age: 20
},
{
id: 2,
name: '李四',
sex: '女',
age: 12
},
{
id: 3,
name: '王五',
sex: '男',
age: 15
}
]
},
methods: {
addSize: function(value) {
this.fontSize += value;
},
destroyEventHub: function() {
eventHub.$off('add-tom');
eventHub.$off('add-jerry');
alert('銷燬完成!');
}
}
});
總結:
一、vue組件:Vue.component(組件名稱,{}); *注意:在vue中儘量不要使用大寫字母,也就是不要使用駝峯命名,儘量使用-分開,否則導致不必要的錯誤*
1.第二個參數option的屬性:
a.template:模板(ES6中可以使用``來使模板代碼可讀性更好)
b.data:數據(使用方法,返回一個對象)
c.methods:組件的方法
d.props:組件的屬性,外部可以傳入
e.mounted:方法(在組件模板準備就緒時調用)
二、子組件傳值給父組件:
1.在子組件中定義事件:使用$emit(事件名,參數)
2.父組件監聽子組件定義的事件:v-on:事件名 或者 :事件名
3.要想獲取到參數,使用$event :事件名($event)
三、兄弟組件之間傳值:使用事件中心
1.實例化一個vue對象作爲事件中心:var eventHub = new Vue();
2.在組件模板準備就緒時(mounted)將事件註冊到事件中心($on):eventHub.$on('事件名, 邏輯);
3.在自己的方法中調用兄弟組件註冊的事件($emit):eventHub.$emit(兄弟組件的事件名, 要傳遞的參數);
4.銷燬註冊的事件($off):eventHub.$off(事件名);
四、插槽(slot):
1.在組件中定義插槽slot:
a.<slot>默認值</slot>
b.多個插槽使用name來區分: <header>
<slot name='title'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name='remark'></slot>
</footer>
2.父組件使用子組件時,填寫數據到插槽中:
a.<error-box>自定義異常信息</error-box>
b.如果爲空則使用子組件的插槽默認值:<error-box></error-box>
c.多個插槽使用slot = name來區分:<h1 slot='title'>異常標題:要註冊的用戶名已存在</h1>
<p>異常詳情:用戶名lingbug已存在,請修改後重試!</p>
<h3 slot='remark'>建議修改爲ling-bug or lingbug1</h3>
d.內容比較多,可以使用template: <error-box-detail>
<template slot='title'>
<p>異常標題:</p>
<p>要註冊的用戶名已存在</p>
<p>用戶名:lingbug</p>
</template>
<template>
<p>異常詳情:</p>
<p>用戶名lingbug已存在,請修改後重試!</p>
</template>
<template slot='remark'>
<p>修復建議:</p>
<p>ling-bug or lingbug1</p>
</template>
</error-box-detail>
3.作用域插槽(子組件將數據傳遞給父組件,由父組件來進行一些邏輯處理):注意:只有在2.6版本以上vue纔可以使用
1.定義子組件數據,使用slot和v-bind來指定父組件可操作的數據:
<ul>
<li :key='user.id' v-for='(user,index) in list'>
<slot :info='user'>
{{index}}.姓名:{{user.name}},性別:{{user.sex}},年齡:{{user.age}}
</slot>
</li>
</ul>
2.父組件中使用template和slot-scope來獲取到子組件的數據:
<template slot-scope="slotProps">
<span v-if='slotProps.info.age >= 18'>成年人</span>
<span v-else>未成年</span>
</template>