内置组件<t:if/>和<t:unless/>

第一部分:源码
AbstractConditional.java

// Copyright 2009 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry5.corelib.base;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.Block;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.ioc.annotations.Inject;

/**
 * Base class for {@link org.apache.tapestry5.corelib.components.If} and {@link org.apache.tapestry5.corelib.components.Unless}.
 * Will render its body or the block from its else parameter.  If it renders anything and it has an element name, then
 * it renders the element and its informal parameters.
 */
@SupportsInformalParameters
public abstract class AbstractConditional
{
    @Inject
    private ComponentResources resources;

    /**
     * Performs the test via the parameters; return true to render the body of the component, false to render the else
     * block (or nothing).
     *
     * @return true to render body
     */
    protected abstract boolean test();

    /**
     * An alternate {@link org.apache.tapestry5.Block} to render if {@link #test()} is false. The default, null, means
     * render nothing in that situation.
     */
    @Parameter(name = "else", defaultPrefix = BindingConstants.LITERAL)
    private Block elseBlock;

    private boolean renderTag;

    /**
     * Returns null if the {@link #test()} is true, which allows normal rendering (of the body). If the test parameter
     * is false, returns the else parameter (this may also be null).
     */
    Object beginRender(MarkupWriter writer)
    {
        Block toRender = test() ? resources.getBody() : elseBlock;

        String elementName = resources.getElementName();

        renderTag = toRender != null && elementName != null;

        if (renderTag)
        {
            writer.element(elementName);
            resources.renderInformalParameters(writer);
        }

        return toRender;
    }

    /**
     * If {@link #test()} is true, then the body is rendered, otherwise not. The component does not have a template or
     * do any other rendering besides its body.
     */
    boolean beforeRenderBody()
    {
        return false;
    }

    void afterRenderBody(MarkupWriter writer)
    {
        if (renderTag)
            writer.end();
    }


}

If.java

// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry5.corelib.components;

import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.base.AbstractConditional;

/**
 * Conditionally renders its body. May render its tag and any informal parameters.
 */
public class If extends AbstractConditional
{
    /**
     * If true, then the body of the If component is rendered. If false, the body is omitted.
     */
    @Parameter(required = true)
    private boolean test;

    /**
     * Optional parameter to invert the test. If true, then the body is rendered when the test parameter is false (not
     * true).
     *
     * @see Unless
     */
    @Parameter
    private boolean negate;

    /**
     * @return test parameter (if negate is false), or test parameter inverted (if negate is true)
     */
    protected boolean test()
    {
        return test != negate;
    }


}

Unless.java

// Copyright 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry5.corelib.components;

import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.base.AbstractConditional;

/**
 * A close relative of the {@link org.apache.tapestry5.corelib.components.If} component that inverts the meaning of its
 * test.  This is easier than an If component with the negate parameter set to true.
 */
public class Unless extends AbstractConditional
{
    /**
     * If true, then the body of the If component is rendered. If false, the body is omitted.
     */
    @Parameter(required = true)
    private boolean test;

    /**
     * @return test parameter inverted
     */
    protected boolean test()
    {
        return !test;
    }
}

第二部分:简介
<t:if/>和<t:unless/>是条件判断组件,使用test属性指定要测试的条件,然后决定渲染的部分,如果test为真则渲染

<t:if/>的内部非<p:else>部分,如果test属性的结果是假,那么渲染<p:else>部分或者else属性指定的字符串、block或者

其他部分,test的测试结果的作用可以使用negate来做反转,是渲染效果相反,如果negate属性为真,那么<t:if/>和

<t:unless/>就是等效的test渲染结果。
<t:unless/>的使用就是相比较<t:if/>更加简单,可以自己试一下了。

第三部分:测试
以下是测试用的最终代码文件
Start.tml

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" xmlns:p="tapestry:parameter">
	<head>
		<title>t:if and t:unless</title>
	</head>
    <body>
    	<t:if test="'field'">not use field<br/></t:if>
	    <hr/>
	    <t:if test="test1" else="block:testfalse">
	    	Test1 t:block True<br/>
	    </t:if>
	    <t:block id="testfalse">
	    	Test1 t:block False<br/>
	    </t:block>
	    <hr/>
	    <t:if test="test1" >
	    	Test1 p:else True<br/>
	    	<p:else>
	    		Test1 p:else False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
    	<span t:type="if" t:test="test2">test2 span</span>
    	<hr/>
	    <t:if test="test2" negate="true">
	    	Test2 negate True<br/>
	    	<p:else>
	    		Test2 negate False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test2" negate="false">
	    	Test2 negate True<br/>
	    	<p:else>
	    		Test2 negate False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test3">
	    	Test3 "" True<br/>
	    	<p:else>
	    		Test3 "" False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test4">
	    	Test4 "false" True<br/>
	    	<p:else>
	    		Test4 "false" False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test5">
	    	Test5 "0" True<br/>
	    	<p:else>
	    		Test5 "0" False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test6">
	    	Test6 int 0 True<br/>
	    	<p:else>
	    		Test6 int 0 False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test7">
	    	Test7 int 7 True<br/>
	    	<p:else>
	    		Test7 int 7 False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test8">
	    	Test8 <![CDATA[List<Integer>]]]>=null True<br/>
	    	<p:else>
	    		Test8 <![CDATA[List<Integer>]]]>=null False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test9">
	    	Test9 <![CDATA[List<Integer>]]]> size=0 True<br/>
	    	<p:else>
	    		Test9 <![CDATA[List<Integer>]]]> size=0 False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test10">
	    	Test10 <![CDATA[List<Integer>]]]> size=2 True<br/>
	    	<p:else>
	    		Test10 <![CDATA[List<Integer>]]]> size=2 False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test11">
	    	Test12 Object=null True<br/>
	    	<p:else>
	    		Test12 Object=null False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
	    <t:if test="test12">
	    	Test13 Object!=null True<br/>
	    	<p:else>
	    		Test13 Object!=null False<br/>
	    	</p:else>
	    </t:if>
	    <hr/>
    </body>
</html>

Start.java

package jumpstart.web.pages;

import java.util.ArrayList;
import java.util.List;

import jumpstart.web.data.Person;

import org.apache.tapestry5.annotations.Property;

public class Start {
	@Property
	private boolean test1 = false;
	@Property
	private boolean test2 = true;
	@Property
	private String test3 = "";
	@Property
	private String test4 = "false";
	@Property
	private String test5 = "0";
	@Property
	private int test6 = 0;
	@Property
	private int test7 = 2;
	@Property
	private List<Integer> test8;
	@Property
	private List<Integer> test9 = new ArrayList<Integer>();
	@Property
	private List<Integer> test10 = new ArrayList<Integer>() {
		{
			add(1);
			add(2);
		}
	};

	@Property
	private Person test11;
	@Property
	private Person test12 = new Person();
}

最终的效果

最终的效果(HTML)

<body>
    	not use field<br/>
	    <hr/>
	    
	    	Test1 t:block False<br/>
	    
	    
	    <hr/>
	    
	    		Test1 p:else False<br/>
	    	
	    <hr/>
    	<span>test2 span</span>
    	<hr/>
	    
	    		Test2 negate False<br/>
	    	
	    <hr/>
	    
	    	Test2 negate True<br/>
	    	
	    
	    <hr/>
	    
	    		Test3 "" False<br/>
	    	
	    <hr/>
	    
	    		Test4 "false" False<br/>
	    	
	    <hr/>
	    
	    	Test5 "0" True<br/>
	    	
	    
	    <hr/>
	    
	    		Test6 int 0 False<br/>
	    	
	    <hr/>
	    
	    	Test7 int 7 True<br/>
	    	
	    
	    <hr/>
	    
	    		Test8 List&lt;Integer&gt;]=null False<br/>
	    	
	    <hr/>
	    
	    		Test9 List&lt;Integer&gt;] size=0 False<br/>
	    	
	    <hr/>
	    
	    	Test10 List&lt;Integer&gt;] size=2 True<br/>
	    	
	    
	    <hr/>
	    
	    		Test12 Object=null False<br/>
	    	
	    <hr/>
	    
	    	Test13 Object!=null True<br/>
	    	
	    
	    <hr/>
    </body>

第四部分:分析
代码中if和unless两个类都是继承自AbstractConditional抽象类,在抽象类中声明了一个protected abstract boolean

test();该方法在if和unless中有不同的实现,返回值正好是相反,这也就成就了if和unless的test属性不同渲染结果。
    Object beginRender(MarkupWriter writer)
    {
        Block toRender = test() ? resources.getBody() : elseBlock;

        String elementName = resources.getElementName();

        renderTag = toRender != null && elementName != null;

        if (renderTag)
        {
            writer.element(elementName);
            resources.renderInformalParameters(writer);
        }

        return toRender;
    }
上述这段代码,首先根据test()的结果,来决定渲染的toRender是if(或者unless)所在标签的内容还是else属性指定的

block,然后下面就正常渲染if(或者unless)的elementName(就是使用<elementName t:type="if" test="'field'"/>格式

书写)。

negate的反转效果就是在实现抽象类AbstractConditional的test()方法的时候使用了一个反转判断效果。

转载于:https://my.oschina.net/namespace/blog/15055

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值