国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā)

這篇具有很好參考價(jià)值的文章主要介紹了web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

新的學(xué)習(xí)方法
  • 用手寫簡單方法實(shí)現(xiàn)一個(gè)功能
  • 然后用比較成熟的第三方解決方案
  • 即能學(xué)習(xí)原理又能學(xué)習(xí)第三方庫的使用

從兩個(gè)DEMO開始

  • Vue Draggable Next: Vue Draggable Next
  • React Sortable HOC: React Sortable HOC
列表排序的三個(gè)階段
  • 拖動開始(dragstart)
    • 被拖動圖層的狀態(tài)變化
    • 會出一個(gè)浮層
  • 拖動進(jìn)行中(dragmove)
    • 浮層會隨著鼠標(biāo)移動
    • 條目發(fā)生換位:當(dāng)浮層下沿超過被拖條目二分之一的時(shí)候,觸發(fā)換位。這是一個(gè)比較獨(dú)特的需求
  • 松開鼠標(biāo)階段(drop)
    • 浮層消失
    • 被拖動圖層狀態(tài)復(fù)原
    • 數(shù)據(jù)被更新
      web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā),慕課網(wǎng)-Web前端架構(gòu)師,前端,編輯器
拖動排序功能開發(fā)

第一階段 Dragstart

  • 被拖動圖層的狀態(tài)變化 常規(guī)做法
    • 添加mouseDown事件,檢查當(dāng)前的target是那個(gè)元素,然后給他添加特定的狀態(tài)
    • 添加mouseMove事件,創(chuàng)一個(gè)和被拖動元素一模一樣的的浮層,將它的定位設(shè)置
      它的定位為絕對定位,并且隨著鼠標(biāo)的坐標(biāo)更新。
  • 使用HTML的Drag特性
    • 文檔地址:拖拽操作
    • 瀏覽器的默認(rèn)拖拽行為:支持圖象,鏈接和選擇的文本
    • 其他元素默認(rèn)情況是不可拖拽的。
    • 如果想可以拖拽可以設(shè)置為draggable = true
    • 使用dragstart事件監(jiān)控拖動開始,并設(shè)置對應(yīng)的屬性

LayerList組件中添加draggable屬性

// LayerList.vue
<li
  class="ant-list-item"
  v-for="item in list" :key="item.id"
  :class="{ active: item.id === selectedId }"
  @click="handleClick(item.id)"
  draggable="true"
></li>

web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā),慕課網(wǎng)-Web前端架構(gòu)師,前端,編輯器
這樣就可以有效果了:當(dāng)拖動對應(yīng)條目的時(shí)候,它會自動生成半透明的條目,并且跟隨鼠標(biāo)的移動。
接下來就開始使用dragstart事件監(jiān)控拖動開始,并設(shè)置對應(yīng)的屬性

  • 給被拖動元素添加特定的狀態(tài):使用一系列的事件來監(jiān)控拖動的進(jìn)度,使用dragStart開始拖動操作
// LayerList.vue
// html部分
<li
  class="ant-list-item"
  v-for="item in list" :key="item.id"
  :class="{ active: item.id === selectedId, ghost: dragData.currentDragging === item.id}"
  @click="handleClick(item.id)"
  @dragstart="onDragStart($event, item.id)"
  draggable="true"
></li>
// js部分(setup)
const dragData = reactive({
  currentDragging: ''
})
const onDragStart = (e: DragEvent, id: string ) => {
  dragData.currentDragging = id;
}
// css部分
.ant-list-item.ghost {
  opacity: 0.5;
}

完成出來的效果:
web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā),慕課網(wǎng)-Web前端架構(gòu)師,前端,編輯器
接下來就是在鼠標(biāo)松開的時(shí)候,特定的狀態(tài)消失:使用drop事件:

<ul :list="list" class="ant-list-items ant-list-border" @drop="onDrop"></ul>
const onDrop = (e: DragEvent ) => {
  dragData.currentDragging = '';
}

但是這樣做發(fā)現(xiàn)不起作用,后來發(fā)現(xiàn)是onDrog事件并沒有觸發(fā),原因:
dragenter 或 dragover 事件的監(jiān)聽程序用于表示有效的放置目標(biāo),也就是被拖拽項(xiàng)目可能放置的地方。網(wǎng)頁或應(yīng)用程序的大多數(shù)區(qū)域都不是放置數(shù)據(jù)的有效位置。因此,這些事件的默認(rèn)處理是不允許放置。
指定放置對象
因?yàn)榫W(wǎng)頁大部分區(qū)域不是有效的放置位置,這些事件的默認(rèn)處理都是不允許放置,所以這個(gè)行為并不會被觸發(fā)。
如果你想要允許放置,你必須取消 dragenter 和 dragover 事件來阻止默認(rèn)的處理。你可以在屬性定義的事件監(jiān)聽程序返回 false,或者調(diào)用事件的 preventDefault() 方法來實(shí)現(xiàn)這一點(diǎn)。在一個(gè)獨(dú)立腳本中的定義的函數(shù)里,可能后者更可行。
最終添加阻止默認(rèn)行為事件:

<ul :list="list" class="ant-list-items ant-list-border" @drop="onDrop" @dragover="onDragOver">

const onDragOver = (e: DragEvent) => {
  e.preventDefault()
}
處理松開鼠標(biāo)時(shí)進(jìn)行排序
  1. 修改dragData 添加一個(gè)當(dāng)前索引的屬性

        const dragData = reactive({
          currentDragging: '',
          currentIndex: -1,
        });
    
  2. @dragstart=“onDragStart($event, item.id, index)” 方法中多添加一個(gè)index參數(shù)

        const onDragStart = (e: DragEvent, id: string, index: number) => {
          dragData.currentDragging = id;
          dragData.currentIndex = index;
        };
    

有了開始拖動的index之后,我們要知道drop的時(shí)候新的index,我們怎么在onDrop方法中拿到新的index呢?因?yàn)樵?code>onDrop中我們的參數(shù)是event,使用event.target可以拿到dom元素,把最新的index放到dom元素上面就可以了,使用:HTMLElement.dataset
3. 使用 HTMLElement.dataset拿到最新的索引

HTMLElement.dataset屬性允許無論是在讀取模式和寫入模式下訪問在HTML 或 DOM中元素上設(shè)置的
所有自定義數(shù)據(jù)屬性(data-*)集
它是一個(gè)DOMString的映射,每個(gè)自定義數(shù)據(jù)屬性的一個(gè)條目。
請注意,dataset屬性本身可以被讀取,但不能直接寫入,相反,所有的寫入必股友是它的屬性,這反過來
表示數(shù)據(jù)屬性。
還要注意,一個(gè)HTML data-attribute 及其對應(yīng)的DOM dataset.property 不共享相同的名稱,但它
們總是相似的:

       <li
         class="ant-list-item"
         :class="{
           active: item.id === selectedId,
           ghost: dragData.currentDragging === item.id,
         }"
         v-for="(item, index) in list"
         :key="item.id"
         @click="handleClick(item.id)"
         @dragstart="onDragStart($event, item.id, index)"
         :data-index="index"
         draggable="true"
       >
  1. 修改onDrop事件
const onDrop = (e: DragEvent) => {
  const currentEle = e.target as HTMLElement;
  if (currentEle.dataset.index) {
    const moveIndex = parseInt(currentEle.dataset.index);
    console.log(moveIndex);
  }
  dragData.currentDragging = "";
};

但是這樣寫moveIndex是不一定存在的,因?yàn)?code>e.target是鼠標(biāo)指向的元素,所以當(dāng)在目標(biāo)子元素上面進(jìn)行釋放的話,就會把目標(biāo)當(dāng)成子元素,比如如果釋放到的元素是鎖元素,則currentEle就是鎖元素。所以這里需要一個(gè)方法來向上進(jìn)行檢索,找到符合條件的父元素。

export const getParentElement = (element: HTMLElement, className: string) => {
  while (element) {
    if (element.classList && element.classList.contains(className)) {
      return element;
    } else {
      element = element.parentNode as HTMLElement;
    }
  }
  return null;
};
    const onDrop = (e: DragEvent) => {
      const currentEle = getParentElement(
        e.target as HTMLElement,
        'ant-list-item'
      );
      if (currentEle && currentEle.dataset.index) {
        const moveIndex = parseInt(currentEle.dataset.index);
        // 使用第三方庫arrayMove改變數(shù)組
        arrayMove.mutate(props.list, dragData.currentIndex, moveIndex);
      }
      dragData.currentDragging = '';
    };

array-move
最終實(shí)現(xiàn)的效果:
web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā),慕課網(wǎng)-Web前端架構(gòu)師,前端,編輯器

在拖動時(shí)完成排序:
    const onDragEnter = (e: DragEvent, index: number) => {
      // 這里的判斷是為了避免完成轉(zhuǎn)換后,觸發(fā)新的一次dragEnter事件
      if (index !== dragData.currentIndex) {
        console.log('enter', index, dragData.currentIndex);
        arrayMove.mutate(props.list, dragData.currentIndex, index);
        dragData.currentIndex = index;
        end = index
      }
    };

這樣就可以在拖動時(shí)完成排序了,onDrop里面就不需要進(jìn)行同樣的操作了,修改一下onDrop事件

let start = -1;
let end = -1;
const onDragStart = (e: DragEvent, id: string, index: number) => {
  dragData.currentDragging = id;
  dragData.currentIndex = index;
  start = index;
};
const onDrop = (e: DragEvent) => {
  context.emit('drop', { start, end})
  dragData.currentDragging = '';
};

現(xiàn)在就完成了可拖動排序的簡單編碼,主要掌握三個(gè)階段:

  1. 排序開始:監(jiān)控被拖拽的元素,添加特殊狀態(tài)和UI
  2. 移動階段:進(jìn)入別的列表的時(shí)候完成數(shù)據(jù)的交換
  3. drop階段:松開按鈕的時(shí)候,將狀態(tài)恢復(fù)原狀,并且發(fā)送對應(yīng)的事件。

使用第三方庫進(jìn)行排序:

使用Vue Draggable進(jìn)行排序:

vue.draggable.next

npm i -S vuedraggable@next

將用draggable替換掉ul

<template>
  <draggable
    :list="list"
    class="ant-list-items ant-list-bordered"
    ghost-class="ghost"
    handle=".handle"
    item-key="id"
  >
    <template #item="{ element }">
      <li
        class="ant-list-item"
        :class="{ active: element.id === selectedId }"
        @click="handleClick(element.id)"
      >
        <a-tooltip :title="element.isHidden ? '顯示' : '隱藏'">
          <a-button
            shape="circle"
            @click.stop="
              handleChange(element.id, 'isHidden', !element.isHidden)
            "
          >
            <template v-slot:icon v-if="element.isHidden"
              ><EyeInvisibleOutlined />
            </template>
            <template v-slot:icon v-else><EyeOutlined /> </template>
          </a-button>
        </a-tooltip>
        <a-tooltip :title="element.isLocked ? '解鎖' : '鎖定'">
          <a-button
            shape="circle"
            @click.stop="
              handleChange(element.id, 'isLocked', !element.isLocked)
            "
          >
            <template v-slot:icon v-if="element.isLocked"
              ><LockOutlined/>
            </template>
            <template v-slot:icon v-else><UnlockOutlined  /> </template>
          </a-button>
        </a-tooltip>
        <inline-edit
          class="edit-area"
          :value="element.layerName"
          @change="
            (value) => {
              handleChange(element.id, 'layerName', value);
            }
          "
        ></inline-edit>
        <a-tooltip title="拖動排序">
          <a-button shape="circle" class="handle">
            <template v-slot:icon><DragOutlined /> </template
          ></a-button>
        </a-tooltip>
      </li>
    </template>
  </draggable>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
import draggable from 'vuedraggable';
import {
  EyeOutlined,
  EyeInvisibleOutlined,
  LockOutlined,
  UnlockOutlined,
  DragOutlined,
} from '@ant-design/icons-vue';
import { ComponentData } from '../store/editor';
import InlineEdit from '../components/InlineEdit.vue';
export default defineComponent({
  props: {
    list: {
      type: Array as PropType<ComponentData[]>,
      required: true,
    },
    selectedId: {
      type: String,
      required: true,
    },
  },
  emits: ['select', 'change', 'drop'],
  components: {
    EyeOutlined,
    EyeInvisibleOutlined,
    LockOutlined,
    UnlockOutlined,
    InlineEdit,
    draggable,
    DragOutlined,
  },
  setup(props, context) {
    const handleClick = (id: string) => {
      context.emit('select', id);
    };
    const handleChange = (id: string, key: string, value: boolean) => {
      const data = {
        id,
        key,
        value,
        isRoot: true,
      };
      context.emit('change', data);
    };
    return {
      handleChange,
      handleClick,
    };
  },
});
</script>

<style scoped>
.ant-list-item {
  padding: 10px 15px;
  transition: all 0.5s ease-out;
  cursor: pointer;
  justify-content: normal;
  border: 1px solid #fff;
  border-bottom-color: #f0f0f0;
}
.ant-list-item.active {
  border: 1px solid #1890ff;
}
.ant-list-item.ghost {
  opacity: 0.5;
}

.ant-list-item:hover {
  background: #e6f7ff;
}
.ant-list-item > * {
  margin-right: 10px;
}
.ant-list-item button {
  font-size: 12px;
}

.ant-list-item .handle {
  cursor: move;
  margin-left: auto;
}
.ant-list-item .edit-area {
  width: 100%;
}
</style>

web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā),慕課網(wǎng)-Web前端架構(gòu)師,前端,編輯器文章來源地址http://www.zghlxwxcb.cn/news/detail-824560.html

到了這里,關(guān)于web架構(gòu)師編輯器內(nèi)容-圖層拖動排序功能的開發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Unity編輯器擴(kuò)展】(二)PSD轉(zhuǎn)UGUI Prefab, 圖層解析和碎圖導(dǎo)出

    【Unity編輯器擴(kuò)展】(二)PSD轉(zhuǎn)UGUI Prefab, 圖層解析和碎圖導(dǎo)出

    ?書接上回:【Unity編輯器擴(kuò)展】(一)PSD轉(zhuǎn)UGUI Prefab, Aspose.PSD和Harmony庫的使用_TopGames的博客-CSDN博客 解放UI程序/美術(shù)? psd文件一鍵轉(zhuǎn)ui prefab 支持所有ui類型 支持textmeshpro psd一鍵轉(zhuǎn)ugui prefab工具 設(shè)計(jì)原理和詳細(xì)使用方法 工具使用預(yù)覽: 1. 實(shí)現(xiàn)將psd解析生成為UI預(yù)制體,并導(dǎo)出UI圖

    2024年02月07日
    瀏覽(33)
  • React 框架下自己寫一個(gè)braft編輯器,然后將編輯器內(nèi)容展示在網(wǎng)頁端

    React 框架下自己寫一個(gè)braft編輯器,然后將編輯器內(nèi)容展示在網(wǎng)頁端

    1.首先自己寫一個(gè)編輯器 輸入文字; 支持選擇表情; 可添加小程序鏈接;可添加網(wǎng)頁鏈接;并且可以編輯刪除;效果如下 2.輸入完畢后,點(diǎn)擊文本輸入框保存,將便攜式內(nèi)容回顯, 渲染時(shí),因?yàn)槭莌tml格式,所以采用dangerouslySetInnerHTML屬性來渲染 添加樣式,渲染后里面的鏈接

    2024年02月16日
    瀏覽(32)
  • AJAX + PHP 編輯器內(nèi)容自動備份草稿保存到本地 (適用ueditor百度編輯器或其它) 內(nèi)容變化后自動觸發(fā)備份txt文件

    AJAX + PHP 編輯器內(nèi)容自動備份草稿保存到本地 (適用ueditor百度編輯器或其它) 內(nèi)容變化后自動觸發(fā)備份txt文件

    百度自帶的自動備份功能enableAutoSave存在問題, 比如第一個(gè)文章他自動備份了.等發(fā)表第二個(gè)文章時(shí),結(jié)果把第一個(gè)文章的內(nèi)容自動填充進(jìn)去了.關(guān)鍵你還不知情!出現(xiàn)過多次這種情況了. 一, 百度原版的 ,具體使用方法,看這里個(gè)文章 Ueditor百度編輯器內(nèi)容自動保存到本地防數(shù)據(jù)丟失

    2024年02月10日
    瀏覽(22)
  • 【HTML】標(biāo)簽讀取富文本編輯器的內(nèi)容

    【HTML】標(biāo)簽讀取富文本編輯器的內(nèi)容

    1.正確讀取富文本內(nèi)容示例: 代碼: ?顯示結(jié)果: ?在這個(gè)例子中, {$row.content} ?是直接輸出從數(shù)據(jù)庫中獲取的富文本內(nèi)容,包括可能存在的HTML標(biāo)簽和屬性,這樣可以確保富文本能夠按照預(yù)期樣式呈現(xiàn)。 2. 錯(cuò)誤讀取富文本內(nèi)容示例及其原因分析: ?代碼: ?顯示結(jié)果: 分析

    2024年02月02日
    瀏覽(38)
  • 工業(yè)組態(tài) 物聯(lián)網(wǎng)組態(tài) 組態(tài)編輯器 web組態(tài) 組態(tài)插件 編輯器

    工業(yè)組態(tài) 物聯(lián)網(wǎng)組態(tài) 組態(tài)編輯器 web組態(tài) 組態(tài)插件 編輯器

    ?體驗(yàn)地址:by組態(tài)[web組態(tài)插件] BY組態(tài)是一款非常優(yōu)秀的純前端的【web組態(tài)插件工具】,可無縫嵌入到vue項(xiàng)目,react項(xiàng)目等,由于是原生js開發(fā),對于前端的集成沒有框架的限制。同時(shí)由于BY組態(tài)只是一個(gè)插件,不能獨(dú)立運(yùn)行,必須嵌入到你方軟件平臺才能使用,所以你方軟件

    2024年04月15日
    瀏覽(68)
  • 利用三維內(nèi)容編輯器制作VR交互課件,簡單好用易上手

    利用三維內(nèi)容編輯器制作VR交互課件,簡單好用易上手

    隨著虛擬現(xiàn)實(shí)技術(shù)的不斷發(fā)展,越來越多的教育機(jī)構(gòu)開始嘗試將其應(yīng)用于教育教學(xué)中。然而,要實(shí)現(xiàn)這一目標(biāo)并不容易,需要專業(yè)的技術(shù)支持和開發(fā)團(tuán)隊(duì)。 為了解決這一問題, 廣州華銳互動 研發(fā)了 三維內(nèi)容編輯器 ,它是一種基于虛擬現(xiàn)實(shí)技術(shù)的教育內(nèi)容編輯器,可以幫助

    2024年02月12日
    瀏覽(24)
  • Unity編輯器擴(kuò)展-第二集-按鈕排序/分組/放入右鍵菜單

    Unity編輯器擴(kuò)展-第二集-按鈕排序/分組/放入右鍵菜單

    第一集鏈接:Unity編輯器擴(kuò)展-第一集-在菜單欄加入自己的按鈕_菌菌巧樂茲的博客-CSDN博客 一、本節(jié)目標(biāo)+效果展示 1.按鈕排序 變成 2.按鈕分組 仔細(xì)看,有個(gè)灰色的杠杠 3.放入右鍵菜單 4.皮一下 ?二、按鈕排序具體流程 第一集講,如果想放入標(biāo)簽主要的代碼是 ?但是這行代碼

    2024年02月14日
    瀏覽(21)
  • 最火web大屏可視化編輯器

    最火web大屏可視化編輯器

    ? ? ? ?樂吾樂Le5le大屏可視化設(shè)計(jì)器,零代碼實(shí)現(xiàn)物聯(lián)網(wǎng)、工業(yè)智能制造等領(lǐng)域的可視化大屏、觸摸屏端UI以及工控可視化的解決方案。同時(shí)也是一個(gè)Web組態(tài)工具,支持2D、3D等多種形式,用于構(gòu)建具有實(shí)時(shí)數(shù)據(jù)展示、監(jiān)控預(yù)警、豐富交互的組態(tài)畫面。擁有豐富的大屏組件和行

    2024年02月05日
    瀏覽(19)
  • 老牌開源 SVG 編輯器 SVGEdit 是如何架構(gòu)的?

    老牌開源 SVG 編輯器 SVGEdit 是如何架構(gòu)的?

    大家好,我是前端西瓜哥。這次簡單看看 SVGEdit 的架構(gòu)。 SVGEdit 的版本為 7.2.0。 SVGEdit 一款非常老牌的 SVG 圖形編輯器,用于編輯處理 SVG,start 數(shù)目前是 5.8k。 它的優(yōu)點(diǎn)在于經(jīng)過多年的開發(fā),完成度高,較為成熟,功能相當(dāng)豐富 。 有豐富的工具:選擇工具、鉛筆工具、鋼筆

    2024年02月03日
    瀏覽(17)
  • JAVA在線電子病歷編輯器源碼 B/S架構(gòu)

    JAVA在線電子病歷編輯器源碼 B/S架構(gòu)

    電子病歷在線制作、管理和使用的一體化電子病歷解決方案,通過一體化的設(shè)計(jì),提供對住院病人的電子病歷書寫、保存、修改、打印等功能。電子病歷系統(tǒng)將臨床醫(yī)護(hù)需要的診療資料以符合臨床思維的方法展示。建立以病人為中心,以臨床診療信息為主線,集成門急診、住

    2024年02月07日
    瀏覽(32)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包