4

我刚刚为我的 MVC 框架构建了一个文本框控件,在完成整个文档之前,我在从 ServerTag 继承的所有内容(又从 DOMElement 继承)上调用 PreRender。

我发现更改 DOMElement 派生对象的 tagName 的唯一方法是用一个新的替换它,其中所有属性都与旧的同步。

这就是代码中的样子:

protected function PreRenderTextarea( WebPage $sender )
{
    $textarea = $sender->createElement( 'textarea' );
    foreach( $this->attributes as $attribute )
    {
        if ( $attribute->name == 'value' )
        {
            $textarea->nodeValue = $attribute->value;
        }
        else
        {
            $textarea->setAttribute( $attribute->name, $attribute->value );
        }
    }
    $this->parentNode->replaceChild( $textarea, $this );
}

public function OnPreRender( WebPage $sender )
{
    parent::OnPreRender();
    $this->setAttribute( 'value', $this->Value );

    switch( $this->Mode )
    {
        case 'normal' : 
            $this->setAttribute( 'type', 'text' ); 
            break;
        case 'password' : 
            $this->setAttribute( 'type', 'password' ); 
            break;
        case 'multiline' : 
            $this->PreRenderTextarea( $sender ); 
            return; 
            break;
    }
}

这真的是唯一的方法吗?这种方式具有相当不利的副作用,即使控件背后的所有逻辑都归零。

4

1 回答 1

2

是的,您必须这样做——原因是您不仅要更改单个属性 ( tagName) 的值,而且实际上是将整个元素从一种类型更改为另一种类型。tagName(或nodeName)和等属性 nodeType在 DOM 中是只读的,并在您创建元素时设置。

因此,创建一个新元素并完全按照您所做的那样移动旧元素,使用DOMNode::replaceChild, 是正确的操作。

我不确定您所说的“使控件背后的所有逻辑无效的不良副作用”是什么意思——如果您澄清一下,我也许可以在那里为您提供指导。

听起来您可能不希望 ServerTag 从 DOMElement 继承,而是您可能希望通过其他模式(例如组合)链接这两个对象(即,ServerTag“具有”DOMElement 而不是“是”DOMElement)所以您只是替换与您的 ServerTag Textbox 对象关联的 DOMElement 对象。

或者更长远的猜测是您可能会遇到仅复制属性的问题(即textarea具有必需的属性,例如rowsand colsinput但没有)。

于 2008-10-29T11:13:34.177 回答