亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

Vue 可拖拽組件Vue Smooth DnD的使用詳解

瀏覽:65日期:2023-02-08 10:03:13
目錄簡介和 Demo 展示API: Container屬性生命周期回調(diào)事件API: Draggable實(shí)戰(zhàn)簡介和 Demo 展示

最近需要有個拖拽列表的需求,發(fā)現(xiàn)一個簡單好用的 Vue 可拖拽組件。安利一下~

Vue Smooth DnD 是一個快速、輕量級的拖放、可排序的 Vue.js 庫,封裝了 smooth-dnd 庫。

Vue Smooth DnD 主要包含了兩個組件,Container 和 Draggable,Container 包含可拖動的元素或組件,它的每一個子元素都應(yīng)該被 Draggable 包裹。每一個要被設(shè)置為可拖動的元素都需要被 Draggable 包裹。

安裝: npm i vue-smooth-dnd

一個簡單的 Demo ,展示組件的基礎(chǔ)用法,實(shí)現(xiàn)了可以拖拽的列表。

<template> <div><div class='simple-page'> <Container @drop='onDrop'><Draggable v-for='item in items' :key='item.id'> <div class='draggable-item'>{{item.data}} </div></Draggable> </Container></div> </div></template><script> import { Container, Draggable } from 'vue-smooth-dnd'; const applyDrag = (arr, dragResult) => {const { removedIndex, addedIndex, payload } = dragResultconsole.log(removedIndex, addedIndex, payload)if (removedIndex === null && addedIndex === null) return arrconst result = [...arr]let itemToAdd = payloadif (removedIndex !== null) { itemToAdd = result.splice(removedIndex, 1)[0]}if (addedIndex !== null) { result.splice(addedIndex, 0, itemToAdd)}return result } const generateItems = (count, creator) => {const result = []for (let i = 0; i < count; i++) { result.push(creator(i))}return result } export default {name: 'Simple',components: { Container, Draggable },data() { return {items: generateItems(50, i => ({ id: i, data: 'Draggable ' + i })) };},methods: { onDrop(dropResult) {this.items = applyDrag(this.items, dropResult); }} };</script><style> .draggable-item {height: 50px;line-height: 50px;text-align: center;display: block;background-color: #fff;outline: 0;border: 1px solid rgba(0, 0, 0, .125);margin-bottom: 2px;margin-top: 2px;cursor: default;user-select: none; }</style>

效果

Vue 可拖拽組件Vue Smooth DnD的使用詳解

API: Container屬性

屬性 類型 默認(rèn)值 描述 :orientation string vertical 容器的方向,可以為 horizontal 或 vertical :behaviour string move 描述被拖動的元素被移動或復(fù)制到目標(biāo)容器。 可以為 move 或 copy 或 drop-zone 或 contain 。move 可以在容器間互相移動,copy 是可以將元素復(fù)制到其他容器,但本容器內(nèi)元素不可變,drop-zone 可以在容器間移動,但是容器內(nèi)元素的順序是固定的。contain 只能在容器內(nèi)移動。 :tag string, NodeDescription div 容器的元素標(biāo)簽,默認(rèn)是 div ,可以是字符串如 tag='table' 也可以是包含 value和 props 屬性的對象 :tag='{value: ’table’, props: {class: ’my-table’}}' :group-name string undefined 可拖動元素可以在具有相同組名的容器之間移動。如果未設(shè)置組名容器將不接受來自外部的元素。 這種行為可以被 shouldAcceptDrop 函數(shù)覆蓋。 見下文。 :lock-axis string undefined 鎖定拖動的移動軸。可用值 x, y 或 undefined。 :drag-handle-selector string undefined 用于指定可以開啟拖拽的 CSS 選擇器,如果不指定的話則元素內(nèi)部任意位置都可抓取。 :non-drag-area-selector string undefined 禁止拖動的 CSS 選擇器,優(yōu)先于 dragHandleSelector. :drag-begin-delay number 0(觸控設(shè)備為 200) 單位毫秒。表示點(diǎn)擊元素持續(xù)多久后可以開始拖動。在此之前移動光標(biāo)超過 5px 將取消拖動。 :animation-duration number 250 單位毫秒。表示放置元素和重新排序的動畫持續(xù)時間。 :auto-scroll-enabled boolean true 如果拖動項目接近邊界,第一個可滾動父項將自動滾動。(這個屬性沒看懂= =) :drag-class string undefined 元素被拖動中的添加的類(不會影響拖拽結(jié)束后元素的顯示)。 :drop-class string undefined 從拖拽元素被放置到被添加到頁面過程中添加的類。 :remove-on-drop-out boolean undefined 如果設(shè)置為 true,在被拖拽元素沒有被放置到任何相關(guān)容器時,使用元素索引作為 removedIndex 調(diào)用 onDrop() :drop-placeholder boolean,object undefined 占位符的選項。包含 className, animationDuration, showOnTop

關(guān)于 drag-class,drop-class 和 drop-placeholder.className 的效果演示

<Container # 省略其它屬性...:animation-duration='1000' # 放置元素后動畫延時drag- drop- :drop-placeholder='{ className: ’drop-preview’, # 占位符的樣式 animationDuration: ’1000’, # 占位符的動畫延遲 showOnTop: true # 是否在其它元素的上面顯示 設(shè)置為false會被其他的拖拽元素覆蓋}'> <!-- 一些可拖拽元素 --> <Draggable>....</Draggable></Container>

類對應(yīng)樣式

.card-ghost { transition: transform 0.18s ease; transform: rotateZ(35deg); background: red !important;}.card-ghost-drop { transition: transform 1s cubic-bezier(0,1.43,.62,1.56); transform: rotateZ(0deg); background: green !important;}.drop-preview { border: 1px dashed #abc; margin: 5px; background: yellow !important;}

實(shí)際效果(我這優(yōu)秀的配色啊)

Vue 可拖拽組件Vue Smooth DnD的使用詳解

生命周期

一次拖動的生命周期通過一系列回調(diào)和事件進(jìn)行描述和控制,下面以包含 3 個容器的示例為例進(jìn)行說明(直接復(fù)制了文檔沒有翻譯,API 詳細(xì)解釋可以看后面介紹。):

Mouse Calls Callback / Event Parameters Notesdown o Initial clickmove o Initial drag | | get-child-payload() index Function should return payload | | 3 x should-accept-drop() srcOptions, payload Fired for all containers | | 3 x drag-start dragResult Fired for all containers | | drag-enter vmove o Drag over containers | | n x drag-leave Fired as draggable leaves container | n x drag-enter Fired as draggable enters container vup o Finish drag should-animate-drop() srcOptions, payload Fires once for dropped container 3 x drag-end dragResult Fired for all containers n x drop dropResult Fired only for droppable containers

請注意,應(yīng)在每次 drag-start 之前和每次 drag-end 之前觸發(fā) should-accept-drop,但為了清晰起見,此處已省略。

其中 dragResult 參數(shù)的格式:

dragResult: { payload,# 負(fù)載 可以理解為用來記錄被拖動的對象 isSource, # 是否是被拖動的容器本身 willAcceptDrop, # 是否可以被放置}

其中 dropResult 參數(shù)的格式:

dropResult: { addedIndex, # 被放置的新添加元素的下標(biāo),沒有則為 null removedIndex, # 將被移除的元素下標(biāo),沒有則為 null payload,# 拖動的元素對象,可通過 getChildPayload 指定 droppedElement, # 放置的 DOM 元素}回調(diào)

回調(diào)在用戶交互之前和期間提供了額外的邏輯和檢查。

get-child-payload(index) 自定義傳給 onDrop() 的 payload 對象。 should-accept-drop(sourceContainerOptions, payload) 用來確定容器是否可被放置,會覆蓋 group-name 屬性。 should-animate-drop(sourceContainerOptions, payload) 返回 false 則阻止放置動畫。 get-ghost-parent() 返回幽靈元素(拖動時顯示的元素)應(yīng)該添加到的元素,默認(rèn)是父元素,某些情況定位會出現(xiàn)問題,則可以選擇自定義,如返回 document.body。事件 @drag-start 在拖動開始時由所有容器發(fā)出的事件。參數(shù) dragResult。 @drag-end 所有容器在拖動結(jié)束時調(diào)用的函數(shù)。 在 @drop 事件之前調(diào)用。參數(shù) dragResult。 @drag-enter 每當(dāng)拖動的項目在拖動時進(jìn)入其邊界時,相關(guān)容器要發(fā)出的事件。 @drag-leave 每當(dāng)拖動的項目在拖動時離開其邊界時,相關(guān)容器要發(fā)出的事件。 @drop-ready 當(dāng)容器中可能放置位置的索引發(fā)生變化時,被拖動的容器將調(diào)用的函數(shù)。基本上,每次容器中的可拖動對象滑動以打開拖動項目的空間時都會調(diào)用它。參數(shù) dropResult。 @drop 放置結(jié)束時所有相關(guān)容器會發(fā)出的事件(放置動畫結(jié)束后)。源容器和任何可以接受放置的容器都被認(rèn)為是相關(guān)的。參數(shù) dropResult。API: Draggable

tag

同容器的 tag 指定可拖拽元素的 DOM 元素標(biāo)簽。

實(shí)戰(zhàn)

實(shí)現(xiàn)一個簡單的團(tuán)隊協(xié)作任務(wù)管理器。

<template> <div class='card-scene'><Containerorientation='horizontal'@drop='onColumnDrop($event)'drag-handle-selector='.column-drag-handle'> <Draggable v-for='column in taskColumnList' :key='column.name'><div class='card-container'> <div class='card-column-header'><span class='column-drag-handle'>&#x2630;</span>{{ column.name }} </div> <Container group-name='col' @drop='(e) => onCardDrop(column.id, e)' :get-child-payload='getCardPayload(column.id)' drag- drop- :drop-placeholder='dropPlaceholderOptions' ><Draggable v-for='task in column.list' :key='task.id'> <div class='task-card'><div class='task-title'>{{ task.name }}</div><div :style='{ background: priorityMap[task.priority].color }'> {{ priorityMap[task.priority].label }}</div> </div></Draggable> </Container></div> </Draggable></Container> </div></template><script> import { Container, Draggable } from 'vue-smooth-dnd'; const applyDrag = (arr, dragResult) => {const { removedIndex, addedIndex, payload } = dragResultconsole.log(removedIndex, addedIndex, payload)if (removedIndex === null && addedIndex === null) return arrconst result = [...arr]let itemToAdd = payloadif (removedIndex !== null) { itemToAdd = result.splice(removedIndex, 1)[0]}if (addedIndex !== null) { result.splice(addedIndex, 0, itemToAdd)}return result } const taskList = [{ name: ’首頁’, priority: ’P1’, status: ’待開發(fā)’, id: 1,},{ name: ’流程圖開發(fā)’, priority: ’P3’, status: ’待評審’, id: 2,},{ name: ’統(tǒng)計圖展示’, priority: ’P0’, status: ’開發(fā)中’, id: 3,},{ name: ’文件管理’, priority: ’P1’, status: ’開發(fā)中’, id: 4,} ] const statusList = [’待評審’, ’待開發(fā)’, ’開發(fā)中’, ’已完成’] const taskColumnList = statusList.map((status, index) => {return { name: status, list: taskList.filter(item => item.status === status), id: index} }) const priorityMap = {’P0’: { label: ’最高優(yōu)’, color: ’#ff5454’,},’P1’: { label: ’高優(yōu)’, color: ’#ff9a00’,},’P2’: { label: ’中等’, color: ’#ffd139’,},’P3’: { label: ’較低’, color: ’#1ac7b5’,}, } export default {name: ’Cards’,components: {Container, Draggable},data () { return {taskColumnList,priorityMap,dropPlaceholderOptions: { className: ’drop-preview’, animationDuration: ’150’, showOnTop: true} }},methods: { onColumnDrop (dropResult) {this.taskColumnList = applyDrag(this.taskColumnList, dropResult) }, onCardDrop (columnId, dropResult) {let { removedIndex, addedIndex, payload } = dropResultif (removedIndex !== null || addedIndex !== null) { const column = taskColumnList.find(p => p.id === columnId) if (addedIndex !== null && payload) { // 更新任務(wù)狀態(tài)dropResult.payload = { ...payload, status: column.name,} } column.list = applyDrag(column.list, dropResult)} }, getCardPayload (columnId) {return index => this.taskColumnList.find(p => p.id === columnId).list[index] },} }</script><style> * {margin: 0;padding: 0;font-family: ’Microsoft YaHei’,’PingFang SC’,’Helvetica Neue’,Helvetica,sans-serif;line-height: 1.45;color: rgba(0,0,0,.65); } .card-scene {user-select: none;display: flex;height: 100%;margin: 20px; } .card-container {display: flex;flex-direction: column;width: 260px;min-width: 260px;border-radius: 12px;background-color: #edeff2;margin-right: 16px;height: calc(100vh - 40px); } .card-column-header {display: flex;height: 50px;margin: 0 16px;align-items: center;flex-shrink: 0;font-weight: 500;font-size: 16px; } .draggable-container {flex-grow: 1;overflow: auto; } .column-drag-handle {cursor: move;padding: 5px; } .task-card {margin: 10px;background-color: white;padding: 15px 10px;border-radius: 8px;box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.12);cursor: pointer;display: flex;justify-content: space-between; } .task-title {color: #333333;font-size: 14px; } .task-priority {width: 60px;line-height: 20px;border-radius: 12px;text-align: center;color: #fff;font-size: 12px; } .card-ghost {transition: transform 0.18s ease;transform: rotateZ(5deg) } .card-ghost-drop {transition: transform 0.18s ease-in-out;transform: rotateZ(0deg) } .drop-preview {background-color: rgba(150, 150, 200, 0.1);border: 1px dashed #abc;margin: 5px; }</style>

效果

Vue 可拖拽組件Vue Smooth DnD的使用詳解

到此這篇關(guān)于Vue 可拖拽組件Vue Smooth DnD的使用詳解的文章就介紹到這了,更多相關(guān)Vue 可拖拽組件內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 国产不卡网 | 国产二区在线播放 | 亚洲精品欧美日本中文字幕 | 在线看成人 | 黄色的视频在线免费观看 | 欧美日韩国产综合视频一区二区三区 | 九九性视频 | 成人卡通精品卡通动漫第一页 | mm1313亚洲国产精品无 | 国产视频在线观看免费 | 国产福利在线 | 本道久久 | 1314亚洲人成网站在线观看 | 中国帅小伙gaysextubevideo | condom色疯狂做受xxxx | 国产精品香蕉在线观看不卡 | 欧美成人亚洲国产精品 | 三级视频网站在线观看播放 | 成人在线观看视频网站 | 你懂的www | 青草视频污 | 黄色一级片视频 | 精品亚洲成a人片在线观看 精品亚洲成a人在线播放 | 国产毛片片精品天天看视频 | 国产网友自拍 | 91刘亦菲精品福利在线 | 98色花堂国产第一页 | 91久久精品国产91久久性色也 | 在线不卡一区二区三区日韩 | 国产 网红 喷水 播放 | 国产精品小黄鸭一区二区三区 | 天天爽影院一区二区在线影院 | 日韩大片免费在线观看 | 亚洲人和日本人jizz | 国产亚洲欧洲精品 | 一级做a爰片久久毛片人呢 一级做a爰片久久毛片毛片 | 欧美日韩一区二区三区自拍 | 麻豆精品永久免费视频 | 中文字幕久久综合伊人 | 精品一区二区久久久久久久网站 | 沟沟人体一区二区 |