写在前面的
经过之前树的拼装,基本上已经可以了解到Iview.js中树组件的格式显示,接下来就是有关于树组件中,expand、checked属性,在实际中的一些使用技巧。
功能描述
- 首先看一下我们之前拼装好的树形菜单:
我们的目的就是为了将用户修改之后的树结构返回给后台进行处理并保存。
代码
前端
- HTML
<Button class="searchBtn" @click="saveRowGroupResource" type="primary" >保存用户组资源</Button>
<Tree :data="datatree" show-checkbox multiple></Tree>
- SCRIPT
export default {
data () {
return {
datatree:[],
}
},
methods: {
//保存用户组权限资源
saveRowGroupResource(){
var vm=this;
//将更改后的datatree原封不动的传到后台,再进行处理
/*注:当在页面上对树结构进行了操作之后,由于在上面我们已经将datatree与页面进行了双向绑定,所以,修改之后的数据依然会保存到datatree中*/
axios.post(url+'/ChangeGroupResource',vm.datatree)
.then(function(response){
alert(response.data)
})
.catch(function(error){
alert(error);
})
}
}
}
后台
/*我们在页面上点击保存组资源之后,将treelist原封不动的再传回来*/
[HttpPost]
[Route("ChangeGroupResource")]
public HttpResponseMessage ChangeGroupResource(IList<CO_RIGHTRESOURCE_QueryParam> treeList)
{
if (!string.IsNullOrEmpty(pageId))
{
#region /**如果传入的ID不为空**/
//............
#endregion
}
else
{
//否则返回请先点击用户组
string strError = "请先选择点击用户组";
return Request.CreateResponse(HttpStatusCode.InternalServerError, strError);
}
}
- 如果id不为空
#region 如果pageID不为空
//将treeList中的checked替换成Checked
string _stringJson = JsonConvert.SerializeObject(treeList);
string stringJson = _stringJson.Replace("checked", "Checked");
IList<CO_RIGHTRESOURCE_QueryParam> newTreeList = JsonConvert.DeserializeObject<List<CO_RIGHTRESOURCE_QueryParam>>(stringJson);
//用来存储root节点
IList<CO_RIGHTRESOURCE_QueryParam> root = new List<CO_RIGHTRESOURCE_QueryParam>();
//用来存储一级节点
IList<CO_RIGHTRESOURCE_QueryParam> firstClass = new List<CO_RIGHTRESOURCE_QueryParam>();
//用来存储二级节点
IList<CO_RIGHTRESOURCE_QueryParam> secondClass = new List<CO_RIGHTRESOURCE_QueryParam>();
//通过循环取出一级和二级节点
foreach (var item in newTreeList)
{
root.Add(item);
};
//通过循环取出一级节点
foreach (var item1 in root)
{
foreach (var item2 in item1.children)
{
firstClass.Add(item2);
}
}
//通过循环取出二级节点
foreach (var item1 in firstClass)
{
if (item1.children != null)
{
foreach (var item2 in item1.children)
{
secondClass.Add(item2);
}
}
}
//判断该用户组是否已经含有该资源,如果不含有则添加,如果取消则删除
CO_Right_Group_Resource rightGroupModel = new CO_Right_Group_Resource();
List<CO_Right_Group_Resource> coRightGroupResourceList = new List<CO_Right_Group_Resource>();
coRightGroupResourceList = rightGroupResourceBO_T.GetEntities(pageId).ToList();
if (coRightGroupResourceList.Count == 0)
{
//如果表中没有数据,则证明,只要前台选择节点,就添加
foreach (var item in secondClass)
{
if (item.Checked == "True")
{
rightGroupModel.GroupID = Convert.ToInt32(pageId);
rightGroupModel.ResourceID = item.ID;
rightGroupModel.CreatedOn = item.CreatedOn;
rightGroupModel.CreatedBy = item.CreatedBy;
rightGroupResourceBO_T.Insert(rightGroupModel);
}
}
}
try
{
#region /**第三次重构,更换对比参考系**/
foreach (var item1 in secondClass)
{
foreach (var item2 in coRightGroupResourceList)
{
//首先判断,该用户组是否含有该资源ID
if (item2.ResourceID == item1.ID)
{
//如果含有,则判断是否被勾选
if (item1.Checked == "True")
{
//如果被勾选,则不用做出改变
}
else
{
//如果没有被勾选,则需要删除
rightGroupResourceBO_T.Delete(Convert.ToInt32(item2.ID));
item1.Checked = "False";
}
}
}
goto continueProcess;
reQuery:
coRightGroupResourceList = rightGroupResourceBO_T.GetEntities(pageId).ToList();
continueProcess:
foreach (var item2 in coRightGroupResourceList)
{
//再循环一次进行添加,如果不含有该资源
if (item2.ResourceID != item1.ID)
{
//如果不含有该资源,判断是否被勾选
if (item1.Checked == "True")
{
//如果被勾选,则继续判断用户组资源是否含有该ID
bool flag2 = coRightGroupResourceList.Exists(p => p.ResourceID == item1.ID);
if (flag2)
{
//如果含有,则不作出改变
}
else
{
//如果不含有,则添加
rightGroupModel.GroupID = item2.GroupID;
rightGroupModel.ResourceID = item1.ID;
rightGroupModel.CreatedOn = item1.CreatedOn;
rightGroupModel.CreatedBy = item1.CreatedBy;
rightGroupResourceBO_T.Insert(rightGroupModel);
goto reQuery;
//由于list长度发生了变化,所以必须重新遍历
}
}
else
{
//如果没有被勾选,则不用做出改变
}
}
}
}
#endregion
string success = "编辑成功";
HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(success, Encoding.GetEncoding("UTF-8"), "application/json") };
return result;
}
catch (Exception)
{
string faild = "编辑失败";
HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(faild, Encoding.GetEncoding("UTF-8"), "application/json") };
return result;
}
#endregion
/*到了这里,我们的资源更新就可以做完了,一个完整的功能就可以做出来了接下来我分享一下之前的两种思路和一种其他的结构*/
总结
前两种思路
首先,在之前的两次重构中,我一直都是使用节点充当外部循环的参考,也就是两层foreach循环嵌套,但是结果发现这样做的效率非常不高,这三种在时间复杂度上并没有区别,但是当节点的数量逐渐增多的时候,使用节点做外部循环的话,我们查询数据库的次数会直线上升。在保持现有功能不变的情况下,我将数据库表数据作为了循环参考,这样既保持了功能,也提高了性能另一种结构
1.可以首先把已经勾选的二级节点在上一步筛选出来,然后和库里的进行比对
2.如果已经勾选的二级节点比库里面的少,则证明取消勾选了某些资源,则需要删除
3.如果已经勾选的二级节点比库里的多,则证明增加勾选了某些资源,则需要删除
4.但是这样做的一个弊端就是当需要一个旧资源然后再新增一个新资源的时候是无法区分的,所以还需要额外的时间复杂度进行更加细致的区分。
我们可以非常清楚的看到,由于我们数据库表结构的设计问题,导致了我不得不写一些代码来回避重复以及再次查询。所以我们需要在设计阶段最大限度的避免这种情况的发生。