【发布时间】:2021-04-27 15:06:45
【问题描述】:
我对树组件结构管理有疑问。 就像一棵树有很多节点一样,当我删除一个节点时,渲染函数运行,但页面没有根据树数据显示正确的信息。
我在这里附上了源代码,请任何人都可以帮助我摆脱这种令人困惑的情况。 非常感谢。
代码示例: 这是树渲染组件,树数据定义在store.state.tree中,我这里标记为reactive,每次删除树中的一个节点,都会调用render函数,我从console.log看到('渲染')
import Node from "./Node";
import {reactive, h} from 'vue';
import store from '@/store';
export default {
name: 'Tree',
components: {Node},
data(){
return reactive({
tree: store.state.tree
});
},
render(){
console.log('render');
let tree = this.tree;
let renderChildNodes = (node)=>{
let vnodes = [];
node.nextnodes.forEach(node => {
vnodes.push(renderChildNodes(node));
});
let vnode = h(Node,{node: node},
{
default: ()=>{
return vnodes;
}
}
);
return vnode;
};
return h('ul', null, renderChildNodes(tree));
}
}
</script>
这是节点代码,我从默认插槽的道具中获取节点,并将其标记为反应式。然后我只是从 store.state.tree 中删除节点。我希望树会刷新视图,但是看起来节点实际上被删除了,但是视图中删除的节点没有更新。
<template>
<li>
<div class="node">
{{state.node.id}}
<input v-model="state.node.msg"/>
<button @click="add(state.node)">add</button>
<button @click="del(state.node)">del</button>
</div>
<ul>
<li>
<slot :node="node"></slot>
</li>
</ul>
</li>
</template>
<script>
import {onMounted, reactive} from 'vue';
import store from '@/store';
export default {
name: 'Node',
props: {
node: {
type: Object,
required: true
}
},
setup(props){
console.log('node setup');
const state = reactive({
node: props.node,
})
onMounted(()=>{
console.log('node onMounted');
})
function add(node){
let sub_node = JSON.parse(JSON.stringify(node));
sub_node.id = node.id + "-" + (node.nextnodes.length+1);
sub_node.nextnodes = [];
node.nextnodes.push(sub_node);
}
function del(node){
findAndRemoveNode(store.state.tree,node);
console.log(store.state.tree.nextnodes);
}
return{
state,
add,
del
}
}
}
function findAndRemoveNode(root, target){
if(!root.nextnodes.findremove(target)){
for(let i=0; i<root.nextnodes.length; i++){
if(findAndRemoveNode(root.nextnodes[i], target))
return true;
}
}else{
console.log(`removed node:` + target.id);
return true;
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
.node{
background-color: #e6e4e4;
text-align:left;
&:hover{
background-color: #c0bdbd;
}
}
li{
margin: .2em;
}
</style>
这是商店代码:
import { createStore } from 'vuex';
export default createStore({
state:{
tree: {
msg: "this is root.",
nextnodes: [{
id:"1",
msg: "node 1",
nextnodes: []
},{
id:"2",
msg: "node 2",
nextnodes: []
},{
id:"3",
msg: "node 3",
nextnodes: []
},{
id:"4",
msg: "node 4",
nextnodes: []
},{
id:"5",
msg: "node 5",
nextnodes: []
},{
id:"6",
msg: "node 6",
nextnodes: []
},{
id:"7",
msg: "node 7",
nextnodes: []
}]
}
},
mutations: {},
actions: {},
modules: {
}
});
这是main.js,我这里放了remove node函数。
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
app.mount('#app')
//app.config.warnHandler = () => null;
Array.prototype.findone = function(val) {
for (var i = 0; i < this.length; i++) {
// if (this[i].id == val.id) return i;
if (this[i] === val) return i;
}
return -1;
};
Array.prototype.findremove = function(val) {
var index = this.findone(val);
if (index > -1) {
this.splice(index, 1);
return true;
}
return false;
};
如果我删除第二个节点, 您可以看到第 7 个节点消失了,但 store.state.tree 实际上被删除了第 2 个节点。视图没有更新,只去掉了最后一个节点,只反映列表大小 delete 2nd node View updated
【问题讨论】:
-
请提供一个可重现的示例而不是整个存储库,并展示您尝试过的内容、预期的内容、正在发生的事情。
-
欢迎来到 Stack Overflow。请在问题中发布相关代码。仅将链接用作参考。
-
对不起,我在帖子中添加了代码,提前感谢您的支持。
标签: vue.js render reactive slots