首先演示一下最終效果:vue
流暢的拖動和交換位置效果,並實時更新數據 react
支持組件的樣式和內容自定義 git
這是此次系列文章的第一篇,我本身封裝了一個用vue實現的拖拽排列卡片組件,而且發佈到npm,詳細地記錄下來了總體制做過程。總共有三篇文章,介紹組件的製做思路和遇到的問題,以及在發佈到npm上並下載使用的過程當中,發生了什麼問題並如何解決。github
這是vue實現的拖動卡片組件,主要實現了:vue-cli
npm install carddragger
複製代碼
當前穩定版本:0.3.6,更新於10月24日早上11點 npm
在你vue項目的入口js文件中使用,vue-cli生成的項目通常爲main.js文件數組
import {installCardDragger} from 'carddragger'
Vue.use(installCardDragger)
複製代碼
在組件中直接importbash
import { cardDragger } from 'carddragger'
export default {
components:{
cardDragger,
}
}
複製代碼
1.基礎使用:ide
<template>
<cardDragger :data="cardList">
</cardDragger>
</template>
<script>
export default {
data() {
return {
cardList: [{
positionNum: i,
name: "演示卡片"+i,
id: "card"+i,
}],
}
}
}
</script>
複製代碼
2.完整示例:
參照源碼倉庫中的examples
將整個項目clone下來,npm install+npm run serve便可看到完整示例函數
屬性 | 說明 | 類型 | 默認值 |
---|---|---|---|
data | 必填,須要傳入的卡片數據,具體格式請看下方解釋 | Array | - |
colNum | 卡片排列的列數 | Number | 2 |
cardOutsideWidth | 卡片外部須要佔據的寬度(包括無內容部分) | Number | 590 |
cardOutsideHeight | 卡片外部須要佔據的高度(包括無內容部分) | Number | 380 |
cardInsideWidth | 卡片的寬度 | Number | 560 |
cardInsideHeight | 卡片的高度 | Number | 320 |
卡片的內容根據data數據生成或自定義
<template>
<div>
<cardDragger
:data="cardList"
:colNum="4"
:cardOutsideWidth="300"
:cardInsideWidth="260"
:cardOutsideHeight="310"
:cardInsideHeight="240"
/>
<!-- 上面的屬性均可自定義 -->
</div>
</template>
<script>
export default {
data(){
return{
cardList: [
{
positionNum: 2,
name: "測試卡片2",
id: "card2",
}
]
}
}
}
</script>
複製代碼
屬性 | 說明 | 類型 | 默認值 |
---|---|---|---|
id | 必填,設置卡片的id做爲惟一識別 | String | - |
positionNum | 必填,設置卡片位置,從1開始依次遞增 | Number | - |
name | 選填,設置卡片的標題名稱 | String | '默認標題' |
componentData | 選填,設置卡片的內容爲組件數據,若是此參數具備數據的話,則slot傳入的數據失效 | 組件 | - |
首先先介紹一下,卡片內容分爲上下兩部分:
兩個部分都是能夠進行自定義內容及樣式的。若不添加的自定義內容的話,標題欄和內容都是默認背景爲白色,顯示data中的name。若添加了自定義內容則背景須要本身設置。
<cardDragger :data="cardList" >
<!-- 在組件中間插入template並設置 v-slot:header="slotProps"
header爲標題欄的插槽名字,在裏面的內容會渲染到你每個卡片標題欄上
slotProps爲從子組件返回的數據,及data數組裏面的每個對象數據-->
<template v-slot:header="slotProps">
<!-- 自定義內容 -->
<div class="topMenuBox" >
<div class="menuTitle" v-if="slotProps.item.name">{{slotProps.item.name}}</div>
<div class="menuTitle" v-else> 默認標題 </div>
</div>
</template>
</cardDragger>
複製代碼
<cardDragger :data="cardList">
<!-- 與標題欄插槽一致,但須要注意v-slot:content-->
<template v-slot:content="slotProps">
<div class="insideData">
{{slotProps.item.name}}
</div>
</template>
</cardDragger>
複製代碼
你也能夠
<cardDragger :data="cardList">
<!-- 與標題欄插槽一致,但須要注意v-slot:content-->
<template v-slot:content="slotProps">
<component :is="slotProps.item.OtherData"></component>
<!--這裏用到的是vue的動態組件功能動態渲染組件,可傳入更多屬性至子組件 -->
</template>
</cardDragger>
//省略部分代碼,加載你的組件
import exampleChild1 from "./childComponent/exampleChild1"
cardList: [
{
positionNum: 1,
name: "演示卡片1",
id: "card1",
OtherData:exampleChild1
//OtherData這個是你本身定義的屬性,注意不可與componentData屬性名字重複
}
]
複製代碼
關於內容我作了另一個判斷,你能夠將須要的組件放在data的componentData屬性裏面,內容會自動讀取componentData的數據。固然你直接都使用slot就能夠忽略這個屬性。
import exampleChild1 from "./childComponent/exampleChild1"
//省略部分代碼
cardList: [
{
positionNum: 1,
name: "演示卡片1",
id: "card1",
componentData:exampleChild1 //直接設置便可使用
}
]
//使用componnetData屬性傳入的組件,可以使用Props獲取到單個卡片數據
//在子組件中使用props便可使用
props:{
itemData:{
type:Object
}
}
複製代碼
渲染優先級:data的componentData > slot > 默認內容
做用:
在點擊卡片頂部標題欄的時候,觸發此函數
參數:
startDrag(event,id)第一個參數event,是點擊事件的原生event
第二個參數id,是選中的卡片的id
做用:
在拖動一個卡片到另一個卡片的位置的時候,觸發此事件
參數:
swicthPosition(oldPositon,newPositon,originItem)第一個參數oldPositon,是卡片原來的位置號碼
第二個參數newPositon,是卡片須要交換的位置號碼
第三個參數originItem,是卡片交換完成後的數據
做用:
拖拽完成鬆開鼠標後,觸發此事件
參數:
swicthPosition(oldPositon,newPositon,originItem)第一個參數oldPositon,是卡片原來的位置號碼
第二個參數newPositon,是卡片須要交換的位置號碼
第三個參數originItem,是卡片交換完成後的數據
1.data的positionNum出現空缺則會報錯,必須從1依次遞增。但好像這種場景也不經常使用,考慮修復ing。
以爲這個系列有點意思的話,點個贊支持一下唄!