50天50個小項目 (Vue3 + Tailwindcss V4) ? | DragNDrop(拖拽占用組件)

📅 我們繼續 50 個小項目挑戰!—— DragNDrop組件

倉庫地址:https://github.com/SunACong/50-vue-projects

項目預覽地址:https://50-vue-projects.vercel.app/

在這里插入圖片描述


使用 Vue 3 的 Composition API 和 <script setup> 語法結合 TailwindCSS 構建一個支持拖拽交互的圖片拖放組件。該組件允許用戶將一張圖片從一個容器拖動并釋放到另一個“空位”中,并帶有視覺反饋(如懸停高亮、背景變化等)。

🎯 組件目標

  • 創建多個“空位”容器
  • 默認展示一張可拖動的圖片
  • 支持拖拽交互并投放到任意空位
  • 投放后更新對應位置的圖片狀態
  • 拖拽過程中提供視覺反饋(如懸停樣式)
  • 使用 TailwindCSS 快速構建現代 UI 界面

?? 技術實現點

技術點描述
Vue 3 Composition API (<script setup>)使用響應式變量管理組件狀態
ref 響應式變量控制當前圖片所在索引與懸停狀態
v-for 循環渲染動態生成多個容器
@dragstart, @dragend, @dragover, @drop 等事件實現完整的拖拽交互邏輯
TailwindCSS 條件類綁定根據狀態動態應用樣式
:style 動態綁定背景圖展示圖片資源

🧱 組件實現

模板結構 <template>

<template><div class="flex h-screen items-center justify-center overflow-hidden bg-sky-500"><!-- 多個空位容器 --><divv-for="(empty, index) in empties":key="index":class="['m-2 h-36 w-36 border-4 border-black bg-white',isHovered[index] && 'border-dashed border-black bg-gray-800',]"@dragover.prevent="dragOver"@dragenter.prevent="dragEnter(index)" @dragleave="dragLeave(index)"@drop="dragDrop(index)"><!-- 當前圖片所在的容器 --><divv-if="index === filledIndex"class="h-full w-full cursor-pointer bg-cover":style="{ backgroundImage: `url(${imageUrls[index]})` }"draggable="true"@dragstart="dragStart"@dragend="dragEnd"></div></div></div>
</template>

腳本邏輯 <script setup>

<script setup>
import { ref } from 'vue'const filledIndex = ref(0)
const isHovered = ref(Array(5).fill(false))// 用于循環生成 5 個空位容器
const empties = Array.from({ length: 5 }, (_, index) => index)// 圖片地址數組
const imageUrls = ['https://picsum.photos/id/10/150/150','https://picsum.photos/id/11/150/150','https://picsum.photos/id/12/150/150','https://picsum.photos/id/13/150/150','https://picsum.photos/id/14/150/150',
]// 拖拽開始
const dragStart = () => {// 可添加 hold 效果或數據存儲
}// 拖拽結束
const dragEnd = () => {// 可添加恢復效果
}// 鼠標懸停時觸發
const dragOver = () => {}// 進入容器時觸發
const dragEnter = (index) => {isHovered.value[index] = true
}// 離開容器時觸發
const dragLeave = (index) => {isHovered.value[index] = false
}// 投放操作
const dragDrop = (index) => {filledIndex.value = indexisHovered.value = Array(5).fill(false)
}
</script>

自定義樣式 <style scoped>

<style scoped>
[draggable='true'] {transition: all 0.2s ease;
}
</style>

🔍 重點效果實現

? 拖拽交互邏輯詳解

1. 拖拽開始:dragStart

當用戶點擊并開始拖動圖片時,會觸發 dragStart 方法。你可以在這里做一些準備操作,例如記錄當前拖動的數據。

2. 拖拽進入容器:dragEnter(index)

當鼠標帶著元素進入某個容器時,我們通過傳入 index 設置該容器的懸停狀態為 true,從而激活其高亮樣式。

3. 拖拽離開容器:dragLeave(index)

當鼠標離開容器時,設置該容器的懸停狀態為 false,恢復默認樣式。

4. 投放完成:dragDrop(index)

這是整個拖拽流程的核心,它負責更新 filledIndex,將圖片移動到新的容器,并重置所有懸停狀態。


💡 視覺反饋機制

我們使用了一個布爾數組 isHovered 來保存每個容器是否被懸停:

const isHovered = ref(Array(5).fill(false))

并通過 v-if="index === filledIndex" 判斷哪個容器應該顯示圖片,其他則為空白容器。

TailwindCSS 中根據這個狀態來切換樣式:

:class="['m-2 h-36 w-36 border-4 border-black bg-white',isHovered[index] && 'border-dashed border-black bg-gray-800',
]"

🖼? 圖片動態加載

使用了 :style 來動態設置背景圖:

:style="{ backgroundImage: `url(${imageUrls[index]})` }"

每張圖片都來自 Picsum Photos 提供的隨機圖片服務,確保每次運行都能看到不同的內容。


🎨 TailwindCSS 樣式重點講解

類名作用
h-screen, items-center, justify-center全屏高度 + 內容居中布局
overflow-hidden防止內容溢出
bg-sky-500設置背景顏色為淺藍色
h-36, w-36設置每個容器的寬高為 36(9rem)
m-2設置外邊距為 2(0.5rem)
border-4, border-black黑色邊框
bg-white / bg-gray-800默認和懸停狀態下的背景顏色
border-dashed懸停時邊框變為虛線
cursor-pointer設置圖片區域為可點擊
bg-cover圖片背景自適應填充
transition添加拖拽過程中的平滑過渡動畫

📁 常量定義 + 組件路由

constants/index.js 添加組件預覽常量:

{id: 21,title: 'Drag N Drop',image: 'https://50projects50days.com/img/projects-img/21-drag-n-drop.png',link: 'DragNDrop',},

router/index.js 中添加路由選項:

{path: '/DragNDrop',name: 'DragNDrop',component: () => import('@/projects/DragNDrop.vue'),},

📁 擴展功能建議

進一步擴展的功能推薦:

  • ? 支持多張圖片同時拖動
  • ? 支持圖片預覽拖拽(不立即改變原圖位置)
  • ? 拖拽時高亮目標容器邊界
  • ? 支持觸摸設備拖拽交互(移動端適配)
  • ? 封裝為可復用組件(支持 props 傳入圖片列表)

🏁 總結

👉 下一篇,我們將完成DrawApp組件,創建一個畫板具有調節畫筆粗細的功能,并且能夠一鍵清除畫板上的內容。🚀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87272.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87272.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87272.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

springboot應用即使使用了連接池,MySQL數據庫仍然有大量sleep狀態的連接

springboot應用即使使用了連接池&#xff0c;MySQL數據庫仍然有大量sleep狀態的連接 問題背景概念理解MySQL配置參數wait_timeout概念Hikari配置參數&#xff08;項目使用hikari作為數據庫連接池&#xff09; 實踐出真知總結和解決思路 問題背景 近期客戶生產環境報&#xff1…

windows下安裝和使用git

本文為windows下git的下載安裝和使用。 git下載和安裝 參考&#xff1a; windows安裝git&#xff08;全網最詳細&#xff0c;保姆教程&#xff09;-CSDN博客 【學了就忘】Git介紹 — 4.Git的安裝 - 簡書 先解決下載時的一些疑惑&#xff1a; 選擇哪個架構&#xff1f; 電腦ARM6…

借助工具給外語視頻加雙語字幕的實用指南?

給外語視頻配上雙語字幕&#xff0c;能讓不同語言背景的觀眾更輕松理解內容&#xff0c;也能讓視頻在傳播時更受歡迎。現在有不少智能工具能幫我們高效完成這項工作&#xff0c;比如 ViiTor AI 平臺&#xff0c;它在處理雙語字幕方面有不少實用功能&#xff0c;下面就結合其功能…

Claude 4 與 Gemini 2.5 Pro:開發者深度比較

Claude 4 與 Gemini 2.5 Pro&#xff1a;開發者深度比較 在使用相同的編碼挑戰對Claude Sonnet 4和Gemini 2.5 Pro Preview進行廣泛的正面測試后&#xff0c;我發現了每個開發人員都應該了解的顯著性能差異。我的發現揭示了執行速度、成本效率以及最重要的&#xff0c;精確執行…

怎么進入9870端口

在實驗時想進入9870端口查看safe狀態 但是輸入localhost:9870后顯示&#xff1a; 首先使用jps確認hadoop狀態&#xff1a; 從 jps 的輸出來看&#xff0c;Hadoop 的核心服務&#xff08;NameNode、DataNode、ResourceManager、NodeManager 等&#xff09;都已經正常運行&…

Windows、Linux、macOS 三大系統安裝 Git 的常見坑點及解決方案,附帶 具體操作示例,幫助新手快速避坑

以下是 Windows、Linux、macOS 三大系統安裝 Git 的常見坑點及解決方案,附帶 具體操作示例,幫助新手快速避坑。 一、Windows 系統安裝 Git 1. 安裝路徑含空格或中文 坑點:默認路徑 C:\Program Files\Git 可能導致某些腳本報錯。 解決:自定義路徑(如 D:\DevTools\Git)。…

OpenAI最新 GPT-4.1 、 GPT-4.1 mini 和 GPT-4.1 nano 新模型如何在ChatGPT付費創作系統平臺對接API使用

GPT-4.1 ?是 OpenAI 于2025年4月15日發布的最新語言模型系列&#xff0c;包括 GPT-4.1 、 GPT-4.1 mini 和 GPT-4.1 nano 三款新成員。這些模型在編程、指令遵循和長上下文理解方面表現出色&#xff0c;支持最大可達100萬個Token的上下文窗口&#xff0c;適用于處理復雜任務和…

計算機網絡(三)傳輸層TCP

目錄 一、TCP概述? 二、TCP三大核心特性 三、 對比UDP?? &#xff08;1&#xff09;TCP、UDP對比 &#xff08;2&#xff09;TCP、UDP頭部格式: &#xff08;3&#xff09;應用場景 ? 四、TCP的三次握手、四次揮手 &#xff08;1&#xff09;三次握手&#xff08;建…

Spring、SpringBoot 本身為什么不提供 Bean 的異步初始化

這是一個很有深度的架構問題&#xff01;Spring/Spring Boot 本身為什么不直接提供 Bean 的異步初始化&#xff1f; 下面從原理、歷史、設計哲學、技術挑戰、社區現狀等多個層面為你詳細分析。 一、Spring Bean 初始化的默認行為 Spring IoC 容器在啟動時&#xff0c;會同步地…

第十三節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 - 接口操作審計日志功能

Vben5 系列文章目錄 ?? 基礎篇 ? 第一節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 ? 第二節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 - Python Flask 后端開發詳解(附源碼) ? 第三節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入…

AI掌柜失守記:AI Agent商業自動化邊界實驗

1. 實驗設計&#xff1a;數字掌柜接管實體貨架 1.1 硬件載體與虛擬人格構建 位于舊金山的實驗場地被改造成微型零售生態系統&#xff1a;智能冰箱搭配商品籃構成實體貨架&#xff0c;iPad自助結賬系統連接Venmo支付接口&#xff0c;Slack通訊平臺成為人機交互窗口。Claude So…

NAT 打洞

本文基于NAT3NAT3實現upd打洞&#xff08;假設你對NAT類型已經很清楚&#xff09; 如果A網絡的NATAB網絡的NATB的值大于6則打洞會失敗&#xff0c;需要使用turn中繼服務 STUN協議解析 #pragma once #include "hv/UdpClient.h" #include "fmt/format.h" /*…

java近期工作總結

近期工作中的一些總結 &#xff08;1&#xff09;三層模板和流程 我發現很多東西其實吧&#xff0c;三層就是一個模板和流程&#xff1b; 正向推&#xff0c;從控制層開始&#xff0c;反向從內個sql開始寫&#xff0c;大部分應該就是從xml文件開始的&#xff0c;然后寫到控制層…

vue中的torefs

在 Vue 中&#xff0c; toRefs(state) 的返回值是一個 新對象&#xff0c;其中每個屬性都是對應 state 中原始屬性的 ref 對象。具體來說&#xff1a; 返回值的結構與特性 1. 對象結構 - 若輸入 state 為 { a: 1, b: text } &#xff0c;則 toRefs(state) 返回&a…

可編程邏輯器件的演進與對比分析

可編程邏輯器件的演進與對比分析 目錄 離散邏輯芯片與早期PLD的限制CPLD的誕生與結構特點FPGA的架構創新CPLD與FPGA的核心差異總結 1. 離散邏輯芯片與早期PLD的限制 在還沒有發明出可編程邏輯器件&#xff08;PLD: Programmable Logic Device&#xff09;之前&#xff0c;設…

Ubuntu機器開啟root用戶遠程登錄

一般正常情況是可以直接使用非root用戶登錄&#xff0c;但是由于權限問題&#xff0c;所以部分內容需要遠程ROOT用戶登錄&#xff0c;具體如下&#xff1a; 1??配置root用戶密碼 一般情況下系統中root不能直接登錄&#xff0c;所以也沒有保存root密碼&#xff0c;現在需要登…

rockchip android14 設置不休眠

rockchip android14 設置不休眠 文章目錄 rockchip android14 設置不休眠前言一、代碼路徑二、代碼修改前言 在rk 的android14代碼中設置開機后永不休眠 一、代碼路徑 device/rockchip/common/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml二、…

什么是數據孤島?如何解決數據孤島問題?

目錄 一、數據孤島的定義與表現 1. 數據孤島的定義 2. 數據孤島的表現形式 二、數據孤島產生的原因 1. 技術層面 2. 組織管理層面 3. 業務流程層面 三、數據孤島帶來的危害 1. 對企業決策的影響 2. 對業務運營效率的影響 3. 對數據治理和安全的影響 四、解決數據孤…

自定義Cereal XML輸出容器節點

自定義Cereal XML輸出容器節點 CEREAL_SERIALIZE_INTRUSIVE 在 1.優化Cereal宏 一行聲明序列化函數 QString、QVector、QList、QMap序列化在2.在Cereal中支持Qt容器序列化 靜態成員函數type_node檢測在 3.利用SFINAE檢測成員函數 &#x1f680; 告別value0&#xff1a;自定義Ce…

Spark 寫入hive表解析

FileOutputCommitter中提交mapreduce.fileoutputcommitter.algorithm.version有v1和v2兩個版本。 v1版本Spark寫入文件的流程&#xff1a; 1.當task完成的時候&#xff0c;會將task的結果文件先寫入到臨時目錄下面。 2.所有的task完成后&#xff0c;將所有的結果文件寫入到結…