最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于vue實(shí)現(xiàn)一個(gè)禪道主頁(yè)拖拽效果

 更新時(shí)間:2019年05月27日 11:50:47   作者:禾寸  
最近在做一個(gè)基于vue的后臺(tái)管理項(xiàng)目。接下來(lái)通過(guò)本文給大家分析一款基于vue做一個(gè)禪道主頁(yè)拖拽效果,需要的朋友可以參考下

效果圖如下所示:

源碼地址

bb兩句

最近在做一個(gè)基于vue的后臺(tái)管理項(xiàng)目。平時(shí)項(xiàng)目進(jìn)度統(tǒng)計(jì)就在上禪道上進(jìn)行。so~ 然后領(lǐng)導(dǎo)就感覺(jué)這個(gè)拖拽效果還行,能不能加到咱們項(xiàng)目里面。 既然領(lǐng)導(dǎo)發(fā)話(huà),那就開(kāi)干。。

所有技術(shù):vue + vuedraggable

拖動(dòng)的實(shí)現(xiàn)基于 vuedraggable 的插件開(kāi)發(fā)。

主頁(yè)為兩欄流式布局,每一個(gè)組件可以在上下拖動(dòng),也可以左右拖動(dòng)。

基本步驟

布局

這塊布局為最為普通的兩欄布局,這里采用flex布局。左邊自適應(yīng),右邊為固定寬。

.layout-container {
 display: flex;
 .left {
 flex: 1;
 margin-right: 40px;
 }
 .right {
 width: 550px;
 }
} 

拖拽實(shí)現(xiàn)

這里使用 vuedraggable 插件。需要在組件里面引入使用。 draggable 相當(dāng)于拖拽容器,這塊很明顯需要兩個(gè)拖拽的容器。所以分別在 .left .right 中添加兩個(gè)拖拽容器。在默認(rèn)情況下,這里已經(jīng)可以進(jìn)行拖拽了。插件的效果還是很強(qiáng)大。

<div class="layout-container">
  <!--左欄-->
 <div class="left">
  <draggable
   v-bind="dragOptions"
   class="list-group"
   :list="item"
  >
   // ... 拖拽元素或組件
  </draggable>
  </div>
  <!--右欄-->
 <div class="right">
  <draggable
   v-bind="dragOptions"
   class="list-group"
   :list="item"
  >
   // ... 拖拽元素或組件
  </draggable>
 </div>
</div>
<script>
import draggable from "vuedraggable";
export default {
 components: {draggable},
 computed: {
 dragOptions() {
  return {
  animation: 30,
  handle: ".drag-handle",
  group: "description",
  ghostClass: "ghost",
  chosenClass: "sortable",
  forceFallback: true
  };
 }
 }
};
</script>

但是, 和我想要的效果還是相差一點(diǎn)。

左右拖動(dòng) 與 僅標(biāo)題欄拖動(dòng)

這塊只需要配置相關(guān)的配置項(xiàng)就可以比較簡(jiǎn)單。 左右拖動(dòng)需要給拖拽容器指定相同的 group 屬性。指定標(biāo)題元素拖動(dòng)需要配置 handle 為可拖動(dòng)元素的選擇器名稱(chēng)。

下面簡(jiǎn)單介紹下常用的配置項(xiàng):

  • disabled :boolean 定義是否此sortable對(duì)象是否可用,為true時(shí)sortable對(duì)象不能拖放排序等功能,為false時(shí)為可以進(jìn)行排序,相當(dāng)于一個(gè)開(kāi)關(guān);
  • group : 用處是為了設(shè)置可以拖放容器時(shí)使用,若兩個(gè)容器該配置項(xiàng)相同,則可以相互拖動(dòng);
  • animation :number 單位:ms,定義排序動(dòng)畫(huà)的時(shí)間;
  • handle :selector 格式為簡(jiǎn)單css選擇器的字符串,使列表單元中符合選擇器的元素成為拖動(dòng)的手柄,只有按住拖動(dòng)手柄才能使列表單元進(jìn)行拖動(dòng);
  • filter :selector 格式為簡(jiǎn)單css選擇器的字符串,定義哪些列表單元不能進(jìn)行拖放,可設(shè)置為多個(gè)選擇器,中間用“,”分隔;
  • draggable :selector 格式為簡(jiǎn)單css選擇器的字符串,定義哪些列表單元可以進(jìn)行拖放
  • ghostClass :selector 格式為簡(jiǎn)單css選擇器的字符串,當(dāng)拖動(dòng)列表單元時(shí)會(huì)生成一個(gè)副本作為影子單元來(lái)模擬被拖動(dòng)單元排序的情況,此配置項(xiàng)就是來(lái)給這個(gè)影子單元添加一個(gè)class,我們可以通過(guò)這種方式來(lái)給影子元素進(jìn)行編輯樣式;
  • chosenClass :selector 格式為簡(jiǎn)單css選擇器的字符串,當(dāng)選中列表單元時(shí)會(huì)給該單元增加一個(gè)class;
  • forceFallback :boolean 如果設(shè)置為true時(shí),將不使用原生的html5的拖放,可以修改一些拖放中元素的樣式等;
  • fallbackClass :string 當(dāng)forceFallback設(shè)置為true時(shí),拖放過(guò)程中鼠標(biāo)附著單元的樣式;

采用相關(guān)配置如下:

computed: {
 dragOptions() {
  return {
  animation: 30,
  handle: ".drag-handle",
  group: "description",
  ghostClass: "ghost",
  chosenClass: "sortable",
  forceFallback: true
  };
 }
 }

拖動(dòng)時(shí)樣式調(diào)整

在拖動(dòng)的時(shí)候,我們需要做三個(gè)事情。拖動(dòng)時(shí),拖動(dòng)元素只顯示標(biāo)題欄,兩欄內(nèi)列表只顯示標(biāo)題元素以及將要移動(dòng)的位置變灰。

1.拖動(dòng)元素只顯示標(biāo)題欄: 在默認(rèn)情況下,會(huì)開(kāi)啟 html5 元素的拖動(dòng)效果。這里明顯不需要。 forceFallback 改為 false 則可以關(guān)閉 html5 的默認(rèn)效果。順便通過(guò) chosenClass: "sortable" 修改拖動(dòng)元素class 類(lèi)名。直接用css進(jìn)行隱藏

.sortable {
 .component-box {
 display: none;
 height: 0;
 }
}

2.兩欄內(nèi)列表只顯示標(biāo)題元素 這里我借助兩個(gè)事件實(shí)現(xiàn)。

  • onStart:function 列表單元拖動(dòng)開(kāi)始的回調(diào)函數(shù)
  • onEnd:function 列表單元拖放結(jié)束后的回調(diào)函數(shù)
<div class="layout-container" :class="{drag:dragging}">
 //...
</div>
data() {
 return {
  dragging: false
 };
},
methods: {
 onStart() {
  this.dragging = true;
 },
 onEnd() {
  this.dragging = false;
 }
 }
.drag {
 .component-box {
 display: none;
 }
}

在開(kāi)始拖動(dòng)的時(shí)候給 .layout-container 添加 .drag 的 class 名。拖動(dòng)結(jié)束時(shí),移除class名。

將要移動(dòng)的位置變灰

這里需要用到上面 ghostClass: "ghost" 配置項(xiàng)。并添加相應(yīng)的css。

.ghost {
 .drag-handle {
 background: rgb(129, 168, 187);
 }
}

好了基本已經(jīng)實(shí)現(xiàn)了。。。

展示動(dòng)態(tài)組件

接下來(lái)就是數(shù)據(jù)的動(dòng)態(tài)展示了。 這里需要vue中的動(dòng)態(tài)組件了。。附上官方文檔連接點(diǎn)擊查看。

然后里面每個(gè)拖動(dòng)的元素的內(nèi)容都寫(xiě)成組件,搭配動(dòng)態(tài)組件實(shí)現(xiàn)自由拖動(dòng)。

// 將所用組件引入
import {
 timeline,
 calendar,
 welcome,
 carousel,
 imgs,
 KonList
} from "@/components/DragComponents";

components: {
 draggable,
 timeline,
 calendar,
 welcome,
 carousel,
 imgs,
 KonList
}

配合 v-for 對(duì)數(shù)據(jù)進(jìn)行循環(huán),然后進(jìn)行動(dòng)態(tài)展示。

<component :is="element.name"/>

這塊涉及到數(shù)據(jù)格式相關(guān)的,可以直接看文末的代碼。。。 這里就就不展開(kāi)說(shuō)了。。

數(shù)據(jù)保持

在拖動(dòng)結(jié)束后,我們需要將拖動(dòng)的順序緩存在前端,當(dāng)下次進(jìn)入后,可以繼續(xù)使用拖動(dòng)后的數(shù)據(jù)。

// 獲取新的布局
 getLayout() {
  let myLayout = JSON.parse(window.localStorage.getItem("kon"));
  if (!myLayout || Object.keys(myLayout).length === 0)
  myLayout = this.layout;
  const newLayout = {};
  for (const side in myLayout) {
  newLayout[side] = myLayout[side].map(i => {
   return this.componentList.find(c => c.id === i);
  });
  }
  this.mainData = newLayout;
},
// 設(shè)置新的布局
setLayout() {
 const res = {};
 for (const side in this.mainData) {
  const item = this.mainData[side].map(i => i.id);
  res[side]=item;
 }
 window.localStorage.setItem("kon", JSON.stringify(res));
}

這樣我只需要在 mounted 中獲取新的布局。。

mounted() {
 this.getLayout();
 }

在拖動(dòng)結(jié)束后,設(shè)置新的布局

onEnd() {
  this.dragging = false;
  this.setLayout();
}

在項(xiàng)目中,還是建議配合后端進(jìn)行用戶(hù)布局的數(shù)據(jù)存儲(chǔ),每次拖動(dòng)后將新的布局?jǐn)?shù)據(jù)請(qǐng)求接口保存在數(shù)據(jù)庫(kù),同時(shí)存入緩存中。當(dāng)再次進(jìn)入頁(yè)面的時(shí)候,讀取緩存中的數(shù)據(jù),沒(méi)有的話(huà)請(qǐng)求后端的接口拿到用戶(hù)的布局,然后再次存入緩存中。有的話(huà)直接讀取緩存中的數(shù)據(jù)。

最后說(shuō)兩句

其實(shí)上面的效果也不是特別難,簡(jiǎn)單花點(diǎn)時(shí)間,看看相關(guān)文檔,就能做出來(lái),,記錄在掘金上面,只是想和大家分享我的思路。同時(shí)希望和大家一起交流,一起進(jìn)步。


生活不易,大家加油

附上源碼: 項(xiàng)目地址

<template>
 <div :class="{drag:dragging}">
  <div class="layout-container">
   <div :class="key" v-for="(item, key) in mainData" :key="key">
    <draggable
     v-bind="dragOptions"
     class="list-group"
     :list="item"
     @end="onEnd"
     @start="onStart"
    >
     <transition-group name="list">
      <div class="list-group-item" v-for="(element, index) in item" :key="index">
       <div class="drag-handle">{{ element.title }}</div>
       <div class="component-box">
        <component :is="element.name"/>
       </div>
      </div>
     </transition-group>
    </draggable>
   </div>
  </div>
 </div>
</template>
<script>
import draggable from "vuedraggable";
import {
 timeline,
 calendar,
 welcome,
 carousel,
 imgs,
 KonList
} from "@/components/DragComponents";

export default {
 components: {
  draggable,
  timeline,
  calendar,
  welcome,
  carousel,
  imgs,
  KonList
 },
 data() {
  return {
   dragging: false,
   componentList: [
    { name: "KonList", title: "追番地址", id: "5" },
    { name: "imgs", title: "五月最強(qiáng)新番", id: "4" },
    { name: "timeline", title: "日程組件", id: "2" },
    { name: "carousel", title: "走馬燈組件", id: "1" },
    { name: "calendar", title: "日歷組件", id: "3" }
   ],
   layout: {
    left: ["5", "4"],
    right: ["2", "1", "3"]
   },
   mainData: {}
  };
 },
 computed: {
  dragOptions() {
   return {
    animation: 30,
    handle: ".drag-handle",
    group: "description",
    ghostClass: "ghost",
    chosenClass: "sortable",
    forceFallback: true
   };
  }
 },
 mounted() {
  this.getLayout();
 },
 methods: {
  onStart() {
   this.dragging = true;
  },
  onEnd() {
   this.dragging = false;
   this.setLayout();
  },
  getLayout() {
   let myLayout = JSON.parse(window.localStorage.getItem("kon"));
   if (!myLayout || Object.keys(myLayout).length === 0)
    myLayout = this.layout;
   const newLayout = {};
   for (const side in myLayout) {
    newLayout[side] = myLayout[side].map(i => {
     return this.componentList.find(c => c.id === i);
    });
   }
   this.mainData = newLayout;
  },
  setLayout() {
   const res = {};
   for (const side in this.mainData) {
    const item = this.mainData[side].map(i => i.id);
    res[side]=item;
   }
   window.localStorage.setItem("kon", JSON.stringify(res));
  }
 }
};
</script>
<style lang="scss" scoped>
.layout-container {
 height: 100%;
 display: flex;
 .left {
  flex: 1;
  margin-right: 40px;
 }
 .right {
  width: 550px;
 }
 .list-group-item {
  margin-bottom: 20px;
  border-radius: 6px;
  overflow: hidden;
  background: #fff;
 }
 .component-box {
  padding: 20px;
 }
 .drag-handle {
  cursor: move;
  height: 40px;
  line-height: 40px;
  color: #fff;
  font-weight: 700;
  font-size: 16px;
  padding: 0 20px;
  background: #6cf;
 }
}
.drag {
 .component-box {
  display: none;
 }
}

.list-enter-active {
 transition: all .3s linear;

}
.list-enter,
.list-leave-to {
 opacity: .5;
}

.sortable {
 .component-box {
  display: none;
  height: 0;
 }
}
.list-group {
 > span {
  display: block;
  min-height: 20px;
 }
}

.ghost {
 .drag-handle {
  background: rgb(129, 168, 187);
 }
}
</style>

總結(jié)

以上所述是小編給大家介紹的基于vue實(shí)現(xiàn)一個(gè)禪道主頁(yè)拖拽效果,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!

相關(guān)文章

  • 前端必知必會(huì)之Vue?$emit()方法詳解

    前端必知必會(huì)之Vue?$emit()方法詳解

    這篇文章主要介紹了前端必知必會(huì)之Vue?$emit()方法的相關(guān)資料,Vue.js中的$emit()方法用于在子組件中創(chuàng)建自定義事件,并在父組件中捕獲這些事件,這在需要從子組件向父組件傳遞信息的大型項(xiàng)目中非常有用,需要的朋友可以參考下
    2025-02-02
  • element-ui如何防止重復(fù)提交的方法步驟

    element-ui如何防止重復(fù)提交的方法步驟

    這篇文章主要介紹了element-ui如何防止重復(fù)提交的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Vue3中Props和Emit的工作原理詳解

    Vue3中Props和Emit的工作原理詳解

    在現(xiàn)代前端開(kāi)發(fā)中,Vue.js 來(lái)作為一個(gè)流行的 JavaScript 框架,提供了簡(jiǎn)單易用的 API 和強(qiáng)大的功能,在 Vue 3 中,“Props”和“Emit”是兩個(gè)核心概念,本文將詳細(xì)探討這兩個(gè)概念的工作原理,并提供示例代碼以幫助更好地理解它們的使用,需要的朋友可以參考下
    2024-11-11
  • vue中的公共方法調(diào)用方式

    vue中的公共方法調(diào)用方式

    這篇文章主要介紹了vue中的公共方法調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue 權(quán)限認(rèn)證token的實(shí)現(xiàn)方法

    vue 權(quán)限認(rèn)證token的實(shí)現(xiàn)方法

    這篇文章主要介紹了vue 權(quán)限認(rèn)證token的實(shí)現(xiàn)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • Vue3+Antd實(shí)現(xiàn)彈框顯示內(nèi)容并加入復(fù)制按鈕

    Vue3+Antd實(shí)現(xiàn)彈框顯示內(nèi)容并加入復(fù)制按鈕

    這篇文章主要介紹了Vue3+Antd實(shí)現(xiàn)彈框顯示內(nèi)容并加入復(fù)制按鈕,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12
  • 淺談Vue為什么不能檢測(cè)數(shù)組變動(dòng)

    淺談Vue為什么不能檢測(cè)數(shù)組變動(dòng)

    這篇文章主要介紹了淺談Vue為什么不能檢測(cè)數(shù)組變動(dòng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 基于Vue實(shí)現(xiàn)文件拖拽上傳功能

    基于Vue實(shí)現(xiàn)文件拖拽上傳功能

    文件拖拽上傳功能現(xiàn)在已經(jīng)隨處可見(jiàn),大家應(yīng)該都用過(guò)了吧,那么它具體是怎么實(shí)現(xiàn)的大家有去了解過(guò)嗎,今天我們一起來(lái)實(shí)現(xiàn)一下這個(gè)功能,并封裝一個(gè)拖拽上傳組件吧
    2024-03-03
  • vue3獲取子組件的DOM元素的方法總結(jié)

    vue3獲取子組件的DOM元素的方法總結(jié)

    在 Vue 3 中,訪(fǎng)問(wèn)子組件的 DOM 元素是一個(gè)常見(jiàn)的需求,本文將介紹如何在 Vue 3 中使用不同的方法來(lái)獲取子組件的 DOM 元素,需要的朋友可以參考下
    2023-08-08
  • 關(guān)于vue中如何監(jiān)聽(tīng)數(shù)組變化

    關(guān)于vue中如何監(jiān)聽(tīng)數(shù)組變化

    這篇文章主要介紹了關(guān)于vue中如何監(jiān)聽(tīng)數(shù)組變化,對(duì)vue感興趣的同學(xué),必須得參考下
    2021-04-04

最新評(píng)論

普兰店市| 琼中| 寿光市| 东海县| 哈密市| 长武县| 石嘴山市| 筠连县| 毕节市| 桃源县| 苍山县| 远安县| 颍上县| 尼勒克县| 绵竹市| 泰宁县| 响水县| 扶风县| 长泰县| 张掖市| 德保县| 崇礼县| 岳阳市| 台东市| 枞阳县| 拉孜县| 石家庄市| 黎平县| 方正县| 浦北县| 红桥区| 邵阳县| 山丹县| 巴彦淖尔市| 汾西县| 六安市| 石门县| 习水县| 陵水| 阿拉善盟| 疏附县|