記錄--Vue3問題:如何實現組件拖拽實時預覽功能?

来源:https://www.cnblogs.com/smileZAZ/archive/2023/12/22/17922167.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 1. 需求分析 實現一個CMS內容管理系統,在後臺進行內容編輯,在官網更新展示內容。 關於後臺的編輯功能,大致分為兩部分:組件拖拽預覽、組件內容編輯實時預覽。 對於組件拖拽預覽,用戶可以在含有各種功能組件的列表中,選擇需要的組件進行拖拽。 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

1. 需求分析

實現一個CMS內容管理系統,在後臺進行內容編輯,在官網更新展示內容。

關於後臺的編輯功能,大致分為兩部分:組件拖拽預覽組件內容編輯實時預覽

對於組件拖拽預覽,用戶可以在含有各種功能組件的列表中,選擇需要的組件進行拖拽。將組件拖拽到預覽畫布中後,可以在畫布中預覽組件的內容。

對於組件內容編輯實時預覽,用戶可以點擊編輯按鈕,顯示對應組件的內容編輯信息。當修改組件內容時,在畫布中可以實時預覽組件的變化。

2. 實現步驟

2.1 關於拖拽組件庫的選擇

關於拖拽組件庫,在github上有很多,最熱門的當屬vuedraggable這個庫。

它基於Sortable.js,擁有完整的中文文檔,所以很多朋友在做拖拽功能時,都會優先考慮它。

但是,我在使用的過程中,在組件拖拽、取消組件拖拽這裡,遇到了一些小問題。不知道是我操作的問題,還是庫本身存在BUG,所以最終沒有選用它。

於是我發現了,一個更加好用的拖拽庫vue-draggable-next

它的出現是參考了vuedraggable這個庫,所以說很多用法很相似,但是使用起來較之更加友善。總結為一個詞,自由。

下麵我們的拖拽功能實現,就是利用了vue-draggable-next這個庫。

如果你對拖拽底層原理感興趣,並且有空餘時間,勞請閱至第三部分拖拽原理總結。

2.2 拖拽功能代碼實例

 

模版和邏輯中代碼都分為了三部分:組件列表預覽畫布內容編輯

佈局時,樣式根據需求自定義,此處只是提供了功能的基本邏輯實現。

使用時,關於拖拽組件的需求,根據文檔中提供的屬性和事件的描述,靈活配置完善。

vue-draggable-next庫文檔地址:https://github.com/anish2690/vue-draggable-next

安裝依賴:

npm install vue-draggable-next
//or
yarn add vue-draggable-next

模板代碼:

<template>
  <div style="display: flex;cursor: pointer;">
    <!-- 組件列表 左側 -->
    <div style="width:30vw;padding:30px;height:300px;border: 1px solid #000;text-align: center">
      <h1>組件列表</h1>
      <VueDraggableNext :list="componentNameList" :group="{ name: 'people', pull: 'clone', put: false }" :sort="false">
        <div v-for="element in componentNameList" :key="element.name">
          <div style="padding: 10px;background: #ccc;margin-bottom: 10px">
            <el-button> {{ element.name }}</el-button>
          </div>
        </div>
      </VueDraggableNext>
    </div>

    <!-- 預覽畫布 中間 -->
    <div style="width:30vw;padding:30px;height:300px;border: 1px solid #000;text-align: center">
      <h1>預覽畫布</h1>
      <VueDraggableNext :list="componentList" group="people" :sort="false">
        <div v-for="(element, index) in componentList" :key="element.name">
          <div>
            <el-button @click="changeComponent(element)" size="small">編輯</el-button>
            <el-button @click="deleteComponent(index)" size="small">刪除</el-button>
          </div>
          <component :is="element.component" :details="element.details"></component>
        </div>
      </VueDraggableNext>
    </div>

    <!-- 內容編輯 右側 -->
    <div style="width:30vw;padding:30px;height:300px;border: 1px solid #000;text-align: center">
      <h1>內容編輯</h1>
      <div v-for="(nowDetails, index) in nowComponentDetail.details" :key="index">
        {{ nowDetails.key }}: <el-input clearable v-model="nowDetails.value" />
      </div>
    </div>
  </div>
  
</template>
邏輯代碼:
 
<script setup>
import {markRaw, reactive, ref, watch, nextTick} from "vue";
// 引入需要拖拽的組件
import About from "@/views/AboutView.vue"
// 引入拖拽庫
import { VueDraggableNext } from "vue-draggable-next";

// 組件列表數據
const componentNameList = [
  {
    // 組件ID
    componentId:0,
    // 組件名
    name:'關於組件',
    // 組件描述
    description: '關於組件',
    // 組件信息
    component: markRaw(About),
    // 組件需要編輯內容
    details: About.props.details.default
  },
  {
    componentId:1,
    name:'關於組件1',
    description: '關於組件1',
    component:markRaw(About),
    details: About.props.details.default
  },
];


// 預覽畫布數據
let componentList = reactive([]);

watch(componentList, () => {
  console.log(componentList, 'componentList')
})



// 畫布中刪除的點擊事件
const deleteComponent = (index) => {
  componentList.splice(index, 1);
};

// 內容編輯數據
let nowComponentDetail = ref({});

// 畫布中編輯的點擊事件
const changeComponent = (element) => {
    nowComponentDetail.value = element;
};
</script>

2.3 功能組件代碼實例(參考)

此處提供了組件列表中,任意功能組件的編寫實例,組件的具體功能根據需求自定義。特別註意,組件Propsdetails對象屬性的結構寫法,要靈活應用。模版代碼:

<template>
  <div style="padding: 10px;background: pink;margin-bottom: 10px">
    {{ props.details.content }}
  </div>
</template>

邏輯代碼:

<script setup>
import { defineProps } from "vue";

const props = defineProps({
    details: {
      type: Object,
      default: {
        content: {
          key: '內容',
          value: "我是About",
        },
    }
  }
})
</script>

3. 問題詳解

3.1 拖拽實現的底層原理

拖拽的實現原理可以簡單描述為以下幾個步驟:

  • 觸發拖拽:通過監聽滑鼠或觸摸事件,當用戶按下滑鼠左鍵或觸摸屏幕時,表示開始拖拽操作。
  • 記錄拖拽信息:在拖拽開始時,記錄拖拽起始位置(滑鼠或觸摸點的坐標),以及需要拖拽的元素的初始位置(相對於文檔的坐標)。
  • 更新拖拽元素位置:在拖拽過程中,通過監聽滑鼠移動或觸摸滑動事件,計算滑鼠或觸摸點的當前位置,並根據滑鼠或觸摸點的位置變化,更新拖拽元素的位置。這可以通過修改元素的 CSS 屬性(如 left 和 top)或使用 CSS 變換(如 translateX 和 translateY)來實現。
  • 處理拖拽結束:當用戶釋放滑鼠左鍵或觸摸結束時,表示拖拽結束。此時可以執行一些操作,如更新拖拽元素的最終位置、觸發事件或回調函數等。

以下是拖拽實現的基本原理代碼實例:

// 獲取拖拽元素
const draggableElement = document.getElementById('draggable');

// 記錄拖拽起始位置和拖拽元素的初始位置
let startX, startY, initialX, initialY;

// 監聽滑鼠按下事件
draggableElement.addEventListener('mousedown', dragStart);
draggableElement.addEventListener('touchstart', dragStart);

// 監聽滑鼠移動事件
document.addEventListener('mousemove', drag);
document.addEventListener('touchmove', drag);

// 監聽滑鼠釋放事件
document.addEventListener('mouseup', dragEnd);
document.addEventListener('touchend', dragEnd);

// 拖拽開始事件處理程式
function dragStart(event) {
  event.preventDefault();

  if (event.type === 'touchstart') {
    startX = event.touches[0].clientX;
    startY = event.touches[0].clientY;
  } else {
    startX = event.clientX;
    startY = event.clientY;
  }

  initialX = draggableElement.offsetLeft;
  initialY = draggableElement.offsetTop;
}

// 拖拽事件處理程式
function drag(event) {
  event.preventDefault();

  if (event.type === 'touchmove') {
    const currentX = event.touches[0].clientX - startX;
    const currentY = event.touches[0].clientY - startY;
    draggableElement.style.left = initialX + currentX + 'px';
    draggableElement.style.top = initialY + currentY + 'px';
  } else {
    const currentX = event.clientX - startX;
    const currentY = event.clientY - startY;
    draggableElement.style.left = initialX + currentX + 'px';
    draggableElement.style.top = initialY + currentY + 'px';
  }
}

// 拖拽結束事件處理程式
function dragEnd() {
  // 執行拖拽結束後的操作
}

3.2 關於vue-draggable-next 庫的功能總結

 

vue-draggable-next 庫特點和功能的補充說明:

  • 基於 Vue 3:vue-draggable-next 是為 Vue.js 3 版本設計的拖拽庫,充分利用了 Vue 3 的響應式系統和組合式 API。
  • 輕量級和簡單易用:該庫的代碼量較少,易於理解和使用。它提供了一組簡單的指令和組件,可以輕鬆地將拖拽功能集成到 Vue.js 應用程式中。
  • 支持多種拖拽模式:vue-draggable-next 支持多種拖拽模式,包括自由拖拽、列表拖拽、網格拖拽等。您可以根據需求選擇適合的拖拽模式。
  • 自定義拖拽樣式和行為:該庫允許您自定義拖拽元素的樣式和行為。您可以定義拖拽時的樣式、占位符元素、限制拖拽的範圍等。
  • 事件和回調支持:vue-draggable-next 提供了一組事件和回調函數,可以在拖拽過程中監聽和處理各種事件。例如,您可以監聽拖拽開始、拖拽結束、拖拽元素排序等事件,並執行相應的操作。
  • 支持觸摸設備:該庫對觸摸設備提供了良好的支持,可以在移動設備上實現流暢的拖拽交互。

本文轉載於:

https://juejin.cn/post/7297093747703005235

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述:在C++中,通過互斥鎖解決併發數據同步問題。定義共用數據和互斥鎖,編寫線程函數,使用互斥鎖確保操作的原子性。主函數中創建並啟動線程,保障線程安全。實例源代碼演示了簡單而有效的同步機制。 在C++中解決併發操作時的數據同步問題通常需要使用互斥鎖(Mutex)來確保線程安全。以下是詳細的步驟以及附 ...
  • 本文先是簡單介紹了ML.NET與ML.NET Model Builder,其次基於ML.NET Model Builder構建了一個貓狗識別的機器學習模型實例,最後在.NET項目中集成了它。 ...
  • Linux系統中tar是最常用的打包工具,通過打包工具可以壓縮/解壓 比如常見的壓縮包格式 如下: tar 未壓縮文件 只是做了一個打包而已 tar.gz 使用gzip演算法格式壓縮的壓縮包 tar.bz2 bz2格式壓縮包 tar.xz xz格式壓縮 參數介紹 tar 的參數很多 列出幾個比較常用的 ...
  • ceph-deploy比較適合生產環境,不是用cephadm搭建。相對麻煩一些,但是並不難,細節把握好就行,只是命令多一些而已。 實驗環境 伺服器主機 public網段IP(對外服務) cluster網段IP(集群通信) 角色 deploy 192.168.2.120 用於部署集群、管理集群 cep ...
  • 在經濟社會發展的過程中,銀行的角色愈發重要。隨著金融體系不斷完善,各大銀行之間的交流、合作也變得尤為關鍵。而銀行之間互相識別和通信的一種方式,就是通過聯行號。 聯行號是指銀行間互相識別的一種編碼方式。每個銀行都擁有一個唯一的聯行號,用於區分不同的銀行和分行。有了聯行號,各大銀行之間的交流和轉賬操作就 ...
  • What is State 雖然數據流中的許多操作一次只查看一個單獨的事件(例如事件解析器),但某些操作會記住多個事件的信息(例如視窗運算元)。 這些操作稱為有狀態的(stateful)。 有狀態操作的一些示例: 當應用程式搜索某些事件模式(event patterns)時,狀態(state)將存儲迄 ...
  • 近日,天翼雲大數據平臺順利完成中國信通院無伺服器(Serverless) 架構大數據平臺測試,成為首批通過該測試的單位之一 ...
  • 1、首先選擇一張需要的圖片,通過左側的Resource Manage選擇“+”並選擇Import Drawables 選擇一張圖片 並調整以下兩個內容 這兩個內容的作用借用谷歌官方的Android開發教程的內容: *Android 設備具有不同的屏幕尺寸(手機、平板電腦和電視等),而且這些屏幕也具有 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...