文档章节

内置组件<t:pageLink/>、<t:actionlink/>和<t:eventlink/>

阎王他爹
 阎王他爹
发布于 2011/04/05 16:30
字数 2682
阅读 682
收藏 1

第一部分:源码
AbstractLink.java

// Copyright 2007, 2008, 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.*;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

/**
 * Provides base utilities for classes that generate clickable links.
 */
@SupportsInformalParameters
public abstract class AbstractLink implements ClientElement
{
    /**
     * An anchor value to append to the generated URL (the hash separator will be added automatically).
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    private String anchor;

    /**
     * If true, then then no link element is rendered (and no informal parameters as well). The body is, however, still
     * rendered.
     */
    @Parameter("false")
    private boolean disabled;

    @Inject
    private ComponentResources resources;

    @Inject
    private JavaScriptSupport jsSupport;

    private Link link;

    private Element element;

    private String clientId;

    private String buildHref(Link link)
    {
        String href = link.toURI();

        if (anchor == null)
            return href;

        return href + "#" + anchor;
    }

    @SetupRender
    void resetElementAndClientId()
    {
        element = null;
        clientId = null;
    }

    /**
     * Writes an &lt;a&gt; element with the provided link as the href attribute. A call to
     * {@link org.apache.tapestry5.MarkupWriter#end()} is <em>not</em> provided. Automatically appends an anchor if
     * the component's anchor parameter is non-null. Informal parameters are rendered as well.
     * 
     * @param writer
     *            to write markup to
     * @param link
     *            the link that will form the href
     * @param namesAndValues
     *            additional attributes to write
     */
    protected final void writeLink(MarkupWriter writer, Link link, Object... namesAndValues)
    {
        element = writer.element("a", "href", buildHref(link));

        writer.attributes(namesAndValues);

        resources.renderInformalParameters(writer);

        this.link = link;
    }

    /**
     * Returns the most recently rendered {@link org.apache.tapestry5.Link} for this component. Subclasses calculate
     * their link value as they render, and the value is valid until the end of the request, or the next time the same
     * component renders itself (if inside a loop).
     * 
     * @return the most recent link, or null
     */
    public Link getLink()
    {
        return link;
    }

    /**
     * Returns the unique client id for this element. This is valid only after the component has rendered (its start
     * tag). A client id is generated the first time this method is invoked, after the link renders its start tag.
     */
    public final String getClientId()
    {
        if (clientId == null)
        {
            if (element == null)
                throw new IllegalStateException(String.format(
                        "Client id for %s is not available as it did not render yet (or was disabled).",
                        resources.getCompleteId()));

            clientId = jsSupport.allocateClientId(resources);

            element.forceAttributes("id", clientId);
        }

        return clientId;
    }

    /**
     * Returns true if the component is disabled (as per its disabled parameter). Disabled link components should not
     * render a tag, but should still render their body.
     */
    public boolean isDisabled()
    {
        return disabled;
    }

    /**
     * Used for testing.
     */
    final void inject(String anchor, ComponentResources resources)
    {
        this.anchor = anchor;
        this.resources = resources;
    }
}

PageLink.java

// Copyright 2007, 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.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.base.AbstractLink;
import org.apache.tapestry5.ioc.annotations.Inject;

/**
 * Generates a render request link to some other page in the application. If an activation context is supplied (as the
 * context parameter), then the context values will be encoded into the URL. If no context is supplied, then the target
 * page itself will supply the context via a passivate event.
 * <p/>
 * Pages are not required to have an activation context. When a page does have an activation context, the value
 * typically represents the identity of some object displayed or otherwise manipulated by the page.
 */
public class PageLink extends AbstractLink
{
    /**
     * The logical name of the page to link to.
     */
    @Parameter(required = true, allowNull = false, defaultPrefix = BindingConstants.LITERAL)
    private String page;

    @Inject
    private ComponentResources resources;

    /**
     * If provided, this is the activation context for the target page (the information will be encoded into the URL).
     * If not provided, then the target page will provide its own activation context.
     */
    @Parameter
    private Object[] context;

    void beginRender(MarkupWriter writer)
    {
        if (isDisabled()) return;

        Link link = resources.createPageLink(page, resources.isBound("context"), context);

        writeLink(writer, link);
    }

    void afterRender(MarkupWriter writer)
    {
        if (isDisabled()) return;

        writer.end(); // <a>
    }
}

AbstractComponentEventLink.java

// Copyright 2008, 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.Link;
import org.apache.tapestry5.MarkupConstants;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ClientBehaviorSupport;
import org.apache.tapestry5.services.Request;

/**
 * Base class for link-generating components that are based on a component event request. Such events have an event
 * context and may also update a {@link org.apache.tapestry5.corelib.components.Zone}.
 */
public abstract class AbstractComponentEventLink extends AbstractLink
{
    /**
     * The context for the link (optional parameter). This list of values will be converted into strings and included in
     * the URI. The strings will be coerced back to whatever their values are and made available to event handler
     * methods.
     */
    @Parameter
    private Object[] context;

    /**
     * Binding the zone parameter turns the link into a an Ajax control that causes the related zone to be updated.
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    private String zone;

    @Environmental
    private ClientBehaviorSupport clientBehaviorSupport;

    @Inject
    private Request request;

    void beginRender(MarkupWriter writer)
    {
        if (isDisabled()) return;

        Link link = createLink(context);

        writeLink(writer, link);

        if (zone != null)
        {
            if (!request.isXHR())
                writer.getElement().forceAttributes(MarkupConstants.ONCLICK, MarkupConstants.WAIT_FOR_PAGE);

            clientBehaviorSupport.linkZone(getClientId(), zone, link);
        }
    }

    /**
     * Invoked to create the Link that will become the href attribute of the output.
     *
     * @param eventContext the context as an object array, possibly null
     */
    protected abstract Link createLink(Object[] eventContext);

    void afterRender(MarkupWriter writer)
    {
        if (isDisabled()) return;

        writer.end(); // <a>
    }
}

ActionLink.java

// Copyright 2006, 2007, 2008, 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.components;

import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.EventConstants;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.annotations.Events;
import org.apache.tapestry5.corelib.base.AbstractComponentEventLink;
import org.apache.tapestry5.ioc.annotations.Inject;

/**
 * Component that triggers an action on the server with a subsequent full page refresh.
 */
@Events(EventConstants.ACTION)
public class ActionLink extends AbstractComponentEventLink
{
    @Inject
    private ComponentResources resources;

    @Override
    protected Link createLink(Object[] contextArray)
    {
        return resources.createEventLink(EventConstants.ACTION, contextArray);
    }
}

EventLink.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.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.base.AbstractComponentEventLink;
import org.apache.tapestry5.ioc.annotations.Inject;

/**
 * A close relative of {@link org.apache.tapestry5.corelib.components.ActionLink} except in two ways.
 * <p/>
 * First, the event that it triggers is explicitly controlled, rather than always "action".
 * <p/>
 * Second, the event is triggered in its container.
 * <p/>
 * This allows slightly shorter URLs but also allows multiple components within the same container to generate identical
 * URLs for common actions.
 */
public class EventLink extends AbstractComponentEventLink
{
    /**
     * The name of the event to be triggered in the parent component. Defaults to the id of the component. An {@link
     * org.apache.tapestry5.corelib.components.ActionLink} triggers an "action" event on itself, and EventLink component
     * triggers any arbitrary event on <em>its container</em>.
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    private String event;

    @Inject
    private ComponentResources resources;

    String defaultEvent()
    {
        return resources.getId();
    }

    @Override
    protected Link createLink(Object[] eventContext)
    {
        ComponentResources containerResources = resources.getContainerResources();

        return containerResources.createEventLink(event, eventContext);
    }
}

第二部分:简介
从AbstractLink抽象类继承的子类都是实现链接的组件。
<t:pageLink/>提供了页面跳转的link组件。
<t:actionLink/>提供了一个执行action方法事件的组件。
<t:eventlink/>提供了执行一个任意方法事件的组件。
三个组件类都是从AbstractLink继承而来,在AbstractLink中声明了anchor和disabled两个组件参数,以上三个组件全部集成了这两个组件参数。
anchor参数的作用是增加一个锚点,HTML中的锚点应该很熟悉吧!不说了。
disabled参数的作用看名字就知道了,就是禁用不禁用的意思,如果值为true则不渲染任何内容,直接输出组件内部文本,如果为false(默认)则渲染一个a标签出来,然后输出到HTML。
<t:pageLink/>组件类PageLink中声明了一个page的参数,用来指定要跳转到的page名。
<t:actionlink/>和<t:eventlink/>两个组件类ActionLink和EventLink都继承了AbstractComponentEventLink,而AbstractComponentEventLink又是AbstractLink的实现子类。
其中在AbstractComponentEventLink中声明了context和zone两个组件参数,context用来做参数传递的,而zone用来进行ajax更新的,涉及<t:zone/>的使用,详细介绍以后会讲解。
context参数的作用是用来传递参数,被跳转到的页面的onActivate方法接收,如果<t:actionlink/>和<t:eventlink/>未指定context属性,那么则使用跳转到的页面的页面类的onPassivate方法进行参数传递,如果指定了context,则onPassivate不执行,具体看示例代码。
<t:actionlink/>组件是<t:eventlink/>的一个简化实现,可以类似于<t:eventlink/>组件指定event属性为action。其中的event是需要在页面类触发的事件方法名,方法名的格式是:on+eventName。其中eventName是event的参数值,方法名中的eventName第一个字母大写。

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

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
	<head>
		<title>link component</title>
	</head>
    <body>
    	<t:pagelink page="another" context="param">another</t:pagelink>
    	<t:pagelink page="another" anchor="pre2">another_pre2</t:pagelink>
    	<t:actionlink t:id="actionId" zone="actionlinkzone">actionlinkzone</t:actionlink>
    	<t:eventlink event="testevent" zone="eventlinkzone">eventlinkzone</t:eventlink>
    	
    	<t:zone t:id="actionlinkzone" id="actionlinkzone">
    		actionlinkzone count:${count}
    	</t:zone>
    	<t:zone t:id="eventlinkzone" id="eventlinkzone">
    		eventlinkzone count:${count}
    	</t:zone>
    </body>
</html>

Start.java

package jumpstart.web.pages;

import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.corelib.components.Zone;

public class Start {
	@Property
	private String param="context param";
	@Property
	@Persist
	private int count;
	@InjectComponent
	private Zone actionlinkzone;
	@InjectComponent
	private Zone eventlinkzone;

	Object onActionFromActionId() {
		count--;
		return actionlinkzone.getBody();
	}

	Object onTestevent() {
		count++;
		return eventlinkzone.getBody();
	}

}

Another.tml

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
	<head>
		<title>page another</title>
		<style>
			.red{color:red;}		
		</style>
	</head>
    <body>
    	<div class="red">${message}</div>
    	<pre id="pre1">
    		pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 pre1 
适当复制内容才可以看到锚点的效果。
    	<pre id="pre2">
    		pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 pre2 
适当复制内容才可以看到锚点的效果。
    	</pre>
    </body>
</html>

Another.java

package jumpstart.web.pages;

import org.apache.tapestry5.annotations.Property;

public class Another {
	@Property
	private String message = "default message";

	void onActivate(String message) {
		this.message = message;
	}

	String onPassivate() {
		return "from passivate";
	}
}

最终的效果

第四部分:分析
上述测试代码最终效果不完整或者与你看到的效果有些出入,根据简介内容自己研究吧!
这里我说一下我的理解:
1.eventlink和actionlink两个组件的重要区别就是各自组件类中的createLink方法内容,其中的actionlink组件类中的createLink方法内容是
return resources.createEventLink(EventConstants.ACTION, contextArray);
其中EventConstants.ACTION的常量值就是action,contextArray就是context的属性值,这就是简介中提到<t:actionlink/>组件是<t:eventlink/>的一个简化实现,可以类似于<t:eventlink/>组件指定event属性为action。为了验证这一点,我们看看eventlink组件类中的createLink方法内容
        ComponentResources containerResources = resources.getContainerResources();
        return containerResources.createEventLink(event, eventContext);
第一行的内容是获得当前组件的容器组件,我的理解应该就是主组件,因为组件有可能是一个mixin,而这个mixin是附着在另外一个组件的,这句就是这个作用。(源码中写的)
第二行的内容就和actionlink的类似了,只不过EventConstants.ACTION参数换成了event,而event就是eventlink的一个属性。
2.Zone参数的功能实现涉及到org.apache.tapestry5.services.ClientBehaviorSupport类,这个以后再研究。
3.pagelink组件类中的重要代码是resources.createPageLink(page, resources.isBound("context"), context);该句代码创建了一个跳转到page参数的org.apache.tapestry5.Link,该方法已经被声明为废弃的了,被org.apache.tapestry5.services.PageRenderLinkSource#createPageRenderLink(String)和org.apache.tapestry5.services.PageRenderLinkSource#createPageRenderLinkWithContext(String, Object[])代替,一个方法被两个方法分解,岂是就是将resources.isBound("context")的作用进行分解了,createPageRenderLink方法是一个不带context(就是组件中context未指定)参数的实现,createPageRenderLinkWithContext方法是一个带context参数的实现。

以上是我对这三个组件的源码研究,如果不正确的,请大家指出。

© 著作权归作者所有

阎王他爹
粉丝 2
博文 17
码字总数 16401
作品 1
昆明
私信 提问
第十二讲:tapestry actionlink与eventlink组件

actionlink与eventlink组件非常相似,都是执行一个事件,在代码编写上有一点点差异。源代码如下: MyEvent.java 项目名称:TapestryStart 开发模式:Maven+Tapestry5.x+Tapestry-hibernate+...

神勇小白鼠
2012/04/13
244
0
第三十三讲:tapestry Ajax eventlink无刷新页面

tapestry的Ajax使用非常简单,Ajax的页面无刷新,刚好解决了eventlink、actionlink等组件无刷新,这点在js应用中非常的强大。下面就于eventlink组件为例。源码如下: AJAXEventLink.java /**...

神勇小白鼠
2012/04/24
150
0
tapestry using ajax

请参看tapestry的官方文档,这里只是总结性的备忘录。 http://tapestry.apache.org/ajax-and-zones.html http://www.w3cschool.cc/jquery/jquery-dom-set.html 相关内容: t:zone组件: 决定a...

zhouyc
2014/06/12
528
0
第二十四讲:tapestry的grid组件

tapestry的grid组件,具体实现方法看源码吧,之前的教程也有讲到,这次配合数据库操作使用,实体Person.java在第二十三讲中已经贴出来了,这里就不贴了,其他源码如下: PersonCreate.java ...

神勇小白鼠
2012/04/16
306
0
第五讲:tapestry增删改查---删除数据

思路:根据user的id去删除数据,直接从UserList页面实现删除。 修改UserList.java,与UserList.tml文件。代码如下: UserList.java 项目名称:TapestryStart 开发模式:Maven+Tapestry5.x+T...

神勇小白鼠
2012/04/13
122
0

没有更多内容

加载失败,请刷新页面

加载更多

vue vue-router beforeRouteEnter

本文转载于:专业的前端网站➬vue vue-router beforeRouteEnter beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `thi...

前端老手
53分钟前
4
0
Spring Boot 2 实战:结合 Docker 容器化

1. 前言 Docker 是啥?好处是啥? 什么现在如果作为一名开发你还不知道甚至没有用过我都感觉你落伍了。Docker 是一种虚拟化的容器技术,目的为了打造持续集成、版本控制、可移植性、隔离性和...

码农小胖哥
57分钟前
4
0
Linux 常用查询句柄的命令(Too many open files)

摘要 查询命令 进程占用的句柄总数 lsof -n | wc -l 查看哪一个进程占用的句柄最多 lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more 第一列 是 占用句柄数; 第二列 是 进程号 PID;...

liangxiao
57分钟前
5
0
JavaScript权威指南笔记5

第五章、语句 0、概述 JS程序是一系列可执行语句的集合。 通过控制语句来改变语句的默认执行顺序。 控制语句:条件、循环和跳转(如return、break和throw) 2、复合语句 当多条语句被当做一条语...

_Somuns
今天
5
0
vmware安装ubuntu18.04总是 panic -not syncing:corrupted stack end detected inside schedule

Vmware 安装ubuntu 总是卡着不动, 提示panic -not synciong 网上提示很多办法,都试了效果不佳, 找到了完美解决办法 你的兼容模式重新选一下为6.0,兼容性对硬件有要求的 即可实现 成功安装...

dragon_tech
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部