draggable.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <script setup lang="ts">
  2. import { ref, onMounted } from "vue";
  3. import Sortable, { Swap } from "sortablejs";
  4. import draggable from "vuedraggable/src/vuedraggable";
  5. import { useAppStoreHook } from "@/store/modules/app";
  6. defineOptions({
  7. name: "Draggable"
  8. });
  9. const { setSortSwap } = useAppStoreHook();
  10. const gridLists = ref<Array<Object>>([
  11. { grid: "cn", num: 1 },
  12. { grid: "cn", num: 2 },
  13. { grid: "cn", num: 3 },
  14. { grid: "cn", num: 4 },
  15. { grid: "cn", num: 5 },
  16. { grid: "cn", num: 6 },
  17. { grid: "cn", num: 7 },
  18. { grid: "cn", num: 8 },
  19. { grid: "cn", num: 9 }
  20. ]);
  21. const lists = ref<Array<Object>>([
  22. { people: "cn", id: 1, name: "www.itxst.com" },
  23. { people: "cn", id: 2, name: "www.baidu.com" },
  24. { people: "cn", id: 3, name: "www.taobao.com" },
  25. { people: "cn", id: 4, name: "www.google.com" }
  26. ]);
  27. const cutLists = ref([
  28. { people: "cn", id: 1, name: "cut1" },
  29. { people: "cn", id: 2, name: "cut2" },
  30. { people: "cn", id: 3, name: "cut3" },
  31. { people: "cn", id: 4, name: "cut4" }
  32. ]);
  33. const change = (evt): void => {
  34. console.log("evt: ", evt);
  35. };
  36. onMounted(() => {
  37. if (!useAppStoreHook().sortSwap) Sortable.mount(new Swap());
  38. setSortSwap(true);
  39. new Sortable(document.querySelector(".cut-container"), {
  40. swap: true,
  41. forceFallback: true,
  42. chosenClass: "chosen",
  43. swapClass: "highlight",
  44. animation: 300
  45. });
  46. });
  47. </script>
  48. <template>
  49. <el-card shadow="never">
  50. <template #header>
  51. <div class="card-header">
  52. <span class="font-medium">
  53. 拖拽组件,采用开源的
  54. <el-link
  55. href="https://sortablejs.github.io/vue.draggable.next/#/simple"
  56. target="_blank"
  57. style="margin: 0 4px 5px; font-size: 16px"
  58. >
  59. vuedraggable
  60. </el-link>
  61. </span>
  62. </div>
  63. <el-link
  64. class="mt-2"
  65. href="https://github.com/pure-admin/vue-pure-admin/blob/main/src/views/able/draggable.vue"
  66. target="_blank"
  67. >
  68. 代码位置 src/views/able/draggable.vue
  69. </el-link>
  70. </template>
  71. <div class="drag-container">
  72. <!-- grid列表拖拽 -->
  73. <el-row :gutter="25">
  74. <el-col :xs="25" :sm="8" :md="8" :lg="8">
  75. <el-card shadow="never">
  76. <template #header>
  77. <div class="card-header">
  78. <span>grid列表拖拽</span>
  79. </div>
  80. </template>
  81. <draggable
  82. v-model="gridLists"
  83. class="grid-container"
  84. item-key="grid"
  85. animation="300"
  86. chosenClass="chosen"
  87. forceFallback="true"
  88. >
  89. <template #item="{ element }">
  90. <div :class="'item' + ' ' + 'item-' + element.num">
  91. {{ element.num }}
  92. </div>
  93. </template>
  94. </draggable>
  95. </el-card>
  96. </el-col>
  97. <el-col :xs="25" :sm="8" :md="8" :lg="8">
  98. <el-card shadow="never">
  99. <template #header>
  100. <div class="card-header">
  101. <span>单列拖拽</span>
  102. </div>
  103. </template>
  104. <!-- 单列拖拽 -->
  105. <draggable
  106. v-model="lists"
  107. item-key="name"
  108. chosen-class="chosen"
  109. force-fallback="true"
  110. animation="300"
  111. @change="change"
  112. >
  113. <template #item="{ element, index }">
  114. <div class="item-single">{{ element.name }} {{ index }}</div>
  115. </template>
  116. </draggable>
  117. </el-card>
  118. </el-col>
  119. <el-col :xs="25" :sm="8" :md="8" :lg="8">
  120. <el-card shadow="never">
  121. <template #header>
  122. <div class="card-header">
  123. <span>拖拽实现元素位置交换</span>
  124. </div>
  125. </template>
  126. <!-- 拖拽实现元素位置切换 -->
  127. <div class="cut-container">
  128. <div
  129. v-for="(item, index) in cutLists"
  130. :key="index"
  131. class="item-cut"
  132. >
  133. <p>{{ item.name }}</p>
  134. </div>
  135. </div>
  136. </el-card>
  137. </el-col>
  138. </el-row>
  139. </div>
  140. </el-card>
  141. </template>
  142. <style lang="scss" scoped>
  143. /* grid列表拖拽 */
  144. .grid-container {
  145. display: grid;
  146. grid-template-rows: 33.3% 33.3% 33.3%;
  147. grid-template-columns: 33.3% 33.3% 33.3%;
  148. }
  149. .item-single {
  150. height: 77px;
  151. font-size: 1.5em;
  152. line-height: 85px;
  153. text-align: center;
  154. cursor: move;
  155. border: 1px solid #e5e4e9;
  156. }
  157. .item-cut {
  158. height: 77px;
  159. font-size: 1.5em;
  160. line-height: 77px;
  161. text-align: center;
  162. cursor: move;
  163. border: 1px solid #e5e4e9;
  164. }
  165. .item {
  166. font-size: 2em;
  167. line-height: 100px;
  168. text-align: center;
  169. cursor: move;
  170. border: 1px solid #e5e4e9;
  171. @media screen and (width <= 750px) {
  172. line-height: 90px;
  173. }
  174. }
  175. .item-1 {
  176. background-color: #ef342a;
  177. }
  178. .item-2 {
  179. background-color: #f68f26;
  180. }
  181. .item-3 {
  182. background-color: #4ba946;
  183. }
  184. .item-4 {
  185. background-color: #0376c2;
  186. }
  187. .item-5 {
  188. background-color: #c077af;
  189. }
  190. .item-6 {
  191. background-color: #f8d29d;
  192. }
  193. .item-7 {
  194. background-color: #b5a87f;
  195. }
  196. .item-8 {
  197. background-color: #d0e4a9;
  198. }
  199. .item-9 {
  200. background-color: #4dc7ec;
  201. }
  202. .chosen {
  203. border: solid 2px #3089dc !important;
  204. }
  205. </style>