$30 off During Our Annual Pro Sale. View Details »

精通 JavaScript 作 Windows Store App 開發

Ping-Yen Tsai
September 20, 2012

精通 JavaScript 作 Windows Store App 開發

Microsoft Tech‧Days Taiwan 2012

Ping-Yen Tsai

September 20, 2012
Tweet

More Decks by Ping-Yen Tsai

Other Decks in Technology

Transcript

  1. 精通 JavaScript 作
    Windows Store App
    開發
    DEV308
    蔡秉諺 Vexed
    中華電信 Xuite

    View Slide

  2. 課程簡介
    Windows Store App ⽀支援以原先⽤用於網⾴頁前端
    開發的 HTML/CSS/JavaScript 技術來進⾏行
    app 的開發,這使得原先做網⾴頁開發的開發
    ⼈人員得以使⽤用既有的知識及技能來開發
    Windows 8 Apps。


    本課程將會介紹在使⽤用 JavaScript 開發
    Windows 8 Apps 時的細節,以及瞭解如何運
    ⽤用開發環境提供的 WinJS 函式庫來開發
    Windows 8 Apps。

    View Slide

  3. 微軟跟你說
    ⽤用 JavaScript 開發 Windows Store App


    和開發網⾴頁前端很像
    很像 !== ⼀一樣

    View Slide

  4. 不⼀一樣
    顧名思義


    可以上 Windows Store
    可以碰到系統底層
    可以離線操作

    View Slide

  5. 不⼀一樣
    多 Windows 、 WinJS 、 MSApp 物件
    少不適合 App 環境函式
    適應 App 環境⾏行為改變
    Cross-Domain AJAX

    View Slide

  6. Windows 物件
    不是 window 物件
    Windows Runtime API (WinRT API)
    C++ C# VB JavaScript 共通

    View Slide

  7. Windows 物件
    不夠⽤用、⾃自⼰己寫 WinRT Component
    C++ C# VB

    View Slide

  8. WinJS 物件
    Windows Library for JavaScript
    100% JavaScript 寫成
    跟 jQuery YUI ⼀一樣
    原始碼可以看、不能改

    View Slide

  9. WinJS 物件
    看原始碼、⽐比看⽂文件快
    base.js WinJS

    ui.js
    WinJS.UI

    註解
    搜尋

    View Slide

  10. 不⽤用 WinJS

    能寫 Windows Store App 嗎?
    不⽤用 jQuery 能寫網⾴頁嗎?
    能、但⿇麻煩
    WinJS 存在意義
    拉近 Windows 物件與網⾴頁前端開發距離

    View Slide

  11. WinJS 能在

    Windows Store App 外⽤用嗎?
    base.js ui.js 開頭註解
    This library is supported for use in Windows
    Store apps only.
    原始碼找 hasWinRT
    未使⽤用 Windows 物件分出
    為了 web context

    View Slide

  12. 少不適合 App 環境函式
    不可開新視窗
    無 open、moveBy、moveTo、resizeBy、resizeTo
    window.close()
    中⽌止 App 、例外使⽤用
    無 alert、comfirm、prompt
    Windows.UI.Popups.MessageDialog 替代
    改變動線

    View Slide

  13. 替代 alert
    var md = new Windows.UI.Popups.MessageDialog('Hi');

    md.showAsync().then(function() { 

    // ...

    });
    關閉

    View Slide

  14. 替代 confirm
    var md = new Windows.UI.Popups.MessageDialog('Are you OK?');


    md.commands.append(new Windows.UI.Popups.UICommand('Yes'));

    md.commands.append(new Windows.UI.Popups.UICommand('No'));


    md.showAsync().then(function (cmd) {

    console.log(cmd.label);

    });

    View Slide

  15. 替代 prompt
    無直接⽅方案
    改變動線
    選項明確
    Windows.UI.Popups.MessageDialog
    同 confirm
    Flyout 控制項
    無 Block UI

    View Slide

  16. 適應 App 環境⾏行為改變
    HTML and DOM API changes list
    的 href 、 target 屬性
    innerHTML、document.write ... 安全機制
    限制載⼊入外部 JavaScript
    Cross-Domain AJAX

    View Slide

  17. 的 href 屬性
    href="../a.html" 、 href="/b.html"
    App 內相對路徑、絕對路徑
    href="ms-appx:///c.html"
    App 內絕對路徑
    3 條斜線

    View Slide

  18. 為什麼 3 條斜線?

    Package 名稱
    package.appmanifest 可⾒見
    Package 名稱省略

    ms-appx-web:/// 、 ms-appdata:///

    View Slide

  19. 外部連結
    Bing
    跳離 App 、 Modern IE 開啟

    View Slide

  20. 的 target 屬性
    target="_blank"
    外部連結
    跳離 App 、 Modern IE 開啟
    App 內連結
    JavaScript 錯誤
    b


    正常運作
    有寫跟沒寫⼀一樣

    View Slide

  21. innerHTML、document.write ...

    安全機制
    elm.innerHTML = '!';
    JavaScript 錯誤
    elm.innerHTML = '';
    JavaScript 錯誤
    elm.innerHTML = toStaticHTML('…');
    Safe

    View Slide

  22. 限制載⼊入外部 JavaScript

    JavaScript 錯誤
    檔案下載、加⼊入 App 內

    View Slide

  23. Cross-Domain AJAX
    XMLHttpRequest
    Cross-Domain
    WinJS.xhr
    XMLHttpRequest
    Cross-Domain
    WinJS.xhr({ url : 'a.txt' }).then(function() {

    // …

    });
    App 內檔案

    View Slide

  24. MSApp 物件
    額外審查?
    都不是好東⻄西?
    WinJS 原始碼找 Unsafe
    MSApp.execUnsafeLocalFunction

    View Slide

  25. MSApp.execUnsafeLocalFunction
    innerHTML、document.write ... 安全機制
    elm.innerHTML = '!';
    JavaScript 錯誤
    MSApp.execUnsafeLocalFunction(function() {

    elm.innerHTML = '!
    p>';

    });
    Pass

    View Slide

  26. App 中顯⽰示外部網⾴頁
    Bing
    外部連結、跳離 App 、 Modern IE 開啟

    iframe 內 local context、外 web context

    iframe 內外 local context
    外部網⾴頁
    App 內網⾴頁

    View Slide

  27. web context
    與 Windows Store App 外幾乎相同
    無 Windows 物件
    WinJS 部分可⽤用
    無 innerHTML、document.write ... 安全機制
    不限制載⼊入外部 JavaScript
    AJAX 不可 Cross-Domain
    WinJS 原始碼找 hasWinRT

    View Slide

  28. web context
    App 內網⾴頁 web context 載⼊入

    local context 、 web context 溝通
    HTML5 postMessage()

    View Slide

  29. View Slide

  30. Windows Store App ⽤用 jQuery
    JavaScript 錯誤
    限制載⼊入外部 JavaScript
    檔案下載、加⼊入 App 內


    View Slide

  31. Windows Store App ⽤用 jQuery
    App 執⾏行
    3 個 JavaScript 錯誤
    jQuery 初始時觸犯
    innerHTML、document.write ... 安全機制
    原始碼找

    jQuery.support = (function() { ... })();
    jQuery.support = MSApp.execUnsafeLocalFunction(function() { ... }

    View Slide

  32. Windows Store App ⽤用 jQuery
    待續 …

    View Slide

  33. Windows Store App ⽤用

    Google Maps JavaScript API
    限制載⼊入外部 JavaScript
    無法檔案下載、加⼊入 App 內
    Google Map 放 map.html 裡
    web context 載⼊入


    View Slide

  34. ECMAScript 5
    Windows Store App 、 IE10 ⽀支援
    WinJS 原始碼
    不普及原因
    IE8 + Windows XP
    ECMAScript 5 compatibility table

    View Slide

  35. ECMAScript 5
    可 JavaScript 模擬
    Array.prototype.forEach
    Object.keys

    需瀏覽器底層⽀支援
    Object getter setter
    Object.defineProperty
    Strict Mode

    View Slide

  36. Object getter setter
    on 、 off 屬性
    只可讀、不可寫
    var strings = {

    get on() { return WinJS.Resources._getWinJSString("ui/on").value; },

    get off() { return WinJS.Resources._getWinJSString("ui/off").value; },

    };
    沒有 JavaScript 錯誤
    var v = 1,

    o = { get p() { return v; },

    set p(x) { v += x; } }; 

    o.p = 2;

    console.log(o.p); // 3

    View Slide

  37. Object.defineProperty
    configurable 、 writable 、 enumerable
    以前存在、看不到、碰不到
    Object.defineProperty(element, "winBindingToken", {

    configurable: false,

    writable: false,

    enumerable: false,

    value: bindingToken

    }

    );

    View Slide

  38. Strict Mode
    "use strict";
    Visual Studio 2012 ⾃自動加上
    strict 模式 (JavaScript) @ MSDN
    arguments.callee 不能⽤用
    block 中不可宣告函式
    call 、 apply 指定 this ⾏行為改變
    函式中 this ⾏行為改變

    View Slide

  39. arguments.callee 不能⽤用
    匿名函式中指向函式本⾝身
    遞迴呼叫
    "use strict"; 


    setTimeout(function() {

    setTimeout(arguments.callee, 1000);

    }, 1000);
    JavaScript 錯誤
    "use strict"; 


    setTimeout(function f() {

    setTimeout(f, 1000);

    }, 1000);
    最佳化
    IE9 (含) 以下有 bug

    View Slide

  40. block 中不可宣告函式
    function declaration
    "use strict";


    if(Windows) {

    function f() { console.log('hasWinRT'); }

    }
    JavaScript 錯誤
    "use strict";


    if(Windows) {

    var f = function() { console.log('hasWinRT'); }

    }
    改⽤用 function expression

    View Slide

  41. call 、 apply 指定 this ⾏行為改變
    "use strict";


    function f() { console.log(this); }


    f.call(null); // null

    f.call(undefined); // undefined
    ⾮非 Strict 模式、 window
    "use strict";


    f.apply(null, [1, 2, 3]);
    使⽤用⺫⽬目的為第⼆二個參數

    View Slide

  42. 函式中 this ⾏行為改變
    IE9 、 bug
    IE10 (原) 、 bug
    "use strict";


    f(); // undefined


    function f() { console.log(this); }
    ⾮非 Strict 模式、 window

    View Slide

  43. "use strict"; 能拿掉嗎?
    嚴謹好、事出必有因

    拿掉還沒碰到問題

    View Slide

  44. WinJS 實踐
    Promise 物件
    Observable 物件
    Single-page navigation

    View Slide

  45. Promise 物件
    Promise/A
    Promise/B
    Promise/D
    WinJS.Promise 、 jQuery Deferred 物件
    Promise/A
    不太相同

    View Slide

  46. WinJS.Promise
    超過 0.5 秒、⾮非同步、吐回 Promise 物件
    messageDialog.showAsync()
    WinJS.Application.local.readText()
    WinJS.xhr
    與 callback 相⽐比
    語意清晰

    View Slide

  47. AJAX a.php -> b.php -> c.php
    var xhr = new XMLHttpRequest();


    xhr.open('GET', 'a.php', true);

    xhr.onreadystatechange(function(http) {

    if(http.readyState == 4 && http.status == 200) {

    xhr.open('GET', 'b.php', true);

    xhr.onreadystatechange(function(http) {

    if(http.readyState == 4 && http.status == 200) {

    xhr.open('GET', 'c.php', true);

    xhr.onreadystatechange(function(http) {

    if(http.readyState == 4 && http.status == 200) {

    // ...

    }

    })

    xhr.send();

    }
    })

    xhr.send();
    }
    });
    xhr.send();

    View Slide

  48. AJAX a.php -> b.php -> c.php
    WinJS.xhr({ url: 'a.php' })

    .then(function() { return WinJS.xhr({ url: 'b.php' }); })

    .then(function() { return WinJS.xhr({ url: 'c.php' }); })

    .done(function() { /* ... */ });

    View Slide

  49. AJAX a.php b.php c.php 同時送出
    等三者皆完成


    再下⼀一步


    不⽤用 Promise

    View Slide

  50. AJAX a.php b.php c.php 同時送出
    WinJS.Promise.join([

    WinJS.xhr ({ url: 'a.php' }),

    WinJS.xhr ({ url: 'b.php' }),

    WinJS.xhr ({ url: 'c.php' })])

    .done(function() { /* ... */ });

    View Slide

  51. 視情況 AJAX a.php 或 b.php
    使⽤用情境
    例 多元登⼊入
    var xhr = XMLHttpRequest();


    if(type === 'A') {

    xhr.open('GET', 'a.php', true);

    xhr.onreadystatechange(function(http) {

    if(http.readyState == 4 && http.status == 200) {

    // http -> result

    f(result);

    }

    });

    xhr.send();

    }

    else {

    xhr.open('GET', 'b.php', true);

    xhr.onreadystatechange(function(http) {

    if(http.readyState == 4 && http.status == 200) {

    // http -> result

    f(result);

    }

    });

    xhr.send();

    }


    function f(result) { /* ... */ }

    View Slide

  52. 視情況 AJAX a.php 或 b.php
    var promise;


    if(type === 'A')

    promise = WinJS.xhr({ url : 'a.php' }).then(function(data){ /* ... */ });

    else

    promise = WinJS.xhr({ url : 'b.php' }).then(function(data) { /* ... */ }); 


    promise.done(function(result) { /* ... */ });

    View Slide

  53. 有值直接⽤用、沒值 AJAX a.php
    if(localStorage.x)

    f(localStorage.x);

    else {

    var xhr = XMLHttpRequest();

    xhr.open('GET', 'a.php', true);

    xhr.onreadystatechange(function(http) {

    if(http.readyState == 4 && http.status == 200) {

    // http -> result

    f(result);

    }

    });

    xhr.send();

    }


    function f(result) { /* ... */ };

    View Slide

  54. 有值直接⽤用、沒值 AJAX a.php
    var promise;


    if(localStorage.x)

    promise = WinJS.Promise.as(localStorage.x);

    else

    promise = WinJS.xhr({ url : 'a.php' }).then(function(data) { /* ... */ }); 


    promise.done(function(result) { /* ... */ });
    WinJS.Promise.as
    ⾮非 Promies 轉成 Promise

    View Slide

  55. ⾃自⼰己兜 Promise 物件
    Promise 內部 callback 實作
    參考 WinJS.xhr 原始碼
    var promise = new WinJS.Promise(function(complete, error, progress) {

    setTimeout(function() {

    // ...

    complete('DEMO');

    }, 3000);

    });

    View Slide

  56. setPromise
    待 Promise 執⾏行完畢、 Event 才完畢
    app.onready = function (ev) {

    ev.detail.setPromise(

    WinJS.Application.roaming.writeText("time.txt", new Date())

    );

    };

    View Slide

  57. Observable 物件
    var target = document.getElementById('target'), 

    a = { x : 1 },

    b = WinJS.Binding.as(a);


    b.bind('x', function(newVal, oldVal) { target.innerHTML = newVal; }); 


    console.log(target.innerHTML); // 1


    b.x = 2;

    console.log(target.innerHTML); // 2


    b.x = 3; 

    console.log(target.innerHTML); // 3

    View Slide

  58. Observable 物件
    ECMAScript 5 Object getter setter
    Observable Proxy
    WinJS.Binding
    WinJS.Binding.as
    WinJS.Binding.define

    WinJS 原始碼

    View Slide

  59. Single-page navigation
    Quickstart: Using single-page navigation
    WinJS.UI.Pages 、 WinJS.Navigation
    官⽅方建議使⽤用、較像 App

    View Slide

  60. Single-page navigation
    WinJS.UI.Pages.define("/pages/home/home.html", {

    ready : function (element, options) {

    WinJS.Utilities.query("a").listen("click", function(ev) {

    ev.preventDefault();

    WinJS.Navigation.navigate(ev.target.href);

    }, false);

    }

    }); 記得寫、否則

    View Slide

  61. Windows App Cert Kit
    簡稱 WACK 或 Windows ACK
    App 上架前
    JavaScript 特有不通過
    UTF-8 檔案編碼
    Bytecode 產⽣生

    View Slide

  62. UTF-8 檔案編碼
    檔案開頭要有 BOM
    jQuery 待續 …
    官⽅方說法、BOM 提⾼高 15 – 20% 效能

    View Slide

  63. Bytecode 產⽣生
    App 內 JavaScript 存為 Bytecode
    不通過處理步驟
    本機電腦 App 移除
    組態選單 Release
    專案 -> 市集 -> 建⽴立應⽤用程式套件
    精靈、 Windows App Cert Kit

    View Slide

  64. Bytecode 產⽣生

    View Slide

  65. Bytecode 產⽣生

    View Slide

  66. Bytecode 產⽣生

    View Slide

  67. Bytecode 產⽣生

    View Slide

  68. ⽴立即啟動!免費開發⼈人員帳⼾戶!!

    Windows Store / Windows Azure / Windows Phone
    擁有 MSDN 訂閱
    「取得代碼」後進⾏行註冊 http://aka.ms/startmsdn
    優惠內容:
    Windows Store / Windows Phone – 啟⽤用後12個⽉月, 完全免費!
    Windows Azure – 訂閱期間, 每⽉月固定的免費使⽤用量!

    View Slide

  69. Connect. Share. Discusss
    http://www.microsoft.com/taiwan/
    techdays2012/
    Microsoft Certification &
    Training Resources
    http://www.microsoft.com/learning/zh/tw/
    Resources for IT
    Professionals
    http://social.technet.microsoft.com/Forums/
    zh-tw/categories/
    Resources for Developers
    http://social.msdn.microsoft.com/Forums/zh-
    tw/categories/
    Resources

    View Slide

  70. View Slide

  71. 請協助完成「本課程問卷」,並在離開
    教室時交給⼯工作⼈人員!
    填妥⼤大會背包中的⼤大會問卷,可於活動
    第三天兌換問卷禮哦!
    感謝您的合作。

    View Slide

  72. View Slide