quasar树组件勾选策略改写
前言
quasar的树组件的勾选策略在有些时候不太适用,leaf 策略会影响父级的勾选状态,但是无法通过组件提供的api(@update:ticked -> function(target))去获取勾选的父节点值,只会返回处于勾选状态的的子节点这里做的改变是获取所有处于勾选状态的节点,并且勾选父节点的时候会子节点会自动勾选,取消父节点勾线的时候,
子节点会自动取消勾选,子节点的勾选状态不会影响父节点的勾选状态
(这里适用于每个节点都对应一条数据的时候使用)
父节点的状态不会根据字节点改变
quasar树组件文档地址
leaf 勾选的节点只是叶子节点。 勾选节点也会影响父级的勾选状态(父级会部分勾选或勾选),以及其子级(所有可勾选的子级也会被勾选)。
leaf-filtered 与leaf具有相同的概念,只是该策略仅适用于过滤后的节点(过滤后仍可见的节点)。
strict 勾选节点独立于父级或子级勾选状态。
一、页面
<q-tree
:nodes="organinzation"
node-key="id"
color="grey-7"
text-color="grey-7"
selected-color="primary"
@update:ticked="tickNode"
:expanded.sync="expanded"
:default-expand-all="true"
:ticked="ticked"
ref="tree"
tick-strategy= 'strict'
/>
二、script部分
代码如下(示例):
export default {
data() {
return {
organinzation: [],
expanded: [],
ticked: [],
lastTicked: [],
};
},
mounted() {
this.getdata().then((res) => {
this.organinzation = Object.assign([], res);
this.dataload = true;
});
},
methods: {
...mapActions("zhinuo", ["handleNodeGet"]),
getdata() {
return new Promise((selove, reject) => {
this.$showloading(this);
this.handleNodeGet({
type: "all",
}).then((res) => {
this.$clearloading(this);
if (res.errno == 0) {
selove(this.initTree(res.data));
} else {
selove([]);
}
});
});
},
initTree(data) {
let arr = [];
for (let i = 0; i < data.length; i++) {
let temp = data[i];
let children = [];
if (temp.children && temp.children.length > 0) {
children = this.treeChildren(temp.children);
}
arr.push({
label: temp.name,
id: temp.id,
pid: temp.pid,
children,
});
}
return Object.assign([], arr);
},
// 这里是对后台返回的数据进行处理的 吧数据处理成符合树组件要求的数据格式
treeChildren(resdata) {
let data = [];
if (resdata) {
for (let i = 0; i < resdata.length; i++) {
let item = resdata[i];
let havechild = [];
//判断是否存在子节点
if (item.children && item.children.length > 0) {
havechild = Object.assign([], this.treeChildren(item.children));
}
data.push({
label: item.name,
id: item.id,
pid: item.pid,
children: havechild,
});
}
}
return data;
},
//根据节点值获取树数据
getObjByID(data, id) {
let r = null;
for (let i = 0; i < data.length; i++) {
let element = data[i];
if (element.id == id) {
r = element;
break;
}
if (element.children && element.children.length > 0) {
r = this.getObjByID(element.children, id);
if (r != null) {
break;
}
}
}
return r;
},
// 获取当前节点下所有子节点的id
getChildAll(data) {
let childrenId = [];
function recursion(nodedata) {
for (const children of nodedata.children) {
childrenId.push(children.id);
if (children.children.length > 0) {
recursion(children);
}
}
}
recursion(data);
return childrenId;
},
// 勾选时触发的方法,主要就是在这里对数据进行处理的
tickNode(val) {
// val为当前节点操作之后,树节点中所有处于勾选状态的节点数据
// this.lastTicked也可以在this.ticked = val;之前通过this.ticked 获得,数据是一样的,都是视图更新前勾选的数据
this.ticked = val;
this.lastTicked = this.$refs.tree.getTickedNodes().map((val) => val.id);
// this.$refs.tree.getTickedNodes()获取视图更新前的数据
const addTickedNodes = _.difference(val, this.lastTicked);// 通过比较得出此次操作勾选的节点
const delTickedNodes = _.difference(this.lastTicked, val);// 通过比较得出此次操作取消勾选的节点
if (addTickedNodes.length == 0) {
this.optionChoiceLimts(delTickedNodes.join(""), "remove", val);
} else {
this.optionChoiceLimts(addTickedNodes.join(""), "add", val);
}
},
// 处理树展示的勾选(主要是来做勾选父节点子节点自动勾选和取消父节点子节点自动取消的数据处理)
optionChoiceLimts(id, type, val) {
let findObj = this.getObjByID(this.organinzation, id);
if (type == "remove") {
const allchildrenId = this.getChildAll(findObj);
const removeAllchild = _.union([Number(id)], allchildrenId);
const tickeNode = _.difference(this.lastTicked, removeAllchild);
this.ticked = tickeNode;
} else {
const allchildrenId = this.getChildAll(findObj);
const tickeNode = _.union(val, allchildrenId, [Number(id)]);
this.ticked = tickeNode;
}
},
},
};
// 此时就可以通过this.ticked 获取页面上树节点中所有出游勾选状态的节点了
树数据结构
const treeJson=[
{
children: [{id: 1,label: "test",pid: 0,children:[]}],
id: 1,
label: "test",
pid: 0
}
]