概述
vue
元件是vue
常用的功能,vue
也因為強大的元件功能得到很多開發者的青睞。一個好的元件,可以提供給開發者很多方便,特別是複用程式碼,程式碼一致性等。
本文通過實現一個列表my-list
元件,來講解元件的用法和特性。
下面先看一下工程目錄:
整個工程可以在git上下載:點選下載,其中藍色線條標記的,分別是我們這次用到的頁面和元件。
元件引入
元件引入分全域性引入和區域性引入,顧名思義,全域性引入可以在任何一個路由頁面使用該元件,而區域性引入是在引入頁面才能使用。
import myList from '../components/my-list'
//全域性引入
Vue.component('my-list',myList)
export default {
name: "componentStudy",
data: function () {
return {}
},
//區域性引入,寫法很靈活
components:{myList},
methods: {},
mounted: function () {
},
computed: {},
created: function () {
}
}
複製程式碼
上面的程式碼的2中寫法分別是全域性引入和區域性引入,整體來說,像分頁元件,下拉框元件,表格元件等大多數頁面都用得上的可以全域性引入,像tab頁面,特殊按鈕等用的比較的少的頁面可以採用區域性引用。
元件傳值
我們的列表元件,各個頁面的資料不一樣,這些資料往往是通過引入改元件的頁面決定的,那麼意味著,這些資料應該是從父元件傳到子元件的,下面我們給我們的列表元件傳一個dataList
(資料)和一個clickFunction
(點選每一項的觸發函式)。vue
通過prop
子元件傳值,這裡傳值可以是js
所有型別。
//檔案componentSutdy.vue
<my-list :data-list="dataList" :click-fun="clickFunction"></my-list>
data: function () {
return {
dataList:[
{title:'攜手打造更加緊密的中非命運共同體',content:'9月3日,2018年中非合作論...'},
{title:'“小眼鏡”牽動大情懷',content:'近日,習近平總書記就青少年視力健...'},
{title:'倡議五週年之際',content:'2013年9月7日,國家主席習...'},
]
}
},
methods: {
clickFunction(item){
console.log(item)
}
},
//檔案my-list.vue
<template>
<div class="my-list">
<ul>
<li class="list-group-item" v-for="(item,index) in dataList" @click="clickFun(1)">
<div class="main-title" v-text="item.title"></div>
<div class="content" v-text="item.content"></div>
</li>
</ul>
</div>
</template>
//子元件接收父元件傳過來的值
props:{
dataList:{
type:[Array,Object], // 型別校驗,多個可能的型別
require:true, //是否必傳
default:function () { //預設值, 物件或陣列預設值必須從一個工廠函式獲取
return []
},
// //自定義校驗
// validator: function (value) {
// // 這個值必須匹配下列字串中的一個
// return ['success', 'warning', 'danger'].indexOf(value) !== -1
// }
},
clickFun:{
type: Function,
require: false
}
},
複製程式碼
可以看到,子元件使用
propos
接收了父元件傳過來的dataList
和clickFun
2個變數。注意傳遞形式就是vue常見語法v-bind來傳遞。試著點選列表,可以看到父元件的方法cliFun被呼叫了,並且接收到了子元件傳過來的變數。 上面的例子,完成了父元件向子元件傳遞引數,子元件呼叫父元件方法。
子元件呼叫父元件方法
和其他框架一下,vue在子元件無法直接通過this.的方式調到父元件的方法,這裡vue提供的是$emit的方式來呼叫父元件的方法。我們修改上面的例子,讓子元件點選按鈕來刪除一個列表,這裡值得注意的是,vue元件直接傳遞引數是單向的,意思是,父元件傳遞過去的變數,只能在父元件被改變子元件是不能改變父元件傳過來的這個變數的。不過可以通過賦值、計算屬性等方式來重新定義一個變數。 修改部分的程式碼:
//檔案componentSutdy.vue
//新增了@deleteItem的繫結
<my-list :data-list="dataList" :click-fun="clickFunction" @deleteItem="removeItem"></my-list>
//方法裡面新增執行函式
removeItem(index){
this.dataList.splice(index,1)
}
//檔案my-list.vue
//新增了$emit('deleteItem',index)"執行函式
<li class="list-group-item" v-for="(item,index) in dataList" @click="clickFun(1)">
<div class="main-title" v-text="item.title"></div>
<div class="content" v-text="item.content"></div>
<i class="el-icon-delete" @click="$emit('deleteItem',index)"></i>
</li>
複製程式碼
設定點選刪除按鈕,順利刪除了一行,可以看到,我們在父元件通過
deleteItem
傳遞了removeItem
函式給子元件,子元件通過$emit('deleteItem',index)
順利調到了父元件的函式,並且傳遞了一個引數,父元件通過這個引數刪除了使用者點選的資料,這個過程完成了欄位就呼叫父元件的方法,也說明了,子元件不要直接改變父元件傳遞過來的引數,因為這裡是單向繫結的。 值得注意的是,欄位就呼叫父元件的函式,有2種方式,穩重第一種是通過prop傳遞,第二種是通過@繫結來傳遞的,實際使用過程中,建議使用第二種方式。
父元件呼叫子元件方法
很多時候,我們需要欄位就來執行某種操作,來達到頁面效果,比如說,我們需要在使用者點選之後,改變列表顏色,來切換主題。
//檔案componentSutdy.vue,關鍵程式碼
<my-list :data-list="dataList" ref="myList" :click-fun="clickFunction" @deleteItem="removeItem"</my-list>
<el-button @click="changeTheme" style="margin-top: 20px;">切換主題</el-button>
changeTheme(){
this.$refs.myList.changeColor()
},
//檔案my-list.vue,關鍵程式碼
<li class="list-group-item" :class="{'has-bg':isChange}" v-for="(item,index) in dataList" @click="clickFun(1)">
<div class="main-title" v-text="item.title"></div>
<div class="content" v-text="item.content"></div>
<i class="el-icon-delete" @click="$emit('deleteItem',index)"></i>
</li>
changeColor(){
this.isChange = true
}
複製程式碼
點選按鈕,順利改變了列表的背景顏色。這裡,在引用元件的時候,我們通過
ref
給元件新增了一個命名:myList
,父元件點選切換主題,執行this.$refs.myList.changeColor()
,子元件changeColor
方法被呼叫,最終實現了轉換主題,這裡元件能單獨命名,意味著同一個頁面可以引用同一個元件多次,通過不同的命名,來單獨操作,互不影響。
元件插槽
元件插槽是為了元件能有更靈活的使用,能讓主頁面在適當的字元插入自定義的html片段,先看一張圖
我們想給每一行新增一個序號並且加粗,如果是元件裡面固定的html結構,和明顯難以實現,這裡我們需要用到slot插槽功能。//檔案componentSutdy.vue,關鍵程式碼
<my-list :data-list="dataList" ref="myList" :click-fun="clickFunction" @deleteItem="removeItem">
<template slot="title" slot-scope="{item,index}">
<div>
<span v-text="`${index + 1}.`" style="font-weight: bold"></span>
<span v-text="item.title"></span>
</div>
</template>
</my-list>
//檔案my-list.vue,關鍵程式碼
<li class="list-group-item" :class="{'has-bg':isChange}" v-for="(item,index) in dataList" @click="clickFun(1)">
<slot name="title" :item="item" :index="index">
<div class="main-title" v-text="item.title"></div>
</slot>
<div class="content" v-text="item.content"></div>
<i class="el-icon-delete" @click="$emit('deleteItem',index)"></i>
</li>
複製程式碼
可以看到,我們在子頁面,新增了
name="title"
的slot
插槽,並且通過繫結資料的方式傳遞了2個引數,item,index
,父元件,<template slot="title" slot-scope="{item,index}">
通過sole與欄位就name匹配,來將html程式碼插入到對應的位置。這樣主頁面就輕鬆定製了新聞列表標題欄的html結構,當主頁面不引入插槽是,將使用預設的html解析。這裡接收引數的方式是採用es205的解構語法。
總結:關於vue元件就將到這裡,相信上面的類容能涵蓋到大多數用法,還有部分動態元件和非同步元件不作講解,實際使用中,用到很少,整個程式碼的原始碼可以在git:github.com/jackzhujie/… 最後想檢視更多文章,可以關注我的個人公眾號: