├── babel.config.js ├── public ├── favicon.ico └── index.html ├── examples ├── assets │ ├── logo.png │ ├── step1.gif │ ├── step2.gif │ └── step3.png ├── main.js ├── components │ ├── childComponent │ │ └── exampleChild1.vue │ ├── example1.vue │ ├── example3.vue │ └── example2.vue └── App.vue ├── .npmignore ├── lib └── demo.html ├── packages ├── card-dragger │ ├── index.js │ └── src │ │ └── card-dragger.vue └── index.js ├── .gitignore ├── vue.config.js ├── package.json └── README.md /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwanda/dragComponent/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /examples/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwanda/dragComponent/HEAD/examples/assets/logo.png -------------------------------------------------------------------------------- /examples/assets/step1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwanda/dragComponent/HEAD/examples/assets/step1.gif -------------------------------------------------------------------------------- /examples/assets/step2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwanda/dragComponent/HEAD/examples/assets/step2.gif -------------------------------------------------------------------------------- /examples/assets/step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwanda/dragComponent/HEAD/examples/assets/step3.png -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # 忽略目录 2 | examples/ 3 | packages/ 4 | public/ 5 | 6 | # 忽略指定文件 7 | vue.config.js 8 | babel.config.js 9 | *.map 10 | -------------------------------------------------------------------------------- /lib/demo.html: -------------------------------------------------------------------------------- 1 | 2 | carddragger demo 3 | 4 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | // import {installCardDragger} from '../packages/index' 5 | // 注册组件库 6 | // Vue.use(installCardDragger) 7 | 8 | Vue.config.productionTip = false 9 | 10 | new Vue({ 11 | render: h => h(App), 12 | }).$mount('#app') 13 | -------------------------------------------------------------------------------- /packages/card-dragger/index.js: -------------------------------------------------------------------------------- 1 | 2 | // 导入组件,组件必须声明 name 3 | import cardDragger from './src/card-dragger.vue' 4 | 5 | // 为组件提供 install 安装方法,供按需引入 6 | cardDragger.install = function (Vue) { 7 | Vue.component(cardDragger.name, cardDragger) 8 | } 9 | 10 | // 默认导出组件 11 | export default cardDragger 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /lib 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /packages/index.js: -------------------------------------------------------------------------------- 1 | // 导入颜色选择器组件 2 | import cardComponent from './card-dragger' 3 | 4 | export const cardDragger = cardComponent 5 | 6 | // 存储组件列表 7 | const components = [ 8 | cardDragger 9 | ] 10 | 11 | // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册 12 | export const installCardDragger = function (Vue) { 13 | // 判断是否安装 14 | if (installCardDragger.installed) return 15 | // 遍历注册全局组件 16 | components.map(component => Vue.component(component.name, component)) 17 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | carddragger 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/components/childComponent/exampleChild1.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 23 | 33 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 修改 src 为 examples 3 | pages: { 4 | index: { 5 | entry: 'examples/main.js', 6 | template: 'public/index.html', 7 | filename: 'index.html' 8 | } 9 | }, 10 | css: { 11 | extract:false 12 | }, 13 | // 扩展 webpack 配置,使 packages 加入编译 14 | chainWebpack: config => { 15 | config.module 16 | .rule('js') 17 | .include 18 | .add('/packages') 19 | .add('/examples') 20 | .end() 21 | .use('babel') 22 | .loader('babel-loader') 23 | .tap(options => { 24 | // 修改它的选项... 25 | return options 26 | }) 27 | } 28 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carddragger", 3 | "version": "0.3.6", 4 | "private": false, 5 | "description": "基于vue的卡片拖拽排列组件", 6 | "main": "lib/carddragger.umd.min.js", 7 | "keywords": [ 8 | "carddragger", 9 | "dragger", 10 | "mover" 11 | ], 12 | "author": "https://juejin.im/user/5c25eae2e51d4573c84905c6", 13 | "license": "MIT", 14 | "scripts": { 15 | "serve": "vue-cli-service serve", 16 | "build": "vue-cli-service build", 17 | "lib": "vue-cli-service build --target lib --name carddragger --dest lib packages/index.js" 18 | }, 19 | "dependencies": { 20 | "core-js": "^2.6.5", 21 | "vue": "^2.6.10" 22 | }, 23 | "devDependencies": { 24 | "@vue/cli-plugin-babel": "^3.11.0", 25 | "@vue/cli-service": "^3.11.0", 26 | "vue-template-compiler": "^2.6.10" 27 | }, 28 | "postcss": { 29 | "plugins": { 30 | "autoprefixer": {} 31 | } 32 | }, 33 | "browserslist": [ 34 | "> 1%", 35 | "last 2 versions" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /examples/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 38 | 39 | 45 | -------------------------------------------------------------------------------- /examples/components/example1.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 69 | 70 | 71 | 107 | -------------------------------------------------------------------------------- /examples/components/example3.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 73 | 74 | 75 | 111 | -------------------------------------------------------------------------------- /examples/components/example2.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 74 | 75 | 76 | 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 一个**用vue实现的拖拽排列卡片组件** 2 | 3 | **具体效果请参考:[文章链接](https://juejin.im/post/5da53e29e51d457822796ed8)** 4 | 5 | 6 | **这是vue实现的拖动卡片组件,主要实现了**: 7 | - 拖动卡片与其他卡片的位置更换,并且其他卡片根据拖动的位置自动顺移,位置数据实时更新 8 | - 拖动的时候可使用鼠标滚动 9 | - 卡片根据数据生成,所有参数和内容都是可以自定义的,方便应用于不同场景 10 | - 不同操作的事件都可获取到,拖动后的位置数据会实时更新 11 | - 可以全局安装和按需加载 12 | 13 | #### 更多详情请见: 14 | - [x] [第一篇为组件封装后的使用文档及介绍](https://juejin.im/post/5da53e29e51d457822796ed8) 15 | - [x] [第二篇为组件的实现思路以及细节](https://juejin.im/post/5dae5daae51d4524c24821de) 16 | - [ ] 第三篇为将组件打包并上传至npm,如何实现按需加载和下载后使用的问题 17 | 18 | ## 如何使用? 19 | #### 下载carddragger 20 | 21 | ``` 22 | npm install carddragger 23 | ``` 24 | 25 | ``` 26 | 当前稳定版本:0.3.6,更新于10月24日早上11点 27 | ``` 28 | #### 全局安装 29 | 在你vue项目的入口js文件中使用,vue-cli生成的项目一般为main.js文件 30 | 31 | ``` 32 | import {installCardDragger} from 'carddragger' 33 | Vue.use(installCardDragger) 34 | ``` 35 | 36 | #### 按需加载 37 | 在组件中直接import 38 | 39 | ``` 40 | import { cardDragger } from 'carddragger' 41 | 42 | export default { 43 | components:{ 44 | cardDragger, 45 | } 46 | } 47 | ``` 48 | #### 使用示例 49 | **1.基础使用:** 50 | ``` 51 | 55 | 68 | ``` 69 | 70 | **2.完整示例:** 71 | 参照[**源码仓库**](https://github.com/dwanda/dragComponent)中的examples 72 | 将整个项目clone下来,npm install+npm run serve即可看到完整示例 73 | 74 | ## Props(参数) 75 | 属性 | 说明| 类型| 默认值 76 | ---|---|---|--- 77 | data | 必填,需要传入的卡片数据,具体格式请看下方解释| Array| - 78 | colNum | 卡片排列的列数| Number| 2 79 | cardOutsideWidth| 卡片外部需要占据的宽度(包括无内容部分)| Number| 590 80 | cardOutsideHeight| 卡片外部需要占据的高度(包括无内容部分)| Number| 380 81 | cardInsideWidth| 卡片的宽度| Number| 560 82 | cardInsideHeight| 卡片的高度| Number| 320 83 | 84 | ![](https://user-gold-cdn.xitu.io/2019/10/21/16dec11bdf2c725c?w=1479&h=702&f=png&s=31102) 85 | #### data格式示例: 86 | 卡片的内容根据data数据生成或自定义 87 | 88 | ``` 89 | 102 | 103 | 118 | ``` 119 | 120 | 属性 | 说明| 类型| 默认值 121 | ---|---|---|--- 122 | id | 必填,设置卡片的id作为唯一识别| String| - 123 | positionNum | 必填,设置卡片位置,从1开始依次递增| Number| - 124 | name | 选填,设置卡片的标题名称| String| '默认标题' 125 | componentData | 选填,设置卡片的内容为组件数据,如果此参数具有数据的话,则slot传入的数据失效| 组件| - 126 | 127 | ## Slot(插槽) 128 | 首先先介绍一下,卡片内容分为上下两部分: 129 | - 上部分为卡片的**标题栏**,并且拖拽事件只有点击上部分才触发 130 | - 下部分为卡片的**内容** 131 | 132 | 两个部分都是可以进行自定义内容及样式的。若不添加的自定义内容的话,标题栏和内容都是默认背景为白色,显示data中的name。**若添加了自定义内容则背景需要自己设置。** 133 | 134 | #### 标题栏插槽 135 | 136 | ``` 137 | 138 | 141 | 148 | 149 | ``` 150 | 151 | #### 内容插槽 152 | ``` 153 | 154 | 155 | 160 | 161 | ``` 162 | 你也可以 163 | 164 | ``` 165 | 166 | 167 | 171 | 172 | 173 | //省略部分代码,加载你的组件 174 | import exampleChild1 from "./childComponent/exampleChild1" 175 | 176 | cardList: [ 177 | { 178 | positionNum: 1, 179 | name: "演示卡片1", 180 | id: "card1", 181 | OtherData:exampleChild1 182 | //OtherData这个是你自己定义的属性,注意不可与componentData属性名字重复 183 | } 184 | ] 185 | 186 | ``` 187 | 188 | 关于内容我做了另外一个判断,你可以将需要的组件放在data的componentData属性里面,内容会自动读取componentData的数据。当然你直接都使用slot就可以忽略这个属性。 189 | 190 | ``` 191 | import exampleChild1 from "./childComponent/exampleChild1" 192 | //省略部分代码 193 | cardList: [ 194 | { 195 | positionNum: 1, 196 | name: "演示卡片1", 197 | id: "card1", 198 | componentData:exampleChild1 //直接设置即可使用 199 | } 200 | ] 201 | //使用componnetData属性传入的组件,可使用Props获取到单个卡片数据 202 | //在子组件中使用props即可使用 203 | props:{ 204 | itemData:{ 205 | type:Object 206 | } 207 | } 208 | ``` 209 | 210 | **渲染优先级**:data的componentData > slot > 默认内容 211 | 212 | ## Events(事件) 213 | 214 | ### startDrag 215 | > **作用**: 216 | > 在点击卡片顶部标题栏的时候,触发此函数 217 | 218 | > **参数**: 219 | > startDrag(event,id) 220 | > 221 | > 第一个参数event,是点击事件的原生event 222 | > 第二个参数id,是选中的卡片的id 223 | 224 | 225 | ### swicthPosition 226 | > **作用**: 227 | > 在拖动一个卡片到另外一个卡片的位置的时候,触发此事件 228 | 229 | > **参数**: 230 | > swicthPosition(oldPositon,newPositon,originItem) 231 | > 232 | > 第一个参数oldPositon,是卡片原来的位置号码 233 | > 第二个参数newPositon,是卡片需要交换的位置号码 234 | > 第三个参数originItem,是卡片交换完成后的数据 235 | 236 | ### finishDrag 237 | > **作用**: 238 | > 拖拽完成松开鼠标后,触发此事件 239 | 240 | > **参数**: 241 | > swicthPosition(oldPositon,newPositon,originItem) 242 | > 243 | > 第一个参数oldPositon,是卡片原来的位置号码 244 | > 第二个参数newPositon,是卡片需要交换的位置号码 245 | > 第三个参数originItem,是卡片交换完成后的数据 246 | 247 | 248 | ## 考虑修复的问题 249 | 1.data的positionNum出现空缺则会报错,必须从1依次递增。但好像这种场景也不常用,考虑修复ing。 250 | 251 | 252 | ## 未来计划 253 | - [ ] 如果有需要的话我再封装个react版本 254 | - [ ] 修改其他需要的参数和进行扩展 255 | 256 | **觉得这个系列有点意思的话,点个星星支持一下呗!** 257 | -------------------------------------------------------------------------------- /packages/card-dragger/src/card-dragger.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 276 | 327 | --------------------------------------------------------------------------------