Vue2 实现时空穿梭框功能模块
前言
这篇文章主要是分享一个时空穿梭框功能,也就是我们平时用的选择功能。勾选了的项就会进入到另一个框中。
时空穿梭框之旅
示例演示:
这个时空穿梭框实现了:
- 1、可以全选、反选
- 2、没有选中时,不可以点穿梭按钮
- 3、自动计数(共有多少个,选中了多少个)
- 4、没有数据时,全选不可点击
这里主要是想通过这个示例来抛砖引玉,更多的功能,你可以根据自己的实践需要来实现。下面我们就来看看这示例的相关文件及代码。
├── index.html
├── main.js
├── router
│ └── index.js # 路由配置文件
└── components # 组件目录
├── App.vue # 根组件
├── Home.vue # 大的框架结构组件
├── ChangeBox.vue
└── ChangeBoxArea.vue
文件也不多,只要有两个(ChangeBox.vue 和 ChangeBoxArea.vue)下面我们就来看看实现这个示例的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>changebox</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
本示例主要用到了 bootstrap ,所以我们就在 index.html 中引入了 bootstrap 的 cdn。然后我们就可以直接在示例中使用 bootstrap 给我们提供的 UI 了。
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
name: 'Home',
component: Home
}]
})
在这里我们直接把 / 路径的配置到 Home 组件。
<template>
<div id="app">
<Home></Home>
</div>
</template>
<script>
import Home from "@/components/Home";
export default {
name: "App",
components: { Home }
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin-top: 60px;
}
</style>
在根组件中,我们只是做了一件很简单的事,就是引入Home 组件。
<template>
<div>
<change-box></change-box>
</div>
</template>
<script>
import ChangeBox from "@/components/ChangeBox";
export default {
name: "Home",
components: {
ChangeBox
}
};
</script>
Home.vue 组件代码非常地简单,这里其实也可以直接写到根组件上的,但为了养成良好的习惯,我们还是有必要把示例的整体结构往写成更接近实战一些。
好了,上面的基本功做好了之后,我就可以开始这个时空穿梭框的主要代码了的展示了。
<template>
<div class="container">
<div class="row">
<div class="col-md-5">
<change-box-area :title="sourceTitle" :data="sourceList"></change-box-area>
</div>
<div class="col-md-2 text-center">
<p><button :disabled="sourceList.length === 0 || sourceRefNum === 0" class="btn btn-primary" @click="toTarget()">》</button></p>
<p><button :disabled="targetList.length === 0 || targetRefNum === 0" class="btn btn-primary" @click="toSource()">《</button></p>
</div>
<div class="col-md-5">
<change-box-area :title="targetTitle" :data="targetList"></change-box-area>
</div>
</div>
</div>
</template>
<script>
import ChangeBoxArea from "./ChangeBoxArea";
// 这里的 isSeleted 属性可以不用添加,可以在 JS 中进行处理,一般情况下后端返回的数据也不会带有类似这种静态状态的属性
let dataList = [
{ id: 1, name: "HTML5", isSelected: false },
{ id: 2, name: "CSS3", isSelected: false },
{ id: 3, name: "Angular", isSelected: false },
{ id: 4, name: "Vue", isSelected: false },
{ id: 5, name: "Linux", isSelected: false },
{ id: 6, name: "JavaScript", isSelected: false }
];
export default {
components: {
ChangeBoxArea
},
name: "ChangeBox",
data() {
return {
sourceTitle: "请选择",
targetTitle: "已选择",
sourceList: dataList,
targetList: []
};
},
methods: {
exchange(fd, td) {
let selectedItem = fd.filter(item => item.isSelected).map(item => {
return {
...item,
isSelected: false
};
});
td.push(...selectedItem);
return fd.filter(item => !item.isSelected);
},
// 把选择数据转移到目标(右框)
toTarget() {
this.sourceList = this.exchange(this.sourceList, this.targetList);
},
// 把选择数据转回到源(左框)
toSource() {
this.targetList = this.exchange(this.targetList, this.sourceList);
}
},
computed: {
// 源数据中选中的数量
sourceRefNum() {
return this.sourceList.filter(item => item.isSelected).length;
},
// 目标数据中选中的数量
targetRefNum() {
return this.targetList.filter(item => item.isSelected).length;
}
}
};
</script>
接下来我们再来看看最后一个
<template>
<div class="panel panel-default">
<div class="panel-heading clearfix">
<div class="pull-left">
<div class="checkbox">
<label>
<input :disabled="data.length === 0" type="checkbox" @click="toggleAll()" :checked="selectedAllStatus"><span>{{title}}</span>
</label>
</div>
</div>
<span class="pull-right">{{selectItemNumber}}/{{data.length}}</span>
</div>
<div class="panel-body">
<ul>
<li v-for="item in data" :key="item.id">
<div class="checkbox">
<label>
<input type="checkbox" v-model="item.isSelected"> {{item.name}}
</label>
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: "ChangeBox",
props: ["title", "data"],
computed: {
// 选择的数量
selectItemNumber() {
return this.data.filter(item => item.isSelected).length;
},
// 全选状态
selectedAllStatus() {
if (
this.selectItemNumber === this.data.length &&
this.selectItemNumber !== 0
) {
return true;
} else {
return false;
}
}
},
methods: {
// 全选及反选
toggleAll() {
let len = this.data.length;
let slen = this.data.filter(item => item.isSelected).length;
if (len !== slen) {
this.data.map(item => (item.isSelected = true));
} else {
this.data.map(item => (item.isSelected = false));
}
}
}
};
</script>
<style scoped>
ul {
list-style: none;
padding: 0;
}
.checkbox {
margin: 0;
}
</style>
在上面的代码中,有一个地图需要特别的注意下:在全选的input 中我们要使用 :checked 来绑定 selectedAllStatus,而不用 v-model,因为我们的 selectedAllStatus 是一个计算属性,如果把它绑定到 v-model,会报错的:
报错
[Vue warn]: Computed property “selectedAllStatus” was assigned to but it has no setter.
大概意思是说 selectedAllStatus 没有 setter 方法,不能给它赋值,当然,你可以把给这个属性添加 setter 方法,但这样做好像又有点累赘了。为此我们直接使用 :checked 来绑定 selectedAllStatus 属性。
Vue 实现时空穿梭框功能模块就分享到这里,其实这样的需求示例在真实的项目中是有可能出现的,但在项目中这个很有可能会更加复杂,比如:
- 1、左边的框不是平铺的,而是多级,可展开收缩,勾选了的项才会出现在右边的框中
- 2、搜索功能
- 3、不用点中间的两个箭头,而是勾选后,就会自动穿梭到右边去。
这样的需求极为常见,所以你有必要在平时的学习中,把这些东西都自己整理出来,或者把常用的功能模块封装成通用组件,这个对于提高工作效率是非常有用的。花个两三天把它封装成一个常用的组件,以后开发起来,只要遇到这种的基本都可以搬过来用,顶多改改样式,所以也有必要给组件添加必要的属性为定制提供可能。又或者更过分点的,追加一些功能。
Vue2 实现时空穿梭框功能模块的更多相关文章
- Vue实现拖拽穿梭框功能四种方式
一.使用原生js实现拖拽 点击打开视频讲解更加详细 <html lang="en"> <head> <meta charset="UTF-8 ...
- vue2.0 + element ui 实现表格穿梭框
element ui 官网里介绍了穿梭框(Transfer),但在实际使用过程中,会出现一些问题: 1.穿梭框里能放置的内容太少,不能满足复杂的业务需求. 2.当选项过多时,穿梭框很难实现分页,左右两 ...
- Vue2 实现树形菜单(多级菜单)功能模块
结构示意图 ├── index.html ├── main.js ├── router │ └── index.js # 路由配置文件 ├── components # 组件目录 │ ├── App. ...
- layui实现类似于bootstrap的模态框功能
以前习惯了bootstrap的模态框,突然换了layui,想的用layui实现类似于bootstrap的模态框功能. 用到了layui的layer模块,例如: <!DOCTYPE html> ...
- 自定义SWT控件五之自定义穿梭框
5.自定义穿梭框 package com.view.control.shuttlebox; import java.util.ArrayList; import java.util.HashMap; ...
- krry-transfer ⏤ 基于 element 的升级版穿梭框组件发布到 npm 啦
博客地址:https://ainyi.com/81 基于 element ui 的==升级版穿梭框组件==发布到 npm 啦 看过我之前博客的同学或许知道我之前写过关于 element 穿梭框组件重构 ...
- VUE+ElementUI实现左侧为树形结构、右侧无层级结构的穿梭框
工作中遇到一个需求,需要将一个数据选择做成穿梭框,但是要求穿梭框左侧为树形结构.右侧为无层级结构的数据展示,ElementUI自身无法在穿梭框中添加树形结构,网上搜到了大佬封装的插件但是对于右侧的无树 ...
- struts-hibernate-ajax完成区县和街道级联下拉框功能(二补充使用json解析list结果集,ajax循环json层级处理)
针对<struts-hibernate-ajax完成区县和街道级联下拉框功能>进行补充,上一篇中,要在action中拼接JSON格式字符串,很容易手抖.直接用json处理一下转成json格 ...
- 用jsonp实现搜索框功能
用jsonp实现搜索框功能 前面的话: 在上周本来想发一篇模仿必应搜索的界面.但是在准备写文章之前突然想到前面学习了ajax技术,在这里我也让我的页面有一种不需要手动刷新就能获取到数据.但是发现用前面 ...
随机推荐
- Spring-quartz定时系统多任务配置
<!-- 启动触发器的配置开始 --> <bean name="startQuertz" lazy-init="false" autowire ...
- 高手教您编写简单的JSON解析器
编写JSON解析器是熟悉解析技术的最简单方法之一.格式非常简单.它是递归定义的,所以与解析Brainfuck相比,你会遇到轻微的挑战 ; 你可能已经使用JSON.除了最后一点之外,解析 Scheme的 ...
- 安装electron-react-boilerplate遇到的问题
一.yarn安装缓慢 // 查看下载源 yarn config get registry // 修改下载源 yarn config set registry https://registry.npm. ...
- 从头开始开发一个vue幻灯片组件
首先新建项目vue init webpack projectName 安装依赖包npm i这些就不说了 接下来就是构建我们的swiper组件 因为我写的代码不规范, 通不过eslint的检测, 会频繁 ...
- Codeforces 803E--Roma and Poker (DP)
原题链接:http://codeforces.com/problemset/problem/803/E 题意:给一个n长度的字符串,其中'?'可以替换成'D'.'W'.'L'中的任意一种,'D'等价于 ...
- Gym-100676F Palindrome
原题连接:https://odzkskevi.qnssl.com/1110bec98ca57b5ce6aec79b210d2849?v=1491063604 题意: 多组输入,每一次输入一个n(字符串 ...
- TList TObjectList的区别和使用
所在的单元 TList(Classes.pas) TObjectList(Contnrs.pas) TObjectList对象的创建方法有一个参数: constructor TObjectList.C ...
- charles抓包看性能数据
1.优化某个接口或加载速度(H5加载速度慢) 抓包看Overview ①看Duration,就是接口的加载时间 ②看Latency,就是延时一端传播到另一端所花费的时间:一般和网络有关:可以综合Dur ...
- Font and PDF
1. 独立存在的Font文件 有三类: Type 1 Font TrueType Font OpenType Font Type 1 是由Adobe开发的,它是基于PostScript的Font,它通 ...
- Tex与PDF
由Knuth Donald开发的tex.web会生成DVI文件,DVI也是Knuth自己实现的(虽然概念是其他人提出的)一种文件格式,目标是与设备无关. 通过dvips程序可以将DVI格式转化成Pos ...