javascript - 希望将带有参数的回调函数传递给 Polymer 中的子组件

标签 javascript node.js polymer polymer-1.0

我想创建一个通用 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>

这是一般的 child :

<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 子 Node 为子 Node 中的每个 Node 实例调用 node-parent 组件中的 nodedesign(node) {} 函数。

更新:

我正在尝试创建一个 d3 力图组件,其父元素将具有绘制 Node 和链接的功能,因此常规缩放和平移功能位于常规组件中。

    <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>

以下内容将位于父级中的函数中,该函数将根据数据内容绘制 Node :

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);

最佳答案

您的想法是错误的,子元素不应该属于父元素,因为它不能重用。更好的方法是让 child 有一个通知属性:

properties: {
    data: {type:Object, notify: true}
}

并且在父元素中监听它使用事件监听器更改了事件eather:

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 数据绑定(bind)系统:

<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 )

关于javascript - 希望将带有参数的回调函数传递给 Polymer 中的子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39735125/

相关文章:

javascript - 当我在 Angular 6 中将其设置为可编辑内容时,如何将焦点设置在该元素上?

javascript - Typescript - 有没有办法指定全局引用?

node.js - ES6 * typescript : Cannot find namespace

javascript - 如何在网页编程中显示适合屏幕的图像列表

javascript - polymer 核心标签和核心复选框动态

javascript - polymer 在运行时更改自定义样式变量

javascript - 改变立方体一个面的颜色 - THREE.js

java - 如何隐藏浏览器检查器中的字段

javascript - ASP.NET MVC3 Ajax.ActionLink - 条件确认对话框

MySQL 连接,ORDER BY RAND() 然后排序 ASC(最好使用 Sequelize)