如何使用 VUE 更新树视图

问题描述

我在树组件结构管理方面遇到问题。 就像一棵树有很多节点一样,当我删除一个节点时,渲染功能会运行,但页面没有根据树数据显示正确的信息。

在这里附上了源代码,请任何人都可以帮助我摆脱这种混乱的情况。 非常感谢。

代码示例: 这是树渲染组件,树数据在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",{
                id:"3",msg: "node 3",{
                id:"4",msg: "node 4",{
                id:"5",msg: "node 5",{
                id:"6",msg: "node 6",{
                id:"7",msg: "node 7",nextnodes: []
            }]
        }
    },mutations: {},actions: {},modules: {
    }
});

这是main.js,我把删除节点功能在这里

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

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)