共计 2527 个字符,预计需要花费 7 分钟才能阅读完成。
很有可能的起因就是:视图所应用的这部分数据,未挂载在 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> |
代码解释:
- 通过在以后画板页面的视图文件 (.vue 文件) 内,申明一个 Stage 实例:
this.stage = new Stage()
;并且初始化其要渲染的元素 -> 流:this.stage.initElements(elements)
,并将此实例存入 stage 的 elements 属性中,用以页面渲染。 - Flow 实例则依据传入的数据初始化其所蕴含的节点(一系列 Node 实例):
this.initNodes(nodes)
,这些节点实例会存入 flow 实例的 nodes 属性中。留神:这些全部都是 js 代码外部实现。 - 画板视图渲染的单元是 Flow,Flow 视图外部再渲染 Node 视图。
- 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'/>
结束。
还请大神们斧正!