Vue Table Sortable component
- This is a draggable sortable table component based on Vue.js.
-
- html
-
- The component receives two props: dataSource and keyWords, where dataSource is an array, keyWords is a string, and the default value is ‘index’.
- js
- The parent component uses
- Summarize
This is a Vue.js-based draggable sortable table component.
html
<template> <!-- Use slots, pass customRow, newDataSource as slot properties to slot content --> <slot name="sort" :customRow="customRow" :dataSource="newDataSource"></slot> </template>
The
component receives two props: dataSource and keyWords, where dataSource is an array, keyWords is a string, and the default value is ‘index’.
js
<script lang="ts"> import {<!-- --> ref, computed, defineComponent } from 'vue' export default defineComponent({<!-- --> props:{<!-- --> // Receive dataSource and keyWords attributes passed in from outside dataSource: {<!-- -->type: Array, default: []}, keyWords: {<!-- -->type: String, default: 'index'} }, emits: ['update:dataSource','sortConfirm'], // Define the event dispatched to the parent component setup(props, {<!-- -->emit}){<!-- --> const newDataSource = computed({<!-- --> get() {<!-- --> return props. dataSource }, set(value) {<!-- --> return emit('update:dataSource', value) // When the new data source changes, dispatch the update:dataSource event to pass the new data source to the parent component } }) const dragItem = ref<any>(); // current drag item const dragIndex = ref<any>(); // Index of the current drag item const targetArr = ref<any>([]); // Array to store target row // Method to customize row content const customRow = (record:any, index:number) => {<!-- --> return {<!-- --> style: {<!-- --> cursor: 'move' }, // mouseover onMouseenter: (event:any) => {<!-- --> let ev = event || window.event; if(ev & amp; & amp; ev. target){<!-- --> ev.target.draggable = true; // set the current line to be draggable } }, // start dragging onDragstart: (event: Event|undefined) => {<!-- --> let ev = event || window.event; ev & amp; & amp; ev.stopPropagation(); // prevent event bubbling dragItem.value = record; // Set the current dragged item dragIndex.value = index; // Set the index of the current drag item }, // dragging onDragover: (event: any) => {<!-- --> let ev = event || window.event; ev.preventDefault(); // prevent default drag behavior if(index == dragIndex.value) return; // If the index of the target row is the same as the current row, do nothing let nowLine = ev?.target.closest('tr.ant-table-row'); // Get the closest parent element with class 'tr.ant-table-row' if(!targetArr.value.includes(nowLine)){<!-- --> targetArr.value.push(nowLine); //Add the target line to the target line array } if (index > dragIndex.value) {<!-- --> // If the target row index is greater than the current row index if (!nowLine.classList.contains('afterLine')) {<!-- --> // if the target line does not have afterLine class name targetArr.value.forEach((ele:any) => {<!-- --> // Remove beferLine and afterLine class names of other target rows ele.classList.remove('beferLine') ele.classList.remove('afterLine') }); nowLine.classList.add('afterLine') // Add afterLine class name to the target line } } else {<!-- --> // if the target row index is less than the current row index if (!nowLine.classList.contains('beferLine')) {<!-- --> // if the target line does not have the beferLine class name targetArr.value.forEach((ele:any) => {<!-- --> // Remove beferLine and afterLine class names of other target rows ele.classList.remove('beferLine') ele.classList.remove('afterLine') }); nowLine.classList.add('beferLine') // add beferLine class name to the target line } } }, // place the dragged item onDrop: (event: Event|undefined) => {<!-- --> let ev = event || window.event; ev & amp; & amp; ev.stopPropagation(); // prevent event bubbling emit('sortConfirm',{<!-- --> // dispatch the sortConfirm event to pass the sort confirmation information to the parent component id: newDataSource.value[dragIndex.value]?.id, // the id of the current drag item toId: newDataSource.value[index]?.id // id of the target row }) newDataSource.value.splice(dragIndex.value,1); // remove the current drag item from the data source newDataSource.value.splice(index,0,dragItem.value); // Insert the current drag item into the target row position targetArr.value.forEach((ele:any) => {<!-- --> // Remove the beferLine and afterLine class names of all elements in targetArr ele.classList.remove('beferLine') ele.classList.remove('afterLine') }) targetArr.value = []; // Clear target row array } } } return {<!-- --> customRow, newDataSource } } }) </script>
Parent component uses
<template> <div> <!-- Use child components and bind the dataSource attribute through v-model --> <CustomComponent v-model="dataSource"></CustomComponent> </div> </template> <script> import CustomComponent from '@/path/to/CustomComponent.vue'; export default {<!-- --> components: {<!-- --> CustomComponent }, data() {<!-- --> return {<!-- --> dataSource: [ // Initialize the data source {<!-- --> id: 1, name: 'Item 1' }, {<!-- --> id: 2, name: 'Item 2' }, {<!-- --> id: 3, name: 'Item 3' }, //... ] }; } }; </script>
In the parent component, use the label to introduce the child component CustomComponent, and bind the dataSource attribute of the parent component to the v-model of the child component through the v-model directive. In the data option, initialize the dataSource array as the initial data, and you can modify and supplement data items according to actual needs.
In this way, in the parent component, you can access the data source in the child component by accessing this.dataSource, manipulate it and update it in real time
Summary
This component uses Vue 3’s ref, computed and defineComponent, and the setup hook function.
In the setup hook function, we define the computed property newDataSource to monitor changes in props.dataSource, and dispatch an event named update:dataSource to pass a new data source to the parent component when a change occurs.
At the same time, we also define several responsive variables dragItem, dragIndex and targetArr, which are used to store the current dragged item, the index of the current dragged item and the array of the target row respectively.
Among them, customRow is a method for customizing row content. It returns an object that contains handlers for events such as mouseover, start dragging, dragging, and dropping dragged items.
Finally, in the return value of the component, we return customRow and newDataSource as reactive data for use in templates. antd for component library