Vue使用vue-draggable 插件在不同列表之间拖拽功能

今天分享一个vue项目中在不同列表拖拽设置选项的功能,这个功能也是在做项目中遇到的,先说下这个功能的要点(参考下图),有2个列表,左侧列表展示已选,右侧列表展示未选,通过拖拽进行设置,已选的选项不能超过4个,超过的话自动将拖拽之前的最后一项清除到右侧,且如果从已选往未选里拖的时候,右侧显示垃圾桶的提示(如图)。

拖拽功能图片:

垃圾桶显示图:

首先讲讲vue-draggable的使用

安装vue-draggable:

npm install vuedraggable

在使用插件的组件内引入vue-draggable并注册组件:

1

2

3

4

5

import draggable from "vuedraggable"

 

components: {

 draggable

}

然后在我们需要拖拽的列表中使用:

1

2

3

4

5

6

7

8

9

10

11

<draggable class="selected-list" tag="ul"

v-model="selectedTheme"

v-bind="dragOptions"

 :move="onMove"

 @end="onEnd"

 >

 <li class="selected-theme"

 v-for="item in selectedTheme"

 :key="item.type"

 >{{item.name}}</li>

</draggable>

下面是拖拽功能组件的完整代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

<template>

 <div class="theme-setting">

 <el-dialog

 title="设置选项"

 :visible.sync="dialogVisible"

 width="648px"

 :close-on-click-modal="false"

 >

 <div class="theme-left">

  <dl class="theme-title">

  <dt class="title">当前选项</dt>

  <dd class="des">从右侧拖拽添加</dd>

  </dl>

  <draggable class="selected-list" tag="ul"

  v-model="selectedTheme"

  v-bind="dragOptions"

  :move="onMove"

  @end="onEnd"

  >

  <li class="selected-theme"

  v-for="item in selectedTheme"

  :key="item.type"

  >{{item.name}}</li>

  </draggable>

 </div>

 <div class="theme-right">

  <h3 class="theme-right-title">全部选项</h3>

  <draggable class="theme-right-list" tag="ul"

  v-model="unSelectTheme"

  v-bind="dragOptions"

  :move="onMove"

  @end="onEnd">

  <li class="theme-right-item"

  v-for="item in unSelectTheme"

  :key="item.type"

  >{{item.name}}</li>

  </draggable>

 </div>

 <div class="drag-drop-del" v-show="isShowDel">

  <img src="../assets/imgs/drapDrop/drag_drop_del.png" alt="">

 </div>

 <span slot="footer" class="dialog-footer">

  <el-button @click="restoreDefault">恢复默认设置</el-button>

  <el-button type="primary" @click="saveThemeSet">保存</el-button>

 </span>

 </el-dialog>

 </div>

</template>

 

<script>

import {Message} from 'element-ui'

import draggable from "vuedraggable"

 export default {

 name: 'DragDrop',

 components: {

 draggable

 },

 data() {

 return {

  dialogVisible: false,

  selectedTheme: [{

  type: 1,

  name: '选项1'

  }, {

  type: 2,

  name: '选项2'

  }, {

  type: 3,

  name: '选项3'

  }, {

  type: 4,

  name: '选项4'

  }], // 已选主题列表

  unSelectTheme: [{

  type: 5,

  name: '选项5'

  }, {

  type: 6,

  name: '选项6'

  }], // 未选主题列表

  backSelectedTheme: [], // 选主题列表备份

  backUnSelectTheme: [], // 未选主题列表备份用于恢复默认设置

  relatedListLast: {}, // 已选主题列表最后一项

  isShowDel: false

 }

 },

 methods: {

 showDrag() {

  this.dialogVisible = true

 },

 onMove({ relatedContext, draggedContext, to }) {

  const relatedElement = relatedContext.element

  const draggedElement = draggedContext.element

  let dragInEl = to['className']

  if (dragInEl == 'selected-list') {

  this.isShowDel = false

  if (this.selectedTheme.length === 4) {

   // 判断往已选列表拖时,如果已经满足4项,则记录已选列表的最后一项

   // 拖拽结束时将此项清除到未选列表中

   this.relatedListLast = this.selectedTheme[this.selectedTheme.length-1]

  }

  } else {

  this.isShowDel = true // 判断如果是往未选列表里拖的话显示垃圾桶

  }

  return (

  (!relatedElement || !relatedElement.fixed) && !draggedElement.fixed

  )

 },

 onEnd(dragObj) {

  let dragInEl = dragObj.to['className']

  if (dragInEl == 'selected-list') {

  if (this.selectedTheme.length > 4) {

   // 判断已选列表大于4项,将记录的最后一项过滤出来,并push到未选列表数组

   this.selectedTheme = this.selectedTheme.filter(item => {

   return item.type != this.relatedListLast.type

   })

   this.unSelectTheme.push(this.relatedListLast)

  }

  }

  if (dragInEl === 'theme-right-list') {

  // 判断是往未选列表拖时,拖拽结束时将垃圾桶隐藏

  this.isShowDel = false

  }

 },

 // 保存设置

 saveThemeSet() {

  const params = {

  taskTopicList: this.selectedTheme

  }

  if (this.selectedTheme.length !== 4) {

  Message({

   type: 'error',

   message: '需设置4个选项 !'

  })

  return false

  }

  $ajax.save(params).then(data => {

  this.dialogVisible = false

  Message({

   type: 'success',

   message: '保存成功!'

  })

  this.$parent.refresh()

  }).catch(err => {

  console.log(err)

  })

 },

 // 恢复默认设置

 restoreDefault() {

  this.selectedTheme = this.backSelectedTheme

  this.unSelectTheme = this.backUnSelectTheme

 }

 },

 computed: {

 dragOptions() {

  return {

  animation: 0,

  group: "description",

  disabled: false,

  ghostClass: "ghost"

  }

 }

 }

 };

</script>

<style lang="less" scoped>

body, ul, dl, dt, dd, li, h1, h3{

 margin: 0;

 padding: 0;

}

ul, ol, li {

 list-style: none;

}

.theme-setting {

 /deep/.el-dialog {

 height: 476px;

 border-radius: 6px;

 .el-dialog__header {

  height: 55px;

  line-height: 56px;

  padding: 0;

  border-bottom: 1px solid rgba(13,20,30, 0.1);

  .el-dialog__title {

  height:21px;

  font-size:16px;

  font-family:MicrosoftYaHei-Bold,MicrosoftYaHei;

  font-weight:bold;

  color:rgba(13,20,30,1);

  line-height:21px;

  }

  .el-dialog__headerbtn {

  margin-top: -4px;

  }

 }

 .el-dialog__body {

  position: relative;

  display: flex;

  height: 331px;

  padding: 0;

  border-bottom: 1px solid rgba(13,20,30, 0.1);

  .theme-left {

  width: 218px;

  margin-left: 24px;

  border-right: 1px solid rgba(13,20,30, 0.1);

  .theme-title {

   display: flex;

   margin-top: 24px;

   .title {

   height:19px;

   margin-right: 4px;

   font-size:14px;

   font-family:MicrosoftYaHei-Bold,MicrosoftYaHei;

   font-weight:bold;

   color:rgba(13,20,30,1);

   line-height:19px;

   }

   .des {

   height:16px;

   font-size:12px;

   font-family:MicrosoftYaHei;

   color:rgba(13,20,30,0.6);

   line-height:19px;

   }

  }

  .selected-list {

   height: 240px;

   margin-top: 24px;

   overflow: hidden;

   .selected-theme {

   width:160px;

   height:48px;

   line-height:48px;

   text-align: center;

   margin-bottom: 16px;

   cursor: pointer;

   background:linear-gradient(180deg,rgba(43,46,83,1) 0%,rgba(108,116,150,1) 100%);

   border-radius:6px;

   font-size:14px;

   font-family:MicrosoftYaHei;

   color:rgba(255,255,255,1);

   }

  }

  }

  .theme-right {

  padding: 0 24px;

  .theme-right-title {

   padding-top: 24px;

   height:19px;

   font-size:14px;

   font-family:MicrosoftYaHei-Bold,MicrosoftYaHei;

   font-weight:bold;

   color:rgba(13,20,30,0.4);

   line-height:19px;

  }

  .theme-right-list {

   width: 357px;

   height: 240px;

   overflow: scroll;

   margin-top: 24px;

   .theme-right-item {

   width: 160px;

   height:48px;

   line-height:48px;

   float: left;

   margin-right: 16px;

   margin-bottom: 16px;

   background:rgba(247,248,252,1);

   border-radius:6px;

   font-size:14px;

   font-family:MicrosoftYaHei;

   color:rgba(13,20,30,0.4);

   text-align: center;

   cursor: pointer;

   }

  }

  .theme-right-list::before, .theme-right-list::after {

   content: "";

   display: table;

  }

  .theme-right-list::after {

   clear: both;

  }

  }

  .drag-drop-del {

  position: absolute;

  right: 1px;

  top: 0;

  width: 404px;

  height: 331px;

  display: flex;

  justify-content: center;

  align-items: center;

  background-image: url('../../src/assets/imgs/drapDrop/drag_drop.png');

  img {

   width: 96px;

   height: 96px;

  }

  }

 }

 .el-dialog__footer {

  height: 88px;

  padding: 24px 24px 0;

  .dialog-footer {

  .el-button+.el-button {

   margin-left: 16px;

  }

  }

 }

 }

}

</style>

总结

到此这篇关于Vue使用vue-draggable 插件在不同列表之间拖拽功能的文章就介绍到这了,更多相关vue vue-draggable 插件 拖拽内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值