很有可能的起因就是:视图所应用的这部分数据,未挂载在vue视图文件data的间接属性上,或者挂载的data间接属性也是一个对象,在第一次生成这个对象的时候,并没有这部分视图数据。。脱钩了。

=======前面的文字帮忙了解,有所顿悟的略过=======

近几日,因为我的项目的须要。写了一个对于数据流的画板。
大抵渲染后果如下:

前端框架应用的VUE。
大抵实现的思路是:
结构三个类:舞台类Stage、数据流类Flow、节点类Node

因为这里不是讲画板实现。重点是介绍下代码大体的构造,好让大家对问题产生的起因有一个大抵的了解。所以只贴了一些结构性伪代码。!!无奈运行哦。。。

记录匆忙,待闲下来,再写一个能够运行的demo。

不太伪的伪代码大抵如下:

class Stage {    constructor(){        this.elements =[] //待渲染到舞台上的元素单元        ...    }        initElements({type,data}){        if(type === 'flow'){            this.createFlow(data)        }    }        createFlow(data){        let flow = new Flow(data,this)    }    ...}class Flow{    constructor({id,nodes},stage){        this.id = id        this.nodes =[]        this.stage = stage        this.component = 'Flow' //以动静组件模式渲染        this.initNodes(nodes)        this.stage.elements.push(this) //将此实例注入stage的elements        ...    }        initNodes(nodelist){        this.nodes = nodelist.map( n => {            return new Node(n)        })    }}class Node{    constructor({id,message}){        this.id = id        this.message = 'show Info'        ...    }    setMessage(ms){        this.message = ms    }    ...}

以后页面vue文件(同样是不太伪的伪代码):

<template>  <div class='sketchpad-with-vue'>    <div class='sketchpad-viewport' id='viewport' >      <div id="sketchpad-stage" class="sketchpad-stage">        <component           v-for="(e,index) in elements"          :is="e.component"            :instance='e'          :key='e.key'        ></component>      </div>        </div>  </div></template><script>export default {  data() {    return {      stage:null,      nodes:[...]    };  },  methods: {    renderNodes(){      if(this.stage){        let elements = [          {type:'Logicflow',data:{nodes:this.nodes,id:this.id}}        ]        this.stage.initElements(elements)      }    },  }}</script>

Node.vue

<template>  <div class='node' :style="nodeStyle">    <div class='header'  :style="headerStyle">      图片解决      <div @click="handleClick">...</div>    </div>    <div class='content' :style="contentStyle">        {{node.message}}    </div>  </div></template><script>export default {  components: {},  props:{    node:{      type:Object,      required:true,      default:() => {}    }  },  data() {    return {            };  },  wath:{    node(oldV,newV){      console.log(oldV,newV)    }  },  computed: {},  watch: {},   methods: {    handleClick(command){        this.node.setMessage('edit')    }  },  created() {  }}</script>

代码解释:

  1. 通过在以后画板页面的视图文件(.vue文件)内,申明一个Stage实例:this.stage = new Stage();并且初始化其要渲染的元素->流:this.stage.initElements(elements),并将此实例存入stage的elements属性中,用以页面渲染。
  2. Flow实例则依据传入的数据初始化其所蕴含的节点(一系列Node实例):this.initNodes(nodes),这些节点实例会存入flow实例的nodes属性中。留神:这些全部都是js代码外部实现。
  3. 画板视图渲染的单元是Flow,Flow视图外部再渲染Node视图。
  4. Node类,具备node节点所应有的一系列操作,已批改其属性。例如,点击一下“...”,将其属性 message批改为'edit'

理论运行中,后盾数据显示message的确曾经扭转,但无论怎么操作都不会引发视图从新渲染。

最初起因就是:
只有this.stage是在画板视图文件中申明的。申明时,this.stage.elements为空数组。VUE是能够检测到elements的变动的。然而,它检测不到elements外部元素(Flow实例)的属性变动。这对VUE来说,无疑就是新建的对象属性。

解决方案:
Stage类新增一个属性:watchInstance = []
将所有须要和视图绑定的实例,均注入到watchInstance数组中。这样就建设起了视图所需实例与VUE的监测桥梁。


并且,在node的间接渲染组件上,定义:key
批改之后,通过刷新该key,来刷新视图。

<Node :node='node' :key='node.key'/>

结束。
还请大神们斧正!