【译】如何使用Chrome开发者工具的移动设备仿真器

网站测试变得越来越复杂。仅仅在几个浏览器中检查功能的日子一去不复返了。你的最新杰作必须在一系列具有不同操作系统,屏幕分辨率和功能的移动、平板和桌面设备上进行严格评估。在极端情况下,它可能需要与原始开发一样长的时间。

该过程进一步被触摸屏、混合设备和高密度显示器复杂化。如果你使用鼠标和键盘在普通的PC上编码,将很难理解你的杰作如何操作。鼠标悬停等功能不一定会起作用,你的应用程序可能无法使用。但是,如何在开发过程中测试你的系统,避免在多个设备之间运行和切换的痛苦?

幸运的是,所有现代浏览器都提供移动设备仿真工具,并且Chrome中的移动设备仿真工具就是最好的工具之一。它可以在不离开舒服的PC开发环境下,帮助你识别早期的问题。

开发工具

启动Chrome,打开要测试的网页,然后打开开发者工具(菜单》更多工具》开发者工具,Mac快捷键是Cmd+Opt+I或F12,Windows和Linux快捷键是Ctrl+Shift+I)。

现在,你可以通过单击左上角的切换设备工具栏图标来启用浏览器仿真器:

启用移动设备仿真器

现在将出现设备仿真:

移动设备仿真器

当选择响应(Responsive)作为设备类型时,可以更改仿真屏幕的尺寸。

触摸启用仿真

将鼠标移到设备上可查看圆形“触摸”光标。这将对基于触摸的JavaScript事件(如touchstarttouchmovetouchend)做出反应。鼠标特定的事件和CSS效果不会做出反应。

按住Shift键,然后单击并移动鼠标以模拟双指缩放操作。

移动仿真器设备工具栏

值得花一点时间来让自己熟悉移动仿真器上方的工具栏和菜单:

移动手机仿真器设备工具栏

默认设置有:

  • 设备类型(或简称响应(Responsive)
  • 当前分辨率
  • 缩放(屏幕可以放大或缩小以更好得适合仿真器面板)
  • 竖屏/横屏切换按钮(假设选择了响应(Responsive)之外的设备)

三点菜单允许你显示或隐藏其他设置:

  • 设备边框(如果可用,手机或平板电脑的外观图形)
  • 媒体查询
  • 像素标尺
  • 设备像素比(例如2.0用于仿真的视网膜屏幕)
  • 设备类型(类别如“mobile”或“tablet”)
  • 网络限制(一种在较慢的连接上限制带宽和测试性能的方法)
  • 捕获包括设备边框(如果显示)的屏幕截图。
  • 最后一个选项允许你重置以上这些设置到默认状态。

移动手机仿真器设备工具栏选项

CSS媒体查询工具栏

工具栏下方的栏显示一系列典型的手机,平板电脑和设备尺寸。当选择响应(Responsive)作为设备的宽度设置时,可以单击此选项。

从三点菜单中选择显示媒体查询(Show media queries),以查看在CSS中设置的所有媒体查询的图形颜色编码表示。

Chrome移动设备仿真器媒体查询

  • 蓝色——以最大宽度的查询
  • 绿色——以一个范围内宽度的查询
  • 橘色——以最小宽度为目标的查询

可以单击任何颜色的条形栏以将仿真器屏幕设置为该宽度。

仿真设备选项

左侧的下拉菜单允许你选择设备。为流行的智能手机和平板电脑提供了几十个预设,包括iPhone,iPad,Kindles,Nexus平板电脑,三星Galaxy等。

并非所有设备都会同时显示在这里 – 选择设备下拉菜单中的编辑(Edit)…,或从开发者工具菜单(F1)中选择设置(Settings),然后选择设备(Devices)标签:

Chrome移动设备仿真器设备

你可以启用或禁用设备或通过以下定义输入你自己的设备:

  • 名称
  • 类型,比如“Mobile”或“Tablet”
  • 浏览器user agent字符串
  • 设备分辨率
  • 像素比(例如iPhone Retina屏幕的像素比是2,其中像素密度是所报告的视口分辨率的两倍高)。

请注意,所有浏览器都使用HTTP headers中的用户代理(UA)字符串来标识自己。这可以在客户端或服务器端上检查,并且在web开发的黑暗日子期间(各个浏览器相互之间不兼容),将用于修改或提供不同的用户体验。在极端情况下,浏览用户将被引导到不同的站点。该技术总是有缺陷的,但由于响应的网页设计技术和完全不可持续的市场上提供的设备数量已经变得很大程度上冗余。

带宽限制模拟

限制(Throttling)下拉菜单允许你模拟移动连接或不可靠的酒店和机场WiFi经常遇到的慢网络速度!你可以使用它来确保你的网站或应用程序快速加载,并在所有环境中保持响应。

网络(Network)标签和Chrome的设备工具栏(启用时)可以使用限制下拉菜单。你可以通过选择限制下拉菜单底部的编辑(Edit…)或从开发者工具菜单(F1)中选择设置(Settings)并选择限制(Throttling)选项卡来设置自己的带宽配置:

Chrome移动设备仿真器带宽

单击添加自定义配置文件(Add custom profile),然后输入:

  • 配置文件名称
  • 下载速度(千比特每秒)
  • 上传速度(千比特每秒)
  • 以毫秒为单位的延迟(在进行网络请求时的典型延迟)

仿真移动传感器

智能手机和平板电脑通常具有传感器,例如在台式设备中不存在的GPS,陀螺仪和加速度计。这些可以在Chrome中通过选择更多工具(More tools),然后从开发工具主三点菜单中选择传感器(Sensors)

Chrome移动设备仿真器带宽

将出现一个新面板,你可以定义:

  • 当前的纬度和经度,或从下拉列表中选择一个主要城市。你也可以选择禁用位置,用来模拟当设备无法获取GPS信号时应用程序的反应。
  • 方向。有几个可用的预设方向,或者可以通过单击和拖动来移动设备图像来改变方向。

远程真实设备调试

最后,Chrome允许你通过USB连接真实的Android设备进行远程设备调试。从开发者工具主三点菜单中选择更多工具(More tools),然后选择远程设备(Remote devices)。确保勾选Discover USB debices,然后连接手机或平板电脑,并按照说明进行操作。

Chrome允许你设置端口转发,以便导航到设备上本地服务器上的网址。 Chrome的预览面板显示设备屏幕的同步视图,你可以使用设备或Chrome本身进行交互。

全方位的开发者工具包括应用程序(Application)选项卡,可用于在离线模式下测试Progressive Web Apps。请注意,不同于需要HTTPS的真实应用程序,Chrome允许PWA通过HTTP连接从本地主机运行。

太棒了!我现在不需要任何设备!

Chrome的移动浏览器模拟器非常实用和强大,但它不能替代在真实设备上与你的网站或应用互动,以评估完整的用户体验。

你也应该知道,没有设备模拟器是完美的。例如,Chrome在iPhone或iPad上显示网页的表示,但不会尝试模拟Safari的标准支持或怪异模式(quirks)。

尽管如此,对于快速和讨厌的移动测试,Chrome的设备模拟器是优秀的。它比在真正的智能手机和平板电脑设备之间切换容易得多,你将拥有所有的开发工具。这将节省工作量。

1.学习TypeScript——使用VS Code搭建TypeScript开发环境

前言

TypeScript和VSCode已经成为了2016年前端开发最流行的开发语言和开发工具之一,更多请看2016年JavaScript流行详情。使用TypeScript语言开发的类库和框架也越来越多,鼎鼎大名的Google的Angular 2中文网)项目就是使用TypeScript作为主要的开发语言的(还有JS版本和Dart版本)。

现在浏览器显然已经不能满足了JS了,很多App也开始使用JS开发了,使用基于TypeScript的IonicNativeScript能够快速高效地帮助你开发APP。

TypeScript是JavaScript的超集,TypeScript只是增强了JavaScript而非改变了JavaScript,TypeScript同样也是基于ECMAScript标准的编程语言。因此非常流行的Vue和React及我们常用Jquery等类库都可以使用TypeScript来编码,TypeScript强大的智能类型分析系统,能够使你的代码更加强壮。

说了这么多TypeScript的优点,下面让我们来学习如果在VScode中使用TypeScript开发项目吧。

下载TypeScript

TypeScript官网中文网)提供了多种下载方式,我们使用NPM来下载TypeScript,如果你没有安装NPM,请到Nodejs官网进行安装。

在CMD(Windows系统)或者终端(macOS系统)中输入一下命令:

npm install -g typescript

安装完毕后我们输入tsc -v可以查看当前安装的TypeScript版本号。当前最新的版本是2.1.5。

下载VSCode

VSCode是我使用过最棒的编辑器没有之一,比Sublime Text还有优秀。

VSCode官网就可以下载相应系统的VSCode安装包,最新的VSCode版本是1.9。

VSCode下载图

创建项目

创建目录

首先我们创建一个项目文件夹,比如叫ts_vscode,然后创建一些主要目录,在VSCode中打开项目,在macOS上我们可以直接使用命令来操作:

# 创建ts_vscode及主要文件夹
mkdir -p ts_vscode/src/{css,images,fonts}

# 使用VSCode打开
code ts_vscode

目录结构:

ts_vscode/
    └─src/
        ├─ css/
        ├─ fonts/
        └─ images/

创建package.json

使用命令npm init来创建package.json文件,一般默认就可以,具体详情可以看这里

创建

目录结构:

ts_vscode/
    ├─ src/
    │    ├─ css/
    │    ├─ fonts/
    │    └─ images/
    └─ package.json

创建tsconfig.json

使用tsc --init命令就可以快速创建一个tsconfig.json文件,关于tsconfig.json的属性描述请访问这里

目录结构:

ts_vscode/
    ├─ src/
    │    ├─ css/
    │    ├─ fonts/
    │    └─ images/
    ├─ package.json
    └─ tsconfig.json

安装项目依赖和开发依赖

我们的这个项目使用jQuery和Bootstrap来做,因此我们使用npm来安装:

npm install jquery bootstrap --save

我们的项目使用了TypeScript来开发,因此我们需要下载相对应的声明文件,关于声明文件请访问这里。安装声明文件命令:

npm install @types/jquery @types/bootstrap -save-dev

创建index.html

ts_vscode目录下创建index.htmlindex.html文件中放入下面的代码:

<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>TypeScript with VSCode</title>
  <!-- Bootstrap -->
  <link rel="stylesheet" href="./node_modules/bootstrap/dist/css/bootstrap.min.css">
  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  <!--[if lt IE 9]>
    <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
  <![endif]-->
  <link rel="stylesheet" href="./src/css/index.css">
</head>

<body>
  <h1 class="text-center"></h1>
  <div class="container">
    <div class="row show-grid">
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
      <div class="col-md-1">.col-md-1</div>
    </div>
    <div class="row show-grid">
      <div class="col-md-8">.col-md-8</div>
      <div class="col-md-4">.col-md-4</div>
    </div>
    <div class="row show-grid">
      <div class="col-md-4">.col-md-4</div>
      <div class="col-md-4">.col-md-4</div>
      <div class="col-md-4">.col-md-4</div>
    </div>
    <div class="row show-grid">
      <div class="col-md-6">
        <button type="button" class="btn btn-default" aria-label="Left Align">
          <span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>
        </button>
      </div>
      <div class="col-md-6">
        <button type="button" class="btn btn-default btn-lg">
          <span class="glyphicon glyphicon-star" aria-hidden="true"></span> Star
        </button>
      </div>
    </div>
  </div>
  <!-- /.modal -->
  <!-- js -->
  <script src="./node_modules/jquery/dist/jquery.min.js"></script>
  <script src="./node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
  <script src="./src/index.js"></script>
</body>

</html>

目录结构:

ts_vscode/
    ├─ src/
    │    ├─ css/
    │    ├─ fonts/
    │    └─ images/
    ├─ index.html
    ├─ package.json
    └─ tsconfig.json

创建index.ts文件并编写TS代码

src目录下创建index.ts文件。我们使用TS编写一个类,并使用这个类的方法向index.htmlh1标签中插入一句话,代码如下:

class Main {
    constructor() {

    }

    name: string;

    show(text: string): void {
        let $ele: JQuery = $("h1");
        $ele.text(text);
    }
}

let main = new Main();
main.name = "Hello TypeScript";
main.show(main.name);

目录结构:

ts_vscode/
    ├─ src/
    │    ├─ css/
    │    ├─ fonts/
    │    ├─ images/
    │    └─ index.ts
    ├─ index.html
    ├─ package.json
    └─ tsconfig.json

编译和启动项目

我们使用package.json中的scripts来编译和启动项目。

编译比较简单,tsc命令就可以编译项目,tsc -w命令监控并自动编译,编译会使用tsconfig.json中的配置项。

启动项目我们安装live-server,来帮助我们启动一个服务器环境,live-server非常轻便且带有自动刷新功能,我们使用npm全局安装即可:

npm install -g live-server

安装完毕后,我们修改package.json中的scripts如下:

"scripts": {
    "test": "tsc -w & live-server"
}

最终目录结构:

最终目录结构

最后我们在终端中输入npm t就可以启动项目了,启动成功后如下图:

启动项目成功

尝试改变项目文件,你可以发现浏览器会自动编译和自动刷新哦。

总结

本文章我们认识了VSCode和TypeScript,学会了基本的安装和编译及简单的TypeScript代码编写。本篇文章的示例代码请访这里

下篇文章我们将学习如何构建打包TypeScript项目。

[译]TypeScript 2.0 Beta发布

今天我们非常兴奋地推出了TypeScript 2.0 beta版。如果你还不熟悉TypeScript,现在你就可以去我们的网站上学习。

获取beta版,你可以下载TypeScript 2.0 Beta for Visual Studio 2015 (此更新需要VS 2015 Update 3),或者运行

npm install -g typescript@beta

这个版本包含大量新特性,如新的方式获取.d.ts文件,但是这里的一些特性仅仅是对其了解。

非空类型

nullundefined是JavaScript bugs中最常见的两个来源。在TypeScript 2.0 之前,nullundefined存在每一类型域中。这意味着如果你有一个带有string类型参数的函数,你不能肯定是单一类型的,实际上有可能是string类型,也有可能是null类型。

在TypeScript 2.0,新的--strictNullChecks编译参数改变这一不确定性。string类型就是string类型,number类型就是number类型。

let foo: string = null; // 错误!

如果你为空呢?我们已经带来两个新的类型:nullundefined。正如你所料,null仅仅是null,undefined仅仅是undefined。对它们自己而言作用不大,但是你可以在联合类型中使用它们去定义是否可以包含null/undefined

let foo: string | null = null; // 正确!

由于作为开发者的你可能经常比编辑器的类型系统懂得更多,因此我们还推出了一个后缀操作符!,这个操作符可以从任何一个表达式从排除nullundefined

declare let strs: string[] | undefined;

// 错误! 'strs' 也许是undefined.
let upperCased = strs.map(s => s.toUpperCase());

// 'strs!' 意味着我们确定它不是'undefined', 因此我们可以调用'map'.
let lowerCased = strs!.map(s => s.toLowerCase());

基于控制流的类型分析

TypeScript对处理可空类型的支持成为可能,要归功于在整个程序中跟踪类型的变化。在2.0中,我们已经开始使用控制流分析,以便更好地了解在指定的位置是什么类型。例如,考虑下面这个函数。

/**
 * @param recipients An array of recipients, or a comma-separated list of recipients.
 * @param body Primary content of the message.
 */
function sendMessage(recipients: string | string[], body: string) {
 if (typeof recipients === "string") {
 recipients = recipients.split(",");
 }

// TypeScript 知道这里的'recipients'是'string[]'类型.
 recipients = recipients.filter(isValidAddress);
 for (let r of recipients) {
 // ...
 }
}

注意,在if块内赋值后,TypeScript知道它已经被处理成为了一个string类型的数组。这类事情可以在早期发现问题并节省你在调试上花费的时间。

let bestItem: Item;
for (let item of items) {
 if (item.id === 42) bestItem = item;
}

// 错误! 如果'items'是空的,'bestItem' 可能还没有被初始化。
let itemName = bestItem.name;

我们非常感谢Ivo Gabe de Wolff,他参与这一特性的实施工作,这也开始了他的论文项目并成长为TypeScript本身的一部分。

简易模块声明

有时候你仅仅想要告诉TypeScript有一个模块存在,并且你可能不关心它具体的内容是什么样子的。以前你要像下面这样写:

declare module "foo" {
 var x: any;
 export = x;
}

但是这样太麻烦的,因此我们使声明模块变得更加简易并且摆脱了样板。在TypeScript 2.0 中你可以这么写

declare module "foo";
declare module "bar";

当你准备好最终要写一个包含具体内容的模块时,你可以返回这些声明并定义你需要的结构。

如果你依靠一个有很多模块的软件包呢?为每一个模块书写一遍可能是痛苦的,但是TypeScript 2.0 通过使用通配符*使之变得容易。

declare module "foo/*";

现在您可以导入任何以foo/开头的路径,TypeScript会认为它存在。
你可以利用这一点,如果你的模块加载器也知道如何导入基于一个特定的模式。例如:

declare module "*!text" {
 const content: string;
 export = content;
}

现在每当你导入一个结尾带有!text的路径时,TypeScript就会知道导入的是string类型。

import text = require("./hello.txt!text");
text.toLowerCase();

关于模块这一部分,博客描述的太简单了,很多人可能不能明白,建议看看GitHub上的这部分内容

下一步

你可能想知道的一个特性是在ES3和ES5中支持async/await,最初,这是定于2.0版本。然而,合理的实现async/await,我们需要重写TypeScript的emitter,这会引起一系列的变化。这样做的同时还要保持TypeScript快速更新,就需要大量的工作和对细节的关注。虽然我们对于今天的实现充满了信心,但是信心不是彻底的测试,并且需要更多的时间用于async/await的稳定。你可以在TypeScript 2.1 中期待它的出现,如果你想要跟踪进度,在GitHub上的Pull request当前是公开的

TypeScript 2.0 还充满了许多有用的新功能,随着时间的推移我们将推出更多细节。如果你想听到更多的新特性,你可以看一下我们的wiki。在未来的几周内,一个更加稳定的候选版本将发布,随后最终的正式版将会发布。

我们很乐意听听你的任何反馈,无论是在下面的评论或GitHub上。黑客快乐!