我想创建一个通用的Polymer组件,在子组件中为数据元素的每个实例调用父Polymer组件中的回调函数。
以下是一般家长:
<dom-module id="nested-parent">
<template>
<style>
:host {
display: block;
}
</style>
<nested-child callback="nodedesign(node)"></nested-child>
</template>
<script>
Polymer({
is: 'nested-parent',
properties: {
},
nodedesign: function(node) {
}
});
</script>
</dom-module>
这是一般孩子:
<dom-module id="nested-child">
<template>
<style>
:host {
display: block;
}
</style>
</template>
<script>
Polymer({
is: 'nested-child',
properties: {
callback: {
type: String
}
}
});
</script>
</dom-module>
我希望node-child为子节点中的每个节点实例调用nodedesign(node) {}
组件中的node-parent
函数。
更新:
我正在尝试创建一个d3力图组件,父元素将具有绘制节点和链接的功能,因此一般的缩放和平移功能都在通用组件中。
<link rel="import" href="../../bower_components/polymer/polymer.html"/>
<script src="../../bower_components/d3/d3.min.js"></script>
<dom-module id="d3-graph">
<template>
<style>
</style>
<div id="generalGraph"></div>
</template>
<script>
var d3graphSVG;
Polymer({
is: "d3-graph",
properties: {
graph: { type: Object, notify: true, observer: '_graphChanged' }
},
ready: function() {
this.scopeSubtree(this.$.generalGraph, true);
d3graphSVG = d3.select(this.$.generalGraph).append("svg")
.attr("width", "100%")
.attr("height", "100%");
},
_graphChanged: function() {
if (this.graph == null) return;
if (this.graph.nodes.length == 0) return;
var width = 800;
var height = 800;
this.scopeSubtree(this.$.generalGraph, true);
var force = d3.layout.force()
.gravity(0.05)
.distance(100)
.charge(function(d) { return (d.mode == 1) ? 50 : -100;})
.size([width, height]);
force
.nodes(this.graph.nodes)
.links(this.graph.links)
.start();
var link = d3graphSVG.selectAll(".link")
.data(this.graph.links)
.enter().append("line")
.attr("class", "link");
var node = d3graphSVG.selectAll(".node")
.data(this.graph.nodes)
.enter().append("g")
.attr("class", "node")
.on("click", function(d) {
console.log("foo");
})
.call(force.drag);
node.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name });
force.on("tick", function() {
link.attr("x1", function(d) {
if (d.source.mode == 1) { d.source.x = 50; }
return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) {
if (d.target.mode == 1) { d.target.x = 50; }
return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) {
if (d.mode == 1) {
d.fixed = true;
d.x = 50;
}
return "translate(" + d.x + "," + d.y + ")";
});
});
}
})
</script>
</dom-module>
以下内容将在父级函数中,该函数将根据数据内容绘制节点:
var node = d3graphSVG.selectAll(".node")
.data(this.graph.nodes)
.enter().append("g")
.attr("class", "node")
.on("click", function(d) {
console.log("foo");
})
.call(force.drag);
node.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name });
其他更新:
我将尝试在父级中为数据添加一个函数:
graph.nodes.forEach( function (node)
{
node._draw = function() {
return '<g class="node"><image xlink:href="https://github.com/favicon.ico" x="-8" y="-8" width="16" height="16"></image><text dx="12" dy=".35em">'
+ this.name + '</text></g>'
};
});
并将子组件功能代码更改为:
var node = d3graphSVG.selectAll(".node")
.data(this.graph.nodes)
.enter().html(this._draw()).call(force.drag);
答案 0 :(得分:1)
你认为错误的方式,儿童元素不应该是父元素的严重因素,因为它不会重复使用。更好的方法是让孩子成为通知财产:
properties: {
data: {type:Object, notify: true}
}
在父元素中,用事件监听器监听它改变的事件:
this.addEventListener('data-changed', this.nodedesign.bind(this));
nodedesign: ( event ) => {
// event.detail should have the data and the element in it
let item = event.detail.item;
let data = event.detail.data;
},
或使用Polymer Data Binding系统:
<nested-child data="{{parentData}}"></nested-child>
properties: {
parentData: {type: Object, observer: 'nodedesign'}
},
nodedesign: ( newValue, oldValue ) => {
// do stuff
},
你可以用一个小技巧调用父函数,但我不推荐它:
let parent = null;
while ((parent = parent.parentElement) && parent.tagName != 'NESTED-PARENT');
if( parent != null ) parent.nodedesign( this )