Vue.js快速入门之六:Set和Map的妙用

ES6的Set和Map区别是:Set是“集合”结构,而Map是“字典”结构;Set是以[value, value]的形式存储元素,而Map是以[key, value]的键值对形式存储元素;Map可以用get()键查找到特定值并返回,而Set不行。

一、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会是这个参数,没有返回值。

注意:

  1. 成员不能重复
  2. 只有值没有键名,类似数组
  3. 可以遍历,方法有add, delete, has等

二、Map的方法

方法 参数 返回值 描述
set (key, value) 实例Map 向字典中添加新元素
get key value 通过键查找特定的数值并返回
has key Boolean 判断字典中是否存在键key
delele key Boolean 通过键key从字典中移除对应的数据
clear 将这个字典中的所有元素删除
keys iterable 将字典中包含的所有键名以迭代器形式返回
values iterable 将字典中包含的所有数据以迭代器形式返回
entries iterable 返回所有成员的迭代器
forEach 遍历字典的所有成员

注意:

  1. 本质上是键值对的集合
  2. 可以遍历,可以跟各种数据格式转换

三、本地模拟数据 获取栏目表

        最近在研究Vue项目的本地模拟数据时,发现ES6的Set和Map可以很好实现本地数据的增删改查,也解决了Array会存储重复数据问题。对于某些项目特定需求,是有帮助的,这里通过以下小案例,让大家了解如何使用它们。

 注:axios和mockjs上两篇已介绍,不清楚可以翻看下。

3.1 创建data.js,模拟本地数据库

        在mock目录中,创建data.js文件,data.js是本地模拟数据库,里在存储各种数据,代码如下:

import { mock } from 'mockjs'

//实例Map,定义一个存储数据的 数据表
const DBMap = new Map();


export default DBMap;

3.2 定义栏目容器

import { mock } from 'mockjs'

//实例Map,定义一个存储数据的 数据表
const DBMap = new Map();

//实例Map,定义一个存储栏目的 数据集
const category = new Map();

//将栏目数据集 存储到 数据表中
DBMap.set("栏目列表", category);

export default DBMap;

3.3 通过mockjs生成栏目模拟数据

        在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);

控制台输出结果如下图:

Vue.js快速入门之六:Set和Map的妙用_第1张图片

3.4 创建index.js,定义模拟数据接口

        在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
	}
});

3.5 创建api目录

        在api目录创建api.js,用来定义接口请求函数,代码如下:

import service from '@/utils/request'

//获取栏目数据
export const getCategory = () => {
	return service.get('/api/category', {});
}

3.6 在页面中获取栏目数据

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);
			})
		}
	}
}

控制台输出结果如下图:

Vue.js快速入门之六:Set和Map的妙用_第2张图片

四、实现栏目名称的增删除改查功能

        通过实现下图案例,完成增删改功能演示。

Vue.js快速入门之六:Set和Map的妙用_第3张图片

4.1 实现添加功能

         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
	}
}

        以上几步完成后,页面中点击添加事件,会弹出如下图输入框:

Vue.js快速入门之六:Set和Map的妙用_第4张图片

        输入完成保存后,重新获取栏目列表,新添加栏目已在列表中了,结果如下图:

Vue.js快速入门之六:Set和Map的妙用_第5张图片

 4.2 实现修改功能

        这边在每个栏目上添加了悬浮显示编辑和删除功能按钮,鼠标放到对应栏目项,则显示操作按钮。如下图:

Vue.js快速入门之六:Set和Map的妙用_第6张图片

        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”修改成”家电电器“,如下图:

Vue.js快速入门之六:Set和Map的妙用_第7张图片

         输入完成点击保存后,重新获取栏目列表,列表中名称已被修改了,结果如下图:

Vue.js快速入门之六:Set和Map的妙用_第8张图片

4.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: '已取消'
		});
	});
},

        点击删除图标后,会出出确认是否删除弹框如下图:

Vue.js快速入门之六:Set和Map的妙用_第9张图片

         点击确认后,栏目列表位置”新添加的栏目“就被删除了。

Vue.js快速入门之六:Set和Map的妙用_第10张图片

五、栏目的关键词功能 

        Vue.js快速入门之六:Set和Map的妙用_第11张图片

        现在我们来实现添加关键词功能,给每个栏目单独添加关键,这时就用到了Set集合了,它可以存储无重复元素。

5.1 实现栏目切换功能

        Html代码如下:

//...

        JS代码如下:

export default {
	data(){
		return {
			categoryList: [],
            //当前选中栏目索引值
			categoryIndex: 0,    
			//右侧关键词数据集
			tagsList: []
		}
	},
	methods: {
		//选择栏目事件
		changeMenuEvent(index){
			this.categoryIndex = index;
		},

		...
	}
}

        如上代码,将changeMenuEvent函数绑定到菜单栏目元素的Dom的@click事件上即可。

5.2 data.js数据表中定义Set集合

        这里将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);
})

5.3 获取对应栏目的关键词列表

        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();
},

六、实现关键词增删改功能

6.1 添加关键词

        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: '已取消'
		});
	});
},

         点击“添加关键词”按钮后,会弹出如下弹框,然后点击“保存”。

 Vue.js快速入门之六:Set和Map的妙用_第12张图片

        保存后,页面中就已显示新添加的关键词信息了,如下图:

 Vue.js快速入门之六:Set和Map的妙用_第13张图片

6.2 修改关键词

        如下图,这里菜单栏目1中,有个“test3”关键事,现在要把它修改成“test2”。

Vue.js快速入门之六:Set和Map的妙用_第14张图片

         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: '已取消'
		});
	});
},

        鼠标放到要修改关键词上,点击悬浮图标“修改按钮”,会弹出修改弹框,如下图:

Vue.js快速入门之六:Set和Map的妙用_第15张图片

         把“test3”修改成“test2”后,点击保存,这里页面上就显示为“test2”了,如下图:

Vue.js快速入门之六:Set和Map的妙用_第16张图片

6.3 删除关键词

         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”删除掉,点击“删除图标按钮”,弹出删除确认码,如下图:

Vue.js快速入门之六:Set和Map的妙用_第17张图片

         点击确认删除后,页面中“test2”就消失了,如下图:

Vue.js快速入门之六:Set和Map的妙用_第18张图片

         这一波操作下来,是不是觉得很有意思。在后台接口未完成之前,前端就可以模拟数据库表,进行数据的增删除改查操作。在此同时,前端也可以完善接口文档,与后台同步接口中的入参数据和响应数据,使得真实接口中的数据和模拟接口中的数据完善衔接。

你可能感兴趣的:(Vue.js,javascript,前端,vue.js,es6)