ES6的Set和Map区别是:Set是“集合”结构,而Map是“字典”结构;Set是以[value, value]的形式存储元素,而Map是以[key, value]的键值对形式存储元素;Map可以用get()键查找到特定值并返回,而Set不行。
方法名 | 参数 | 返回值 | 描述 |
---|---|---|---|
add | value | 实例Set | 新增,相当于Array里的push |
delete | value | Boolean | 集合中存在,则删除其value |
has | value | Boolean | 判断集合中是否存在value |
clear | 清空集合 | ||
keys | iterable | 返回一个包含集合中所有键的迭代器 | |
values | iterable | 返回一个包含集合中所有值的迭代器 | |
entries | iterable | 返回一个包含Set对象中所有元素的键值对迭代器 | |
forEach | 用于对集合成员执行callback回调函数操作,如果提供了this Arg参数,回调中的this会是这个参数,没有返回值。 |
注意:
方法 | 参数 | 返回值 | 描述 |
---|---|---|---|
set | (key, value) | 实例Map | 向字典中添加新元素 |
get | key | value | 通过键查找特定的数值并返回 |
has | key | Boolean | 判断字典中是否存在键key |
delele | key | Boolean | 通过键key从字典中移除对应的数据 |
clear | 将这个字典中的所有元素删除 | ||
keys | iterable | 将字典中包含的所有键名以迭代器形式返回 | |
values | iterable | 将字典中包含的所有数据以迭代器形式返回 | |
entries | iterable | 返回所有成员的迭代器 | |
forEach | 遍历字典的所有成员 |
注意:
最近在研究Vue项目的本地模拟数据时,发现ES6的Set和Map可以很好实现本地数据的增删改查,也解决了Array会存储重复数据问题。对于某些项目特定需求,是有帮助的,这里通过以下小案例,让大家了解如何使用它们。
注:axios和mockjs上两篇已介绍,不清楚可以翻看下。
在mock目录中,创建data.js文件,data.js是本地模拟数据库,里在存储各种数据,代码如下:
import { mock } from 'mockjs'
//实例Map,定义一个存储数据的 数据表
const DBMap = new Map();
export default DBMap;
import { mock } from 'mockjs'
//实例Map,定义一个存储数据的 数据表
const DBMap = new Map();
//实例Map,定义一个存储栏目的 数据集
const category = new Map();
//将栏目数据集 存储到 数据表中
DBMap.set("栏目列表", category);
export default DBMap;
在data.js中,通过mockjs生成栏目模拟数据,然后循环追加到集合中,代码如下:
let _index = 1;
//使用mock生成栏目模拟数据
mock({
'data|5': [
{
'name|+1': opt => { return '菜单栏目' + _index; },
'id': '@id',
'path': opt => { return '/category/column' + (_index++); }
}
]
})['data'].forEach(item => {
category.set(item.id, item);
})
console.log(category);
控制台输出结果如下图:
在mock目录中,创建index.js来定义模拟数据的接口,具体用法上一篇已详细讲解。
import DBMap from './data'
//获取所有栏目
mock("/api/category", "get", (req, res) => {
let _result = [];
//获取栏目数据
let _category = DBMap.get("栏目列表");
let _isDone = false;
//循环获取数据
try{
let _keys = _category.keys();
do {
let _next = _keys.next();
_isDone = _next.done;
if(_next.value){
_result.push(_category.get(_next.value))
}
} while (!_isDone);
}catch(e){}
return {
code: 200,
message: 'success',
data: _result
}
});
在api目录创建api.js,用来定义接口请求函数,代码如下:
import service from '@/utils/request'
//获取栏目数据
export const getCategory = () => {
return service.get('/api/category', {});
}
import { getCategory } from '@/api/api'
export default {
data(){
return {
categoryList: []
}
},
created(){
this.updateList();
},
methods: {
//获取栏目列表
updateList(){
getCategory().then(res => {
if(res.code == 200){
this.categoryList = res.data;
}
console.log(res);
}).catch(error => {
console.error(error);
})
}
}
}
控制台输出结果如下图:
通过实现下图案例,完成增删改功能演示。
1)mock目录中index.js增加栏目的添加模拟接口
import { mock } from 'mockjs'
//增加栏目
mock("/api/category", "post", (req, res) => {
let _result = "",
_code = 0,
_data = mock({'id': '@id'});
if(req['body']){
//获取栏目数据
let _category = DBMap.get("栏目列表");
_category.set(_data.id, mock({
'name': req.body,
'id': _data.id,
'path': opt => { return '/category/column' + _category.size; }
}))
_code = 200;
_result = "保存成功";
}else{
_result = "请输入栏目名称";
}
return {
code: _code,
message: _result,
data: null
}
});
2)api目录的api.js中添加请求接口函数
//添加栏目
export const addCategory = param => {
return service.post('/api/category', param);
}
3)页面中增加“添加事件函数“
import { getCategory, addCategory } from '@/api/api'
export default {
data(){
return {
categoryList: []
}
},
created(){
this.updateList();
},
methods: {
//获取栏目列表
updateList(){
getCategory().then(res => {
if(res.code == 200){
this.categoryList = res.data;
}
console.log(res);
}).catch(error => {
console.error(error);
})
},
//添加栏目事件
addCategory(){
this.$prompt('请输入栏目名称', '提示', {
confirmButtonText: '保存',
cancelButtonText: '取消',
}).then( res => {
addCategory(res.value).then(res => {
if(res.code==200){
this.$message.success(res.message);
this.updateList();
}else{
this.$message.error(res.message);
}
});
}).catch( () => {
this.$message({
type: 'info',
message: '已取消'
});
});
},
//end
}
}
以上几步完成后,页面中点击添加事件,会弹出如下图输入框:
输入完成保存后,重新获取栏目列表,新添加栏目已在列表中了,结果如下图:
这边在每个栏目上添加了悬浮显示编辑和删除功能按钮,鼠标放到对应栏目项,则显示操作按钮。如下图:
1)mock目录中index.js增加栏目的修改模拟 接口
//修改栏目名称
mock("/api/category", "put", (req, res) => {
let _result = "",
_code = 0;
if(req['body']){
//获取栏目数据
let _data = JSON.parse(req.body),
_category = DBMap.get("栏目列表"),
_column = _category.get(_data['id']);
//修改栏目名称
_column['name'] = _data['name'];
_code = 200;
_result = "修改成功";
}else{
_result = "参数格式错误";
}
return {
code: _code,
message: _result,
data: null
}
});
2)api目录中api.js增加修改请求接口函数
//修改栏目
export const editCategory = param => {
return service.put('/api/category', param);
}
3)页面的methods中增加“修改事件函数”
//编辑栏目名称事件
editCategory(_id, _name){
this.$prompt('请输入栏目名称', '提示', {
confirmButtonText: '保存',
cancelButtonText: '取消',
inputValue: _name
}).then( res => {
editCategory({
id: _id,
name: res.value
}).then(res => {
if(res.code==200){
this.$message.success(res.message);
this.updateList();
}else{
this.$message.error(res.message);
}
})
}).catch( () => {
this.$message({
type: 'info',
message: '已取消'
});
});
}
//end
以上几步完成后,鼠标放到“菜单栏目3”上,点击编辑图标,弹出修改弹框,将“菜单栏目3”修改成”家电电器“,如下图:
输入完成点击保存后,重新获取栏目列表,列表中名称已被修改了,结果如下图:
这时,栏目中”新添加的栏目“不需要了,通过删除功能移出掉。
1)mock目录中index.js增加栏目的删除模拟接口
//修改栏目名称
mock("/api/category", "delete", (req, res) => {
let _result = "",
_code = 0;
if(req['body']){
//获取栏目数据
let _category = DBMap.get("栏目列表");
if(_category.has(req.body)){
_category.delete(req.body);
_code = 200;
_result = "删除成功";
}else{
_result = "该栏目不存在~";
}
}else{
_result = "请传入需要删除项的ID";
}
return {
code: _code,
message: _result,
data: null
}
});
2)api目录中api.js增加删除请求接口函数
//删除栏目
export const deleteCategory = param => {
return service.delete('/api/category', {
data: param
});
}
3)页面的methods中增加”删除事件函数“
//删除指定栏目
deleteCategory(_id){
this.$confirm('此操作将永久删除该栏目,是否继续?', "提示", {
confirmButtonText: "确认删除",
cancelButtonText: "取消",
type: "warning"
}).then(res => {
deleteCategory(_id).then(res => {
if(res.code==200){
this.$message.success(res.message);
this.updateList();
}else{
this.$message.error(res.message);
}
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
});
});
},
点击删除图标后,会出出确认是否删除弹框如下图:
点击确认后,栏目列表位置”新添加的栏目“就被删除了。
现在我们来实现添加关键词功能,给每个栏目单独添加关键,这时就用到了Set集合了,它可以存储无重复元素。
Html代码如下:
//...
JS代码如下:
export default {
data(){
return {
categoryList: [],
//当前选中栏目索引值
categoryIndex: 0,
//右侧关键词数据集
tagsList: []
}
},
methods: {
//选择栏目事件
changeMenuEvent(index){
this.categoryIndex = index;
},
...
}
}
如上代码,将changeMenuEvent函数绑定到菜单栏目元素的Dom的@click事件上即可。
这里将3.1和3.2 中的代码进行稍微修改,代码如下:
import { mock } from 'mockjs'
//实例Map,定义一个存储数据的 数据表
const DBMap = new Map();
//实例Map,定义一个存储栏目的 数据集
const category = new Map();
//实例Map,定义一个存储关键词的数据集
const tags = new Map();
//数据集 存储到 数据表中
DBMap.set("栏目列表", category);
DBMap.set("关键词列表", tags);
//通过mock随机生成栏目名
let _index = 1;
//使用mock生成栏目模拟数据
mock({
'data|5': [
{
'name|+1': opt => { return '菜单栏目' + _index; },
'id': '@id',
'path': opt => { return '/category/column' + (_index++); }
}
]
})['data'].forEach(item => {
tags.set(item.id, new Set());
category.set(item.id, item);
})
1)mock目录中index.js增加获取关键词列表模拟接口
//获取关键词列表
mock("/api/tags", "get", (req, res) => {
let _result = [],
_code = 0,
_msg = "";
//获取关键词数据
let _tags = DBMap.get("关键词列表");
if(req['body']){
try{
let _setData = _tags.get(req.body),
_values = _setData.values(),
_isDone = false;
if(_setData.size!=0){
//循环获取数据
do{
let _next = _values.next();
_isDone = _next.done;
if(_next.value){
_result.push(_next.value);
}
} while(!_isDone);
}
_code = 200;
_msg = "success";
}catch(e){
_code = 0;
_msg = JSON.stringify(e);
}
}else{
_code = 0;
_msg = "请传入栏目ID";
}
return {
code: _code,
message: _msg,
data: _result
}
});
2)api目录中api.js增加获取关键词请求接口函数
//获取关键词列表
export const getTagsList = param => {
return service.get('/api/tags', {
data: param
});
}
3)页面的methods中增加“获取关键词列表”事件函数
//获取关键词列表
updateTags(){
let _id = this.categoryList[this.categoryIndex]['id'];
getTagsList(_id).then(res => {
if(res.code==200){
this.tagsList = res.data;
}
})
}
这时,每个栏目中还有没有关键词,所有获取是空数组。还需要注意一件事,就是获取关键词列表事件函数已定义,需要在栏目切换时,重新获取关键词列表数据,changeMenuEvent事件函数修改如下:
//选择栏目事件
changeMenuEvent(index){
this.categoryIndex = index;
this.updateTags();
},
1)mock目录中index.js增加 添加关键词模拟接口
//栏目中添加关键词信息
mock("/api/tags", "post", (req, res) => {
let _result = [],
_code = 0,
_msg = "";
//获取关键词数据
let _tags = DBMap.get("关键词列表");
if(req['body']){
try{
let _data = JSON.parse(req.body),
_setData = _tags.get(_data.id);
_setData.add(_data['name']);
_code = 200;
_msg = "success";
}catch(e){
_code = 0;
_msg = JSON.stringify(e);
}
}else{
_code = 0;
_msg = "请传入栏目ID";
}
return {
code: _code,
message: _msg,
data: _result
}
});
2)api目录中api.js增加 添加关键词请求接口函数
//添加关键词信息
export const addTags = param => {
return service.post('/api/tags', param);
}
3)页面的methods中增加“添加关键词”事件函数
//添加关键词
addTagsEvent(){
let _id = this.categoryList[this.categoryIndex]['id'];
this.$prompt('请输入关键词名称', '提示', {
confirmButtonText: '保存',
cancelButtonText: '取消',
}).then( res => {
addTags({
id: _id,
name: res.value
}).then(res => {
if(res.code==200){
this.$message.success(res.message);
this.updateTags();
}else{
this.$message.error(res.message);
}
});
}).catch( () => {
this.$message({
type: 'info',
message: '已取消'
});
});
},
点击“添加关键词”按钮后,会弹出如下弹框,然后点击“保存”。
保存后,页面中就已显示新添加的关键词信息了,如下图:
如下图,这里菜单栏目1中,有个“test3”关键事,现在要把它修改成“test2”。
1)mock目录中index.js增加 修改关键词模拟接口
//栏目中修改关键词信息
mock("/api/tags", "put", (req, res) => {
let _result = [],
_code = 0,
_msg = "";
//获取关键词数据
let _tags = DBMap.get("关键词列表");
if(req['body']){
try{
let _data = JSON.parse(req.body),
_setData = _tags.get(_data.id);
if(_setData.has(_data.oldVal)){
_setData.delete(_data.oldVal);
_setData.add(_data.newVal);
_code = 200;
_msg = "success";
}else{
_code = 0;
_msg = "修改的信息不存在";
}
}catch(e){
_code = 0;
_msg = JSON.stringify(e);
}
}else{
_code = 0;
_msg = "请传入栏目ID";
}
return {
code: _code,
message: _msg,
data: _result
}
});
2)api目录中api.js增加 修改关键词请求接口函数
//修改关键词信息
export const editTags = param => {
return service.put('/api/tags', param);
}
3)页面的methods中增加“修改关键词”事件函数
//修改关键词
editTagsEvent(_name){
let _id = this.categoryList[this.categoryIndex]['id'];
this.$prompt('请输入栏目名称', '提示', {
confirmButtonText: '保存',
cancelButtonText: '取消',
inputValue: _name
}).then( res => {
editTags({
id: _id,
oldVal: _name, //原内容
newVal: res.value //新内容
}).then(res => {
if(res.code==200){
this.$message.success(res.message);
this.updateTags();
}else{
this.$message.error(res.message);
}
})
}).catch( () => {
this.$message({
type: 'info',
message: '已取消'
});
});
},
鼠标放到要修改关键词上,点击悬浮图标“修改按钮”,会弹出修改弹框,如下图:
把“test3”修改成“test2”后,点击保存,这里页面上就显示为“test2”了,如下图:
1)mock目录中index.js增加 删除关键词模拟接口
//栏目中修改关键词信息
mock("/api/tags", "delete", (req, res) => {
let _result = [],
_code = 0,
_msg = "";
//获取关键词数据
let _tags = DBMap.get("关键词列表");
if(req['body']){
try{
let _data = JSON.parse(req.body),
_setData = _tags.get(_data.id);
if(_setData.has(_data.name)){
_setData.delete(_data.name);
_code = 200;
_msg = "success";
}else{
_code = 0;
_msg = "删除的信息不存在";
}
}catch(e){
_code = 0;
_msg = JSON.stringify(e);
}
}else{
_code = 0;
_msg = "请传入栏目ID";
}
return {
code: _code,
message: _msg,
data: _result
}
});
2)api目录中api.js增加 删除关键词请求接口函数
//删除关键词信息
export const deleteTags = param => {
return service.delete('/api/tags', {
data: param
});
}
3)页面的methods中增加“删除关键词”事件函数
//删除关键词
deleteTagsEvent(_name){
let _id = this.categoryList[this.categoryIndex]['id'];
this.$confirm('此操作将永久删除关键词('+_name+'),是否继续?', "提示", {
confirmButtonText: "确认删除",
cancelButtonText: "取消",
type: "warning"
}).then(res => {
deleteTags({
id: _id,
name: _name
}).then(res => {
if(res.code==200){
this.$message.success(res.message);
this.updateTags();
}else{
this.$message.error(res.message);
}
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
});
});
},
将刚修改过的“test2”删除掉,点击“删除图标按钮”,弹出删除确认码,如下图:
点击确认删除后,页面中“test2”就消失了,如下图:
这一波操作下来,是不是觉得很有意思。在后台接口未完成之前,前端就可以模拟数据库表,进行数据的增删除改查操作。在此同时,前端也可以完善接口文档,与后台同步接口中的入参数据和响应数据,使得真实接口中的数据和模拟接口中的数据完善衔接。