Google Web Toolkit(GWT)中的多页教程

Mak*_*sim 60 navigation gwt

我刚开始学习Google Web Toolkit(GWT).如何在GWT应用程序中创建不同的HTML页面?

例如,我想为书店创建一个应用程序.在这个应用程序中,我将有三页:

  1. 主页我欢迎用户并提供用户书籍
  2. 页面按类别浏览书籍并查看详细信息(使用GWT小部件)
  3. 在线查看书籍.

当然可能还有其他页面,比如用户的详细信息,添加新书等等.那么,在GWT中制作不同页面的最佳方法是什么?如何在页面之间进行导航?有没有例子或教程?或者,当我可以在一个页面中创建整个应用程序时,我是否还需要创建不同的页面?

Chr*_*alo 74

我在这种情况下通常做的是首先设计网页框架.我将有标题,侧面菜单和页脚的div.div我的HTML中还有一个主要内容.

例:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta name='gwt:module' content='org.project.package.Core=org.project.package.Core'>
    </head>
    <body>
        <!-- Load the JavaScript code for GWT -->
        <script language="javascript" src="ui/org.project.package.ui.Core.nocache.js"></script>

        <!-- For some unknown reason in Internet Explorer you have to have cellpadding/spacing ON THE ELEMENT and not on the STYLE if it is in the body tag like this -->
        <table id="wrapper" cellpadding="0" cellspacing="0" style="width: 100%;height: 100%;">

             <!-- Header row -->
             <tr style="height: 25%;">
                 <td colspan="2" id="header"></td>
             </tr>

             <!-- Body row and left nav row -->
             <tr style="height: 65%;">
                 <td id="leftnav"></td>
                 <td id="content"></td>
             </tr>

             <!-- Footer row -->
             <tr style="height: 10%;">
                <td colspan="2" id="footer"></td>
             </tr>

        </table>

        <!-- This iframe handles history -->
        <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

(如果您喜欢基于<div>的布局,请随意使用它们.)

然后Core.java像往常一样构建入口点(在我的例子中),根据需要设置每个元素.

RootPanel.get("header").add(new Header());
RootPanel.get("leftnav").add(new NavigationMenu());
RootPanel.get("footer").add(new Footer());
Run Code Online (Sandbox Code Playgroud)

当然,可以有一个静态页脚和标题,但这既不是在这里也不是在那里.

我还有一个名为"Content"的抽象类.内容对象扩展为"Composite",并且将具有各种方法来简化新页面的创建和布局.我为此应用程序构建的每个页面,无论是帮助屏幕,搜索屏幕,购物车还是其他任何类型,都是类型Content.

现在,我所做的是创建一个名为"ContentContainer"的类.这是一个负责管理"content"元素的单例.它有一个方法"setContent",它接受"Content"类型的对象.然后它基本上删除"content"<td>中的任何内容,并将其替换为您通过"setContent"方法分配的任何窗口小部件(Composite).setContent方法还处理历史记录和标题栏管理.基本上,如果每个页面内容必须"知道"它必须执行的所有功能,ContentContainer用于聚合您可能必须进行的所有各种绑定点.

最后,你需要一种方法来访问那个页面,对吗?这很简单:

ContentContainer.getInstance().setContent(new Search());
Run Code Online (Sandbox Code Playgroud)

将上述内容置于某个地方的点击事件中,您就是金色的.

您的其他小部件需要绑定的唯一内容是ContentContainer和它们添加的内容类型.

我可以看到ChrisBo的方法的缺点是你有一个必须维护令牌 - >页面的列表.我能看到的另一个缺点是我看不出你如何使用这种方法建立一个真正的历史系统.

它对我的方法提供的一件事是所有页面选择都非常集中.我会使用某种Enum或至少一个带有String值的静态类来防止自己混淆链接.

在任何一种情况下,我认为这一点可以概括为:根据用户点击用户执行的操作来交换某些中心页面元素的内容.


Chr*_*ing 20

我会使用HyperLink和History类.关于Hyperlink类的好处是,它设置了这个标记(例如#foobar),而你所要做的就是捕获事件,当更改令牌的值时会触发该事件(ValueChangeEvent).在eventHandler中,您将替换页面.

示例:欢迎地址页面:www.yourpage.com/#home在此页面上将是"浏览书"页面的链接,当点击链接时,新地址将是这样的:www.yourpage.com /#浏览

以下是代码:


public class MainEntryPoint implements EntryPoint, ValueChangeHandler {
    VerticalPanel panel = new VerticalPanel();
    Label label=new Label();
    public void onModuleLoad() {
        Hyperlink link1 = new Hyperlink("books", "browse");
        Hyperlink link2 = new Hyperlink("user details", "details");
        panel.add(link1);
        panel.add(link2);
        panel.add(label);
        RootPanel.get().add(panel);
        History.addValueChangeHandler(this);
        //when there is no token, the "home" token is set else changePage() is called.
        //this is useful if a user has bookmarked a site other than the homepage.
        if(History.getToken().isEmpty()){
            History.newItem("home");
        } else {
            changePage(History.getToken());
        }
    }

public void onValueChange(ValueChangeEvent event) {
    changePage(History.getToken());
}
public void changePage(String token) {
    if(History.getToken().equals("browse")) {
        label.setText("Here would be some books");
    } else if (History.getToken().equals("details")) {
        label.setText("Here would be the user details");
    } else {
        label.setText("Welcome page");
    }
}
Run Code Online (Sandbox Code Playgroud)

}


小智 9

真棒!我将Chris R.的回答与Chris Boesing的结合起来得出这个结论:

这是'索引'起始页面

public class Index implements EntryPoint, ValueChangeHandler<String> {
    public void onModuleLoad() {
        History.addValueChangeHandler(this);
        if (History.getToken().isEmpty()) History.newItem("index");
        Composite c = new Login(); 
        FlowControl.go(c);
    }

    public void onValueChange(ValueChangeEvent<String> e) {
        FlowControl.go(History.getToken());
    }
}
Run Code Online (Sandbox Code Playgroud)

这是Chris R.的控制器或ContentContainer.

public class FlowControl {
private static FlowControl instance;
private FlowControl() {}
public static void go(Composite c) {
    if (instance == null) instance = new FlowControl(); // not sure why we need this yet since everything is static.
    RootPanel.get("application").clear();
    RootPanel.get("application").getElement().getStyle().setPosition(Position.RELATIVE); // not sure why, but GWT throws an exception without this. Adding to CSS doesn't work.
    // add, determine height/width, center, then move. height/width are unknown until added to document. Catch-22!
    RootPanel.get("application").add(c);
    int left = Window.getClientWidth() / 2 - c.getOffsetWidth() / 2; // find center
    int top = Window.getClientHeight() / 2 - c.getOffsetHeight() / 2;
    RootPanel.get("application").setWidgetPosition(c, left, top);
    History.newItem(c.getTitle()); // TODO: need to change and implement (or override) this method on each screen
}

public static void go(String token) {
    if (token == null) go(new Login());
    if (token.equals("cart")) go(new Cart());
    if (token.equals("login")) go(new Login());
    // Can probably make these constants in this class
}
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的代码中的任何地方胡椒超链接和按钮.(还没试过超链接.)

    Button submit = new Button("Submit");
    submit.addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
            FlowControl.go(new MyScreen());             
        }           
    });
Run Code Online (Sandbox Code Playgroud)

我在HTML中添加了一个div

<!-- This is where the application will reside within. It is controlled by FlowControl class. -->
<div id="application"></div>
Run Code Online (Sandbox Code Playgroud)

现在所有的屏幕必须在构造函数中调用initWidget()而不是添加到RootPanel,因为它现在是一个Composite类,就像

    initWidget(myPanel); // all composites must call this in constructor
Run Code Online (Sandbox Code Playgroud)


put*_*uan 5

如果你想要它是完全AJAXified(如桌面应用程序),当然你只需要一个页面.然后根据链接更改正文的内容.

此外,有一个非常活跃的GWT谷歌小组,我知道在此之前已经问过,你只需要使用"搜索"功能.