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

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

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

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

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

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

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

安裝: npm i vue-smooth-dnd

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

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

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

類對(duì)應(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的使用詳解

生命周期

一次拖動(dòng)的生命周期通過一系列回調(diào)和事件進(jìn)行描述和控制,下面以包含 3 個(gè)容器的示例為例進(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

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

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

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

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

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

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

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

tag

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

實(shí)戰(zhàn)

實(shí)現(xiàn)一個(gè)簡(jiǎn)單的團(tuán)隊(duì)協(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: ’待評(píng)審’, id: 2,},{ name: ’統(tǒng)計(jì)圖展示’, priority: ’P0’, status: ’開發(fā)中’, id: 3,},{ name: ’文件管理’, priority: ’P1’, status: ’開發(fā)中’, id: 4,} ] const statusList = [’待評(píng)審’, ’待開發(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)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 伊人焦久影院 | 91短视频社区在线观看 | 精品一成人岛国片在线观看 | 欧美黄色大片网站 | 日韩免费黄色片 | 韩国一级毛片大全女教师 | 久久久久女人精品毛片九一 | 国内精品九一在线播放 | 成人在线观看国产 | 亚洲一区区 | 99久久99这里只有免费的精品 | 国产一级黄色大片 | 91久久线看在观草草青青 | 国产美女久久久 | 岛国在线123456 | 免费a级在线观看完整片 | 一级毛片aa高清免费观看 | 国产成人在线观看网站 | 国产成人免费视频 | 国产福利专区 | 长腿美女校花宿舍嗷嗷嗷大叫 | 中文字幕成人乱码在线电影 | 国产一区二三区 | 国产成人精品一区二三区2022 | 久久精品国产福利国产琪琪 | 精品视频麻豆入口 | 国产在线观看第一页 | 美国一级特黄aa大片 | 欧美精品日本一级特黄 | 青草视频在线观看免费资源 | 日韩综合在线视频 | 亚洲精品国产一区二区三区在 | 国产午夜在线观看 | 色香婷婷| 激情小视频在线播放免费 | 33333在线亚洲 | 国产精品久久久久久久网站 | 国产欧美日韩一区 | 色伊人色成人婷婷六月丁香 | 婷婷综合社区 | 亚洲日本中文字幕在线2022 |