3

这个问题的完整重现案例在我的GitHub 存储库中。我只会在这里重现必要的部分。

假设我有一些自定义标签的用法:

<!--- testCfcTags.cfm --->
<cfimport taglib="cfcBasedTags" prefix="t">

Text before tags<br>
<t:grandparent gp:attr="set in grandparent">
    Text in grandparent, before parent<br>
    <t:parent p:attr="set in parent">
        Text in parent, before child<br>
        <t:child c:attr="set in child">
            Text in child<br>
        </t:child>
        Text in parent, after child<br>
    </t:parent>
    Text in grandparent, after parent<br>
</t:grandparent>
Text after tags<br>

如果我使用基于 CFM 的自定义标签,并且我想将标签实现中的数据与child标签相关联grandparent,我会简单地这样做:

<!--- child.cfm --->
<cfif thistag.executionMode eq "end">
    <cfassociate basetag="cf_grandparent" datacollection="childAttributesForGrandparent"><!--- this line --->
    <cfassociate basetag="cf_parent" datacollection="childAttributesForParent">
</cfif>

注意我可以直接关联到祖父母标签。

我无法弄清楚如何使用 Lucee 的基于 CFC 的自定义标签干净地做到这一点。

这是我能想到的最好的:

// Child.cfc
component {

    function init(hasEndTag, parent){
        this.parent = arguments.parent;
    }

    function onEndTag(attributes, caller, generatedContent){
        writeOutput(generatedContent);
        this.parent.childattributesForParent = attributes;
        this.parent.parent.childattributesForGrandparent = attributes;
        return false;
    }

}

在 Parent.cfc 我有这个:

// Parent.cfc
component {

    function init(hasEndTag, parent){
        this.parent = arguments.parent;
    }

    function onEndTag(attributes, caller, generatedContent){
        writeOutput(generatedContent);
        this.parent.parentattributesForGrandparent = attributes;
        writeDump(var=this.childAttributesForParent, label="Parent childAttributesForParent");
        return false;
    }

}

thisParent 和 Grandparent 范围的累积(错误)使用意味着从 Child 我可以通过this.parent.parent.

然而,这一切都有点“希思·罗宾逊”。鉴于 Lucee 的基于 CFC 的自定义标签实现的其余部分非常巧妙,我确信我只是遗漏了一些东西。我真的不认为我应该通过父母挖洞才能到达祖父母。这也意味着对于孩子直接在祖父母中的情况,代码需要有所不同。我真正需要的是在 CFC 之间传递一些标签层次结构,而不仅仅是父级。

我用谷歌搜索过,但大部分内容都是我写的(这又基于最初为 Railo 的实现而写的博客文章——这是 Lucee 实现的基础)。

我已经阅读过的文档没有帮助:

4

1 回答 1

2

根据 Railo 博客:

http://blog.getrailo.com/post.cfm/cfc-based-custom-tags-by-example-part-1

您可以使用标签 cfassociate 和函数 GetBaseTagList 和 >GetBaseTagData,其方式与常规基于 CFML 的自定义标签相同。

所以你可以做(​​在cfscript中):

cfassociate(basetag="cf_grandparent", datacollection="childAttributesForGrandparent"); 

我已经用一些示例汇总了一个要点 - 我已经测试并验证了它适用于 Lucee 4.5.1: https ://gist.github.com/dajester2013/183e862915972d51279f

编辑:选项2,基本标签方法:

根据我的评论,这是一种通过基本标签的潜在方法 - 它至少掩盖了不那么漂亮的方面:

BaseTag.cfc

component accessors=true {

    property name="tagName";
    property name="parent";
    property name="hasEndTag";

    public BaseTag function init() {
        structAppend(variables, arguments);

        tagName = "cf_" & lcase(listLast(getMetaData(this).fullname,"."));

        return this;
    }

    public any function getParent(string tagName, ancestors=1) {
        if (!isNull(tagName)) {

            var data = getBaseTagData(tagName, ancestors);
            if (structKeyExists(data,"thisTag")) {
                return data.thisTag;

            // getBaseTagData returns the variables scope for CFC tags...
            } else if (structKeyExists(data, "this")) {
                return data.this;
            }
        } else if (!isNull(variables.parent)) {
            return variables.parent;
        }
    }

    private void function associate(required string tagName, string dataCollection=this.getTagName()) {
        cfassociate(basetag=tagname, dataCollection=dataCollection);
    }

}

测试孩子.cfc

component extends=BaseTag {

    public function onStartTag() {
        attributes._childId = randrange(1000,9000);
        associate("cf_testtag", "testchildren");

        writedump(var=this.getParent(),label='immediateparent');
        writedump(var=this.getParent("cf_testtag"), label='testtag');
        abort;
    }

}
于 2015-03-01T02:09:05.297 回答