现在的位置: 首页 > 综合 > 正文

HTML + JavaScript 学习Metro程序 (1)

2013年12月06日 ⁄ 综合 ⁄ 共 7115字 ⁄ 字号 评论关闭

Windows 8 已经正式发布了,有人说好,也有人说不好。但是不管怎样, Windows 8 肯定会有大量的用户。作为程序员,当然又得学习新的东西了,俺也不例外啊。

Windows 8的传统界面跟Windows 7 没有太大区别,区别大的就是Metro风格了(现在好像叫做Modern UI了吧)。

根据MSDN上的说法,开发Metro程序有三种方式:

1. HTML + JavaScript

2. C#/VB + XAML

3. C++ + XAML/DirectX

个人觉得如果Metro App里面UI部分比较多的话,采用第一种或者第二种比较好,不太推荐C++, 当然如果App里面比较涉及底层的话,还是C++。

 

我先选择HTML + JavaScript来学习开发Metro程序。第一次开发Metro,错误在所难免,各位大哥不要笑话啊。

MSDN上面已经有很详细的说明了:http://msdn.microsoft.com/zh-cn/library/windows/apps/br211385.aspx。这里主要是为了记录一下我自己的学习过程。

 

先从最最简单的Blank App开始,用VS2012创建一个JavaScript Windows store 应用程序,选择Blank App模板,如下图。

随后,VS就生成了一个模板代码。主要有3个文件:default.css, default.js, default.html.

这也就是HTML + JavaScript开发Metro应用程序的3个重要组成部分:

1. css文件: 用来协助HTML文件布局UI;

2. HTML文件:处理UI;

3. js文件:程序的代码。

对于做过Web开发的程序员来说,可以很快的用javascript做一个Metro小应用。因为CSS, HTML 和javascript在web开发里面太常见了。

接下来,我用javascript来模拟一个小应用吧,就模拟做一个登录页面。比如:

很简单,就居中放一个登录框。我用default.js, default.css, default.html来处理这个对话框。

先来看看default.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>App1</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

    <!-- App1 references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    
    
    <div id="logging">
        <div class="row" style="margin-top:50px">
            Username: <input id="TextUserName" type="text" style="width:150px"/>
        </div>
        <div class="row">
            Password: <input id="TextPassword" type="password" style="width:150px"/>
        </div>
        <div class="row" style="margin-top:20px;margin-left:50px">
            <button type="button" id="login" style="position:relative">Login</button>
            <button type="button" id="register" style="position:relative">Register</button>
        </div>
        <div class="row" style="margin-top:20px;margin-left:50px">
            <p id="hint"></p>
        </div>
    </div>
    
</body>
</html>

其中<div id="logging"></div>,这部分就是用来显示登录框的。相当的简单啊,这个对于做过web开发的程序员来说简直是小菜一碟,呵呵。

看看相应的css:

body {
}

@media screen and (-ms-view-state: fullscreen-landscape) {
}

@media screen and (-ms-view-state: filled) {
}

@media screen and (-ms-view-state: snapped) {
}

@media screen and (-ms-view-state: fullscreen-portrait) {
}



#logging {
    border: 2px solid #C0C0C0;
    background-color: #008080;
    font-family: 黑体;
    font-size: 20px;
    position: fixed;
    width: 300px;
    height: 300px;
    top: 50%;
    left: 50%;
    margin-left: -150px;
    margin-top: -150px;
}

.row {
    width: 260px;
    height: auto;
    margin-left:10px;
}

我就加了一个id和一个class,其中id logging里面,为了把登录框居中显示,用了一个小技巧,就是top和left都是50%,这样左上角的位置就是屏幕中心,然后margin-left, margin-top用了一个负数,也就是宽度和高度的一半。这样就相当于登录框的中心点在屏幕的中心了。这样办法使用于任何屏幕分辨率。

 OK, 接下来就看看代码:

// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
    "use strict";

    WinJS.Binding.optimizeBindingReferences = true;

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
               
            }
            args.setPromise(WinJS.UI.processAll().done(function () {
                AddEvents();
            }));
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    WinJS.UI.Pages.define("/default.html", {
        // This function is called whenever a user navigates to this page. It
        // populates the page elements with the app's data.
        ready: function (element, options) {
            // TODO: Initialize the page here.
            AddEvents();

            var appData = Windows.Storage.ApplicationData.current;
            var roamingSettings = appData.roamingSettings;

            var username = document.getElementById("TextUserName");
            var str = roamingSettings.values["username"];
            username.value = str;
        },

    });

    // The click event handler for login
    function Login(mouseEvent) {
             window.navigate("pagecontrol.html");
     //   WinJS.Navigation.navigate("pagecontrol.html");
    }

    function Register(mouseEvent) {
        var hint = document.getElementById("hint");
        var username = document.getElementById("TextUserName");
        var pwd = document.getElementById("TextPassword");
        hint.innerText = "username:" + username.value + "\npassword:" + pwd.value;

    }

    function nameInputChanged(eventInfo) {
        var ele = eventInfo.srcElement;

        var appData = Windows.Storage.ApplicationData.current;
        var roamingSettings = appData.roamingSettings;
        roamingSettings.values["username"] = ele.value;
    //    WinJS.Application.sessionState.UserName = ele.value;
    
    }


    function AddEvents() {
        var login = document.getElementById("login");
        login.addEventListener("click", Login, false);
        var register = document.getElementById("register");
        register.addEventListener("click", Register, false);
        var username = document.getElementById("TextUserName");
        username.addEventListener("change", nameInputChanged);
    }

    app.start();
})();

增加一个函数function AddEvents(),这个函数用来给按钮设置响应函数。那么我们在什么地方调用这个函数呢?

1. 在app.onactivated里面,这样等于app激活的时候就设置按钮的响应函数;

2. 但是这里好像有个问题,对于app中有多个页面的时候,app.onactivated不会调用多次。比如切换到第二个页面,那么第二个页面的按钮的响应函数什么时候设置呢?我们可以使用ready成员函数,如:

WinJS.UI.Pages.define("/default.html", {
        // This function is called whenever a user navigates to this page. It
        // populates the page elements with the app's data.
        ready: function (element, options) {
            // TODO: Initialize the page here.
            AddEvents();
    });

我还不是很确定ready函数是页面开始加载前调用,还是页面已经加载完了再被调用?这个还得进一步确认。

 

注意,JavaScript的匿名函数的第一行代码, "use strict",这个意思是使用strict(严格)模式,MSDN上是这么解释的:

Strict mode is a way to introduce better error-checking into your code. When you use strict mode, you cannot, for example, use implicitly declared variables, or assign a value to a read-only property, or add a property to an object
that is not extensible. The restrictions are listed in the Restrictions on Code in Strict Mode section later in this topic.

 ok,这个例子里面有2个按钮,登录和注册,注册就简单显示一条信息。登录的话,就是切换到第二个页面。

那么如何添加一个新的页面呢?也是很简单,在vs向导就可以了,如:

我们只有增加一个PageControl就行了,然后VS就会自动生成3个文件:css,html,js。

注意上面登录按钮里面是如何切换到第二个页面的,我这里使用window.navigate("pagecontrol.html");来切换到第二个页面。其实这个地方有好几种办法,web开发里面的js跳转页面的方法基本都可以用。而且微软自己好像也封装了一些办法,这个不在这里探讨了。

第二个页面很简单,就放了个返回登录页面的链接:

怎么实现的呢,太简单了,就用了一个html超链接:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>pagecontrol</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

    <link href="/css/pagecontrol.css" rel="stylesheet" />
    <script src="/js/pagecontrol.js"></script>
</head>
<body>
    <div class="pagecontrol fragment" style="text-align:center">
        <header aria-label="Header content" role="banner">
            <button class="win-backbutton" aria-label="Back" disabled type="button"></button>
            <h1 class="titlearea win-type-ellipsis">
                <span class="pagetitle">Second page</span>
            </h1>
        </header>
       
        <a href="/default.html">return to "login page"</a>
    </div>

    
</body>
</html>

就是这一行:<a href="/default.html">return to "login page"</a>,其他什么也没做,cool。

ok,再介绍一下数据存储。我们可以使用2种对象:

1. Windows.Storage.ApplicationData.current.roamingSettings

2. WinJS.Application.sessionState

第一种是“永久”存储,就是说就算应用退出了,数据还是存在的。

第二种就是临时的了MSDN上的说法是:

会话数据为临时数据,它与应用中用户的当前会话相关。会话会在以下情形下结束:用户使用关闭手势或 Alt + F4 关闭应用、重新启动计算机或注销计算机。

上面的例子里面使用了第一种“永久”存储。使用也是相当的简单,通过这些对象,我们可以把应用的状态保存起来,然后在某种情况下恢复,比如把应用从后台迁到前台。

 

先学习到这里,下一次来看看“应用栏”的使用。

抱歉!评论已关闭.