元件
全域性註冊元件
- Vue.extend(選項物件)建立元件構造器
- Vue.component( id, [definition] )註冊元件
- 使用元件
//擴充套件元件構造器
let Custom = Vue.extend({
template: '<div>我是全域性元件</div>'
})
//註冊元件
Vue.component('custom-component', Custom)
複製程式碼
//簡寫方式,自動呼叫 Vue.extend
Vue.component('custom-component', {
template: '<div>我是全域性元件</div>'
})
複製程式碼
//使用元件
<div id="app">
<custom-component></custom-component>
</div>
複製程式碼
區域性註冊元件
- 選項物件的components屬性註冊區域性元件,只能在所註冊的作用域模板中使用
{
components:{
元件id:例項構造器 | 物件
}
}
複製程式碼
new Vue({
el:'#app',
components: {
'custom-component': {
template: `<div>我是區域性註冊的元件</div>`
}
}
})
複製程式碼
元件命名約定和模板
註冊元件命名:
- kebab-case (短橫線分隔命名)
- camelCase (駝峰式命名)
- PascalCase (單詞首字母大寫命名)
使用元件命名:
- kebab-case (短橫線分隔命名)
父子元件之間的通訊
<div id="app">
<parent></parent>
</div>
Vue.component('parent', {
data(){
return {
name: 'parent'
}
},
template: `<div>
{{name}}
<child></child>
</div>`,
components: {
child: {
data(){
return {
name: 'child'
}
},
template: `<div>{{name}}</div>`
}
}
})
new Vue({
el: '#app'
})
複製程式碼
- 父元件傳遞引數
- 在child元件上新增屬性,如果是動態屬性用v-bind
- child元件使用props接受引數,可以驗證引數
在child元件上繫結動態屬性msg,把parent元件的msg值傳給child元件
{
data(){
return {
name: 'parent',
msg: '你是誰'
}
},
template: `<div>
{{name}}
<child :msg="msg"></child>
</div>`,
components: {
child: {
data(){
return {
name: 'child'
}
},
template: `<div>{{name}}</div>`
}
}
}
複製程式碼
child元件接受引數
{
child: {
props: ['msg'],
data(){
return {
name: 'child'
}
},
template: `<div>
<p>我是:{{name}}</p>
<p>{{msg}}</p>
</div>`
}
}
複製程式碼
child引數驗證
{
props: {
msg: {
//型別
type: String,
//是否必須
required: true,
//預設值
default: '',
//驗證
validator(value) {
return value
}
}
}
}
複製程式碼
完整示例
Vue.component('parent', {
data(){
return {
name: 'parent',
msg: '你是誰'
}
},
template: `<div>
{{name}}
<child :msg="msg"></child>
</div>`,
components: {
child: {
props: {
msg: {
type: String,
required: true,
default: ''
}
},
data(){
return {
name: 'child'
}
},
template: `<div>
<p>我是:{{name}}</p>
<p>{{msg}}</p>
</div>`
}
}
})
複製程式碼
-
子元件釋出事件
- child元件使用$emit釋出事件
- 在parent元件監聽事件
Vue.component('parent', {
...
template: `<div>
{{name}}
<child @change-msg="changeMsgHandle" :msg="msg"></child>
</div>`,
methods: {
changeMsgHandle(val){
this.msg = val;
}
},
components: {
child: {
...
methods: {
changeMsg(){
this.$emit('change-msg','我是child元件');
}
},
template: `<div>
<p>我是:{{name}}</p>
<p>{{msg}}</p>
<button @click="changeMsg" type="button">改變msg</button>
</div>`
}
}
})
複製程式碼
完整示例
Vue.component('parent', {
data(){
return {
name: 'parent',
msg: '你是誰'
}
},
template: `<div>
{{name}}
<child @change-msg="changeMsgHandle" :msg="msg"></child>
</div>`,
methods: {
changeMsgHandle(val){
this.msg = val;
}
},
components: {
child: {
props: {
msg: {
type: String,
required: true,
default: ''
}
},
data(){
return {
name: 'child'
}
},
methods: {
changeMsg(){
this.$emit('change-msg','我是child元件');
}
},
template: `<div>
<p>我是:{{name}}</p>
<p>{{msg}}</p>
<button @click="changeMsg" type="button">改變msg</button>
</div>`
}
}
})
複製程式碼
使用插槽分發內容
-
編譯作用域
- 父元件模板的內容在父元件作用域內編譯;
- 子元件模板的內容在子元件作用域內編譯。
-
插槽的作用
- 將父元件中寫在子元件一對標籤內的結構混合在子元件模板中,這個過程稱之為內容分發。使用特殊的 元素作為原始內容的插槽
-
單個插槽
- 如果子元件中沒有一對slot標籤,寫在子元件標籤對的內容會被丟棄 子元件中有slot標籤,子元件標籤對的內容會整體替換在slot標籤位置 slot標籤內的內容被視作備用內容
-
具名插槽
- 可以使用name來配置如何分發內容
- 沒有name的slot被視為預設插槽
元件的雙向繫結
v-modal作用在元件上,建立雙向繫結
- 接收value這個prop
- 有值變化時,釋出input事件
<div id="app">
<custom v-model="message"></custom>
<!--v-model就是下面寫法的語法糖-->
<custom :value="message" @input="value=>message=value"></custom>
</div>
Vue.component('custom', {
props:{
value:{
type: String
}
},
template: `<div>
<h2>{{value}}</h2>
<button @click="changeTitle">改變</button>
</div>`,
methods: {
changeTitle(){
this.$emit('input','子元件改了')
}
}
});
new Vue({
el: '#app',
data:{
message: '父級的資料'
}
});
複製程式碼
- v-model定製 prop 和 event
<div id="app">
<custom v-model="message" value='hello'></custom>
</div>
Vue.component('custom', {
model: {
prop: 'propName',
event: 'eventName'
},
props:{
propName: {
type: String
},
value:{
type: String
}
},
template: `<div>
<h2>{{value}}</h2>
<h2>{{propName}}</h2>
<button @click="changeTitle">改變</button>
</div>`,
methods: {
changeTitle(){
this.$emit('eventName','子元件改了')
}
}
});
new Vue({
el: '#app',
data:{
message: '父級的資料'
}
});
複製程式碼
.sync 修飾符
- 語法糖,會擴充套件成一個更新父元件繫結值的 v-on 偵聽器
<div id="app">
<custom :title.sync="message"></custom>
</div>
Vue.component('custom', {
props:{
title: {
type: String,
default: 'hello'
}
},
template: `<div>
<h2>{{title}}</h2>
<button @click="changeTitle">改變</button>
</div>`,
methods: {
changeTitle(){
this.$emit('update:title',"改變了")
}
}
});
new Vue({
el:'#app',
data:{
message: 'vuejs'
}
});
複製程式碼
註冊全域性自定義指令
-
鉤子函式
- bind:只呼叫一次,指令第一次繫結到元素時呼叫
- inserted:被繫結元素插入父節點時呼叫
- update:更新時呼叫
- componentUpdated: 更新完畢呼叫
- unbind:只呼叫一次,指令與元素解綁時呼叫。
Vue.directive('my-directive', {
bind: function () {},
inserted: function () {},
update: function () {},
componentUpdated: function () {},
unbind: function () {}
})
複製程式碼
封裝model元件
- 樣式
<style>
p,h4{
margin:0;
}
.modal{
width: 500px;
background-color: #fff;
border: 1px solid rgba(0,0,0,.2);
border-radius: 6px;
box-shadow: 0 3px 9px rgba(0,0,0,.5);
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 111;
}
.modal-header {
padding: 15px;
border-bottom: 1px solid #e5e5e5;
}
.modal-content {
padding: 20px;
}
.modal-footer {
padding: 15px;
text-align: right;
border-top: 1px solid #e5e5e5;
}
.btn {
padding: 5px 15px;
}
.mask {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(55,55,55,.6);
height: 100%;
z-index: 100;
}
</style>
複製程式碼
- 結構
<div id="app">
<Modal></Modal>
</div>
複製程式碼
- modal主體結構
<div class="modal">
<div class="modal-header"></div>
<div class="modal-content"></div>
<div class="modal-footer"></div>
</div>
複製程式碼
- modal的頭部,內容,底部都可能定製內容
- 每部分都新增一個slot
- 點選按鈕需要釋出事件
<div class="modal-header">
<slot name='header'>
<h4>{{title}}</h4>
</slot>
</div>
<div class="modal-content">
<slot name="content">在這裡新增內容</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<input
@click="okHandle"
class="btn"
type="button"
:value="okValue"
/>
<input
@click="cancelHandle"
class="btn"
type="button"
:value="cancelValue"
/>
</slot>
</div>
複製程式碼
- 元件完整結構
<script type="text/x-template" id="modal-temp">
<div v-transform-body v-show="value" class="modal-example">
<div class="mask"></div>
<div class="modal">
<div class="modal-header">
<slot name='header'>
<h4>{{title}}</h4>
</slot>
</div>
<div class="modal-content">
<slot name="content">在這裡新增內容</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<input
@click="okHandle"
class="btn"
type="button"
:value="okValue"
/>
<input
@click="cancelHandle"
class="btn"
type="button"
:value="cancelValue"
/>
</slot>
</div>
</div>
</div>
</script>
複製程式碼
- 註冊Modal元件
- 使用props接受引數,並驗證
- 新增監聽事件
Vue.component('Modal',{
props:{
value:{
type: Boolean,
default: false
},
title:{
type: String,
default: '預設標題'
},
okValue:{
type: String,
default: '確定'
},
cancelValue:{
type: String,
default: '取消'
}
},
template: '#modal-temp',
methods: {
okHandle () {
this.$emit('ok-click');
this.$emit('input',false);
},
cancelHandle () {
this.$emit('cancel-click');
this.$emit('input',false);
}
}
})
複製程式碼
- 自定義插入節點到body指令
Vue.directive('transform-body',{
inserted(el){
document.body.appendChild(el);
}
});
複製程式碼
<div id="app">
<button @click="showModal" type="button">顯示modal</button>
<Modal v-model="show" @ok-click="okHandle" @cancel-click="cancelHandle"></Modal>
</div>
new Vue({
el:'#app',
data:{
show: true
},
methods: {
showModal(){
this.show = true;
},
okHandle(){
console.log('點選了確定按鈕')
},
cancelHandle(){
console.log('點選了取消按鈕')
}
}
});
複製程式碼
生命週期函式
-
beforeCreate:資料劫持之前被呼叫,無法訪問methods,data,computed上的方法或資料
-
created:例項已經建立完成之後被呼叫。但掛載階段還沒開始,$el 屬性目前不可見。常用於ajax傳送請求獲取資料
-
beforeMounted:在掛載開始之前被呼叫
-
mounted:vue例項已經掛載到頁面中,可以獲取到el中的DOM元素,進行DOM操作
-
beforeUpdated:更新資料之前呼叫
-
updated:元件 DOM 已經更新
-
beforeDestroy:例項銷燬之前呼叫。在這一步,例項仍然完全可用。
-
destroyed:Vue 例項銷燬後呼叫
-
activated:keep-alive 元件啟用時呼叫
-
deactivated:keep-alive 元件停用時呼叫
限制元素&動態元件
is
Vue 只有在瀏覽器解析、規範化模板之後才能獲取其內容。
像 <ul>、<ol>、<table>、<select> 這樣的元素裡允許包含的元素有限制,而另一些像 <option> 這樣的元素只能出現在某些特定元素的內部。
複製程式碼
<div id="app">
<table>
<custom></custom>
</table>
<table>
<tr is='custom'></tr>
</table>
</div>
Vue.component('custom',{
template: `<tr><td>hello</td></tr>`
});
new Vue({
el: '#app'
});
複製程式碼
- 通過使用保留的 <component> 元素,並對其 is 特性進行動態繫結
var vm = new Vue({
el: '#example',
data: {
currentView: 'home'
},
components: {
home: { /* ... */ },
posts: { /* ... */ },
archive: { /* ... */ }
}
})
<component v-bind:is="currentView">
<!-- 元件在 vm.currentview 變化時改變! -->
</component>
複製程式碼
keep-alive
- 把切換出去的元件保留在記憶體中,可以保留它的狀態或避免重新渲染
- include - 字串或正規表示式。只有匹配的元件會被快取。
- exclude - 字串或正規表示式。任何匹配的元件都不會被快取
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多個條件判斷的子元件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一起使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
複製程式碼