提交 7d492d92 编写于 作者: W wizardforcel

2022-01-09 00:00:45

上级 dc99e79a
......@@ -17,12 +17,12 @@ Currying 和 partial function application 经常被合并。[<sup>【17】</sup>
另一方面,F#架构师 Don Syme 等人说“ *Currying* 是当函数以迭代形式接受参数时使用的名称——即当函数可以部分应用时”(*专家 F# 2.0* ,第 559 页)。程序员代码中这样表示的多参数函数在语言实现中是默认的,并且可以部分应用。相比之下,多参数函数也可以表示为元组的函数,在这种情况下,元组将被语言实现视为单参数,这使得函数成为单参数函数。这意味着函数不能部分应用,因为没有其他参数。表示的选择由程序员决定,Syme 等人将程序员对语言实现中默认使用的表示的选择称为 currying,这与前面的引用相反,后者指的是当程序员做出选择时语言实现所做的事情。但是说 curried functions *可以*部分应用并不是把 currying 等同于部分应用——只是说部分应用的可能性取决于语言实现对 currying 的支持。
1. 由于部分应用依赖于 currying,这两者经常一起出现,但是它们不同,因为使用部分应用,您可以将多个参数“绑定”到一个值,并且要评估结果函数,您所需要的只是剩余的参数。我刚才陈述的三件事定义了部分应用和货币之间的区别。部分应用是将值绑定到参数的过程,这导致函数具有较少的参数。相比之下,currying 是用单参数函数的嵌套集或链来替换单个多参数函数的过程。
2. 部分应用程序可以通过一次绑定多个参数来执行。相比之下,currying 总是一次使用一个参数。
3. 要完全评估部分应用的函数,只需绑定尚未绑定的参数。根据部分应用程序的定义,必须已经绑定了一个或多个参数。相比之下,对于 curried 函数,完全求值需要绑定所有参数,并且可能已经绑定了零个或多个参数。
2. 部分应用可以通过一次绑定多个参数来执行。相比之下,currying 总是一次使用一个参数。
3. 要完全评估部分应用的函数,只需绑定尚未绑定的参数。根据部分应用的定义,必须已经绑定了一个或多个参数。相比之下,对于 curried 函数,完全求值需要绑定所有参数,并且可能已经绑定了零个或多个参数。
### 部分应用
以下示例演示了部分应用程序(FSI 控制台):
以下示例演示了部分应用(FSI 控制台):
```fs
> let Add5 a b c d e = a + b + c + d + e;;
......@@ -90,7 +90,7 @@ Currying 由 F#语言实现处理,因此对程序员来说基本上是不可
这里需要理解的重要一点是,F#语法是这样定义的,即任何用空格指定其参数的函数都会被自动修改,仅仅通过使用这种语法,您就使用了语言实现中内置的 currying。
另一个例子:由于`Add x y`将被评估为 curried 函数(其参数用空格隔开),我们可以直接使用分部应用程序或通过流水线操作,这更明确地创建分部函数应用程序:
另一个例子:由于`Add x y`将被评估为 curried 函数(其参数用空格隔开),我们可以直接使用分部应用或通过流水线操作,这更明确地创建分部函数应用:
```fs
> Add 1 (Add 2 (Add 3 (Add 4 (5))));; // Looks familiar to the decompiled F# code!
......@@ -106,7 +106,7 @@ Currying 由 F#语言实现处理,因此对程序员来说基本上是不可
### 课程
* 只要您单独表示多个参数,而不是元组或其他复杂参数,F#语言实现就会创建一个 curried 函数。
* 当您仅绑定多参数函数的前 *n* 个参数的值时,您正在创建部分函数应用程序
* 当您仅绑定多参数函数的前 *n* 个参数的值时,您正在创建部分函数应用。
## 什么是命令式编程?
......
......@@ -390,7 +390,7 @@
* 创建只做一件事的函数。
* 更小的函数更容易组合(下一节将详细介绍)。
* 较小的函数使您更容易更改应用程序的行为,而不会破坏代码的其他部分。
* 较小的函数使您更容易更改应用的行为,而不会破坏代码的其他部分。
## 功能流水线、部分应用、功能组合
......@@ -423,7 +423,7 @@
在计算机科学中,部分应用(或部分函数应用)是指将一个函数的多个参数固定下来,产生另一个较小的函数的过程[<sup>【34】</sup>](IFP_0010.htm#_ftn34)(“Arity”表示函数接受的参数个数。)
我们可以通过推迟哈希算法来进一步“功能化”前面的代码,只需创建一个部分应用程序:
我们可以通过推迟哈希算法来进一步“功能化”前面的代码,只需创建一个部分应用:
```fs
let pwdHash2 pwd = pwd |> encodeUTF8 |> getHash2
......@@ -452,18 +452,18 @@
```
观察我们是如何创建部分应用程序`pwdHash2`的,在评估时,它用 UTF8 编码来编码我们的密码,但是让我们推迟选择实际的哈希算法。我们通过输入原始密码字符串来分配编码密码,通过提供哈希算法对象来完成函数应用。
观察我们是如何创建部分应用`pwdHash2`的,在评估时,它用 UTF8 编码来编码我们的密码,但是让我们推迟选择实际的哈希算法。我们通过输入原始密码字符串来分配编码密码,通过提供哈希算法对象来完成函数应用。
这个的语法有点乱,因为我们在混合。NET 对象,而不是使用纯 F#函数。然而,我相信这代表了在用 F#编程时您将处理的真实世界,所以我宁愿说明这个语法,而不是一个纯 F#实现。这都是函数式思考的一部分,但是要意识到你仍然必须使用不支持功能流水线和迎合的命令式框架。
#### 课程
* 编写函数时,考虑哪些参数最有可能被部分应用,并将这些参数放在第一位。
* 如果程序员没有按照您想要的顺序提供参数,请编写一个函数来翻转参数,您可以使用它来创建部分应用程序函数。
* 如果程序员没有按照您想要的顺序提供参数,请编写一个函数来翻转参数,您可以使用它来创建部分应用函数。
### 重新审视函数流水线并引入元组
我们现在可以考虑如何添加不同的行为,例如,在密码中添加一些“盐”。这进一步说明了我们的应用程序的行为是如何通过简单、可组合的函数而被轻松改变的。首先,让我们这样来看编码函数:
我们现在可以考虑如何添加不同的行为,例如,在密码中添加一些“盐”。这进一步说明了我们的应用的行为是如何通过简单、可组合的函数而被轻松改变的。首先,让我们这样来看编码函数:
```fs
let myEncPwd2 = ("abc" |> encodeUTF8 |> getHash2)(new SHA1Managed())
......@@ -545,7 +545,7 @@
#### 课程
* 为了利用函数组合,最好有只取一个参数的函数。
* 您在组合中的函数很可能是部分函数应用程序
* 您在组合中的函数很可能是部分函数应用!
### 函数和文字:管道和合成的关键区别
......@@ -587,11 +587,11 @@
```
请注意,我们是如何将流水线操作(从初始值开始)与函数组合(对值进行编码并将结果传递给 append 函数的部分应用程序的函数)相结合的。)知道您使用的是文字还是“函数作为值”非常重要,因为这将指导您如何使用函数流水线和函数组合。
请注意,我们是如何将流水线操作(从初始值开始)与函数组合(对值进行编码并将结果传递给 append 函数的部分应用的函数)相结合的。)知道您使用的是文字还是“函数作为值”非常重要,因为这将指导您如何使用函数流水线和函数组合。
### 部分应用和流水线
理解部分应用程序和流水线之间的交互也很重要,因为这可能会产生意想不到的后果。
理解部分应用和流水线之间的交互也很重要,因为这可能会产生意想不到的后果。
给定(FSI 控制台):
......@@ -620,7 +620,7 @@
```
在这里我们可以清楚地看到,流水线试图提供第一个参数,但是由于`getHash`是一个部分应用程序,其中没有提供任何参数,它会因类型不匹配而失败,因为流水线试图提供第一个参数,类型为`HashAlgorithm`,带有`byte[ ]`
在这里我们可以清楚地看到,流水线试图提供第一个参数,但是由于`getHash`是一个部分应用,其中没有提供任何参数,它会因类型不匹配而失败,因为流水线试图提供第一个参数,类型为`HashAlgorithm`,带有`byte[ ]`
一个正确的用法是这样的:
......@@ -631,7 +631,7 @@
### 价值困惑
从前面的代码中可以清楚地看到,部分应用`getHash(new SHA1Managed())`优先于管道操作符。当我们没有正确创建分部函数应用程序时,我们能够在编码过程中识别出这个问题,因为`getHash`函数有不同类型的参数,编译器或 IDE 告诉我们有问题。然而,如果参数是相同的类型,我们可以很容易地创建仅在运行时发现的计算错误。我们可以用下面的代码(FSI 控制台)更清楚地说明这一点:
从前面的代码中可以清楚地看到,部分应用`getHash(new SHA1Managed())`优先于管道操作符。当我们没有正确创建分部函数应用时,我们能够在编码过程中识别出这个问题,因为`getHash`函数有不同类型的参数,编译器或 IDE 告诉我们有问题。然而,如果参数是相同的类型,我们可以很容易地创建仅在运行时发现的计算错误。我们可以用下面的代码(FSI 控制台)更清楚地说明这一点:
```fs
let Sub x y = x - y;;
......@@ -667,7 +667,7 @@
前面的代码仍然没有实现我们想要实现的目标:
* 我们希望能够指定要在实际哈希函数之外使用的编码器和哈希算法,换句话说,我们希望抽象出应用程序可能想要使用的实际编码器和哈希算法。
* 我们希望能够指定要在实际哈希函数之外使用的编码器和哈希算法,换句话说,我们希望抽象出应用可能想要使用的实际编码器和哈希算法。
* 我们希望能够干净地追加字节流,这样我们就可以使用密码和 salt。
使用我们所学的关于函数组合、部分函数应用和函数流水线的所有知识,我们现在准备好构建一个更加简洁的实现,展示(希望)F#和函数编程的独特特性。
......@@ -689,7 +689,7 @@
```
我称之为`encodeStringAndAppendFunction`的原因是,当给定一个将字符串转换为字节[ ]的编码算法时,它会返回一个部分函数应用程序——只提供了`Array.append`函数的第一个参数。
我称之为`encodeStringAndAppendFunction`的原因是,当给定一个将字符串转换为字节[ ]的编码算法时,它会返回一个部分函数应用——只提供了`Array.append`函数的第一个参数。
这允许我们将编码和追加操作链接在一起。我们可以在单独的`let`语句中做到这一点,以最后的“追加一个空数组”结束
......@@ -745,7 +745,7 @@
```
但是因为我已经明智地将编码器-哈希器元组放在第一位,所以我可以用不同的编码和哈希算法创建部分函数应用程序(FSI 控制台):
但是因为我已经明智地将编码器-哈希器元组放在第一位,所以我可以用不同的编码和哈希算法创建部分函数应用(FSI 控制台):
```fs
// Create a UTF32 encoder.
......@@ -764,7 +764,7 @@
```
我们现在有了一个非常灵活的系统,可以使用不同的编码和哈希方法对加盐密码进行哈希处理,使用部分应用程序来创建一个可重复使用的哈希函数。
我们现在有了一个非常灵活的系统,可以使用不同的编码和哈希方法对加盐密码进行哈希处理,使用部分应用来创建一个可重复使用的哈希函数。
```fs
// Now let’s create a couple hashes using our different partial applications:
......@@ -787,9 +787,9 @@
### 课程
* 包起来。NET 函数,以便您可以使用部分应用程序构造。
* 包起来。NET 函数,以便您可以使用部分应用构造。
* 将不变参数放在函数的第一位,以便函数适合部分应用。
* 部分应用程序非常强大,允许您创建揭示有用模式的函数组合,为您创建健壮应用程序提供进一步抽象的线索。
* 部分应用非常强大,允许您创建揭示有用模式的函数组合,为您创建健壮应用提供进一步抽象的线索。
* 局部应用是函数式编程的“重用”策略之一。这个策略的代码。
* 不是重复,而是让你的功能尽可能小!
......@@ -994,7 +994,7 @@ F#中使用递归来避免可变性。是的,我们可以用 F# as (FSI 控制
### For 和 while:何时使用迭代
`for``while`语句的主要目的是独立于正在处理的数据迭代固定次数,或者永远执行一个过程(或者通常在应用程序的生命周期内)。F#提供了三种不同的循环结构:
`for``while`语句的主要目的是独立于正在处理的数据迭代固定次数,或者永远执行一个过程(或者通常在应用的生命周期内)。F#提供了三种不同的循环结构:
* 为…至[<sup>【39】</sup>](IFP_0010.htm#_ftn39)
* 为…在[<sup>【40】</sup>](IFP_0010.htm#_ftn40)
......
......@@ -63,7 +63,7 @@
```
前面的代码产生相同的输出(每个数字在一个单独的行上)。在函数式编程中经常依赖闭包,因为人们经常创建局部函数应用程序,这些应用程序传入的值(或函数)是当前词法范围的一部分。为了精通函数式编程,人们应该对闭包非常熟悉。
前面的代码产生相同的输出(每个数字在一个单独的行上)。在函数式编程中经常依赖闭包,因为人们经常创建局部函数应用,这些应用传入的值(或函数)是当前词法范围的一部分。为了精通函数式编程,人们应该对闭包非常熟悉。
## 受歧视的工会…
......@@ -528,7 +528,7 @@
```
我们现在可以通过创建两个部分函数来利用部分应用程序:一个在“连接”的环境中处理从数据库获取数据,另一个在“断开”的环境中简单地抛出异常:
我们现在可以通过创建两个部分函数来利用部分应用:一个在“连接”的环境中处理从数据库获取数据,另一个在“断开”的环境中简单地抛出异常:
```fs
let getRecordConnected = getRecord getPersonFromDatabase
......@@ -566,7 +566,7 @@
* 延续传递风格是一种强大的技术,它允许调用者定义函数如何继续处理,而不是将处理嵌入到函数本身。
* 重新思考对象层次结构,其中函数被覆盖,因为需要不同的行为,使用 CPS 代替。
* 查看您的函数,并考虑可以使用 CPS 提取哪些部分,以使您的程序更适合开发人员的需求。
* 将 CPS 与部分函数应用程序结合起来,创建可重用的行为。
* 将 CPS 与部分函数应用结合起来,创建可重用的行为。
### CPS 和递归
......@@ -749,7 +749,7 @@
这里的“魔力”(除了是高阶函数的优秀例子)是“累加器”的意思——在第一种情况下,它是一个递增的计数,在第二种情况下,它是一个和。
最后,我们可以使用部分函数应用程序来创建可重用的函数:
最后,我们可以使用部分函数应用来创建可重用的函数:
```fs
let getTreeSize<'a> = foldTree (fun lacc (x : 'a) racc -> lacc + racc + 1)
......@@ -757,7 +757,7 @@
```
现在我们可以调用我们的部分应用程序(F#控制台):
现在我们可以调用我们的部分应用(F#控制台):
```fs
> getTreeSize<int> tree;;
......@@ -791,7 +791,7 @@
* 当使用“多路径”递归(如树)时,CPS 是确保尾部递归的必要工具。
* 学会“颠倒”你对函数的想法——看看函数里面有什么,看看你是否想把它暴露在外面。
* 编写函数时要考虑部分应用:什么是“重用”参数和“高度变化”参数?“重用”参数应该放在第一位,这样就可以轻松定义部分函数应用程序,从而促进函数重用。
* 编写函数时要考虑部分应用:什么是“重用”参数和“高度变化”参数?“重用”参数应该放在第一位,这样就可以轻松定义部分函数应用,从而促进函数重用。
* 为了获得更多的乐趣(双关语),请看“变形,第二部分”[<sup>【55】</sup>](IFP_0010.htm#_ftn55)
* 熟悉基本的 F#运算符。[<sup>【56】</sup>](IFP_0010.htm#_ftn56)这可以为你在试图弄清楚别人的代码时节省很多时间。
......@@ -1001,7 +1001,7 @@ monad 的一个用途是保留状态而不求助于可变变量。在这一节
### 一种状态单胞菌
状态 monad 不能解决在应用程序的整个生命周期中保持状态的整体问题。为此,来自`System.Collections.Generic`名称空间的可变字典是一种解决方案。相反,一个状态单在一个特定的*工作流中维护状态。*我举一个生成伪随机数的简单例子[<sup>【60】</sup>](IFP_0010.htm#_ftn60)(手动!),使用“带进位乘法”方法。F#中的可变实现如下所示:
状态 monad 不能解决在应用的整个生命周期中保持状态的整体问题。为此,来自`System.Collections.Generic`名称空间的可变字典是一种解决方案。相反,一个状态单在一个特定的*工作流中维护状态。*我举一个生成伪随机数的简单例子[<sup>【60】</sup>](IFP_0010.htm#_ftn60)(手动!),使用“带进位乘法”方法。F#中的可变实现如下所示:
```fs
let mutable m_w = 1
......@@ -1069,7 +1069,7 @@ monad 的一个用途是保留状态而不求助于可变变量。在这一节
```
这个运算符借用了函数式编程语言 Haskell,它将这个运算符定义为“带值传递的 Monad 排序运算符。”这里,`x`是给定初始状态,`s0`返回一个值和一个新状态的函数。运算符是一个部分函数应用程序,因为它提供了 x 和链中的下一个函数,但它没有给出`s0`,初始状态。
这个运算符借用了函数式编程语言 Haskell,它将这个运算符定义为“带值传递的 Monad 排序运算符。”这里,`x`是给定初始状态,`s0`返回一个值和一个新状态的函数。运算符是一个部分函数应用,因为它提供了 x 和链中的下一个函数,但它没有给出`s0`,初始状态。
让我们看看这个表达式的作用:
......@@ -1194,7 +1194,7 @@ monad 的一个用途是保留状态而不求助于可变变量。在这一节
```
但正是部分函数应用程序语法让我们能够轻松地将第一个 CPS 示例翻译成糖计算表达式:
但正是部分函数应用语法让我们能够轻松地将第一个 CPS 示例翻译成糖计算表达式:
```fs
let printRandomValues =
......
# 四、命令式和函数式交互
本节将讨论如何在一个应用程序中一起使用 C#和 F#代码。我们将创建一个简单的应用程序,它的前端用户界面用 C#实现,后端数据管理用 F#实现。无论是创建 Windows 窗体还是与 ASP.NET 一起创建 web 应用程序,混合命令式和函数式编程风格可能是最有效的方法——当然,用于设计窗体或网页的工具,XAML 或 HTML,都对生成 C#或 VB 代码有更多的支持。此外,因为用户界面一直在管理状态,应用程序中本质上可变的部分最好用支持可变的语言来实现。相反,处理数据持久化和转换的应用程序后端通常非常适合 F#,因为不变性对于处理异步流程至关重要。
本节将讨论如何在一个应用中一起使用 C#和 F#代码。我们将创建一个简单的应用,它的前端用户界面用 C#实现,后端数据管理用 F#实现。无论是创建 Windows 窗体还是与 ASP.NET 一起创建 web 应用,混合命令式和函数式编程风格可能是最有效的方法——当然,用于设计窗体或网页的工具,XAML 或 HTML,都对生成 C#或 VB 代码有更多的支持。此外,因为用户界面一直在管理状态,应用中本质上可变的部分最好用支持可变的语言来实现。相反,处理数据持久化和转换的应用后端通常非常适合 F#,因为不变性对于处理异步流程至关重要。
## 创建多语言项目
第一步很简单:在 Visual Studio 2012 中创建新的 Windows 窗体应用程序项目。我已经调用了我的 **fsharp-demo** :
第一步很简单:在 Visual Studio 2012 中创建新的 Windows 窗体应用项目。我已经调用了我的 **fsharp-demo** :
![](img/image003.png)
......@@ -78,11 +78,11 @@
```
当我们运行应用程序时,首先会出现一个带有结果的消息框。恭喜,我们已经成功地从 C#调用了 F#。
当我们运行应用时,首先会出现一个带有结果的消息框。恭喜,我们已经成功地从 C#调用了 F#。
## 从 F#调用 C#
我们可能还想走另一个方向,从我们的 F#代码中调用 C#。我们已经看到了许多这样的例子,但是假设您想在自己的应用程序中调用一些 C#代码。与任何多项目解决方案一样,我们不能有循环引用,所以这意味着您必须了解解决方案的*结构*,这样 C#和 F#项目之间共享的公共代码必须进入自己的项目。
我们可能还想走另一个方向,从我们的 F#代码中调用 C#。我们已经看到了许多这样的例子,但是假设您想在自己的应用中调用一些 C#代码。与任何多项目解决方案一样,我们不能有循环引用,所以这意味着您必须了解解决方案的*结构*,这样 C#和 F#项目之间共享的公共代码必须进入自己的项目。
下一个问题是您是想要在静态还是实例上下文中调用 C#代码。静态上下文类似于调用 F#代码。首先,简单地创建一个静态类和一些静态成员:
......@@ -144,7 +144,7 @@
## 数据库浏览器——一个简单的项目
现在我们已经了解了 C#和 F#交互的基础,让我们创建一个简单的“数据库浏览器”应用程序。这个应用程序将使用 Syncfusion 的 Essential Studio 作为 C#的前端,而 F#作为所有数据库连接和查询的后端。该用户界面将包括:
现在我们已经了解了 C#和 F#交互的基础,让我们创建一个简单的“数据库浏览器”应用。这个应用将使用 Syncfusion 的 Essential Studio 作为 C#的前端,而 F#作为所有数据库连接和查询的后端。该用户界面将包括:
* 用户可以从中选择表格的列表控件。
* 将显示选定表格内容的网格控件。
......@@ -425,7 +425,7 @@
```
这里我们利用了部分函数应用程序——我们已经很容易地重构了读取器,使其在解析每一行时更加通用。这花了大约五分钟的时间,通过我们现有的单元测试,我们能够验证我们的更改没有破坏任何东西。
这里我们利用了部分函数应用——我们已经很容易地重构了读取器,使其在解析每一行时更加通用。这花了大约五分钟的时间,通过我们现有的单元测试,我们能够验证我们的更改没有破坏任何东西。
#### 将我们的 F#结构转换成数据表
......
......@@ -4,16 +4,16 @@
我们经常听到“减少时间”和“减少复杂性”这些词,以至于它们现在基本上没有意义。这是正确的,因为除了烤面包机之外,很少有其他技术能真正节省时间并降低复杂性——大多数技术倾向于将时间和复杂性管理推给其他东西,而且,与任何编程语言一样,“其他东西”是开发人员的技能。
当然,在读了比雅尼·斯特劳斯特鲁普的《C++编程语言》几周后,我正在写我的第一个面向对象的 C++应用程序,但是我做得好吗?当然不是。当我开始做 C#开发时,我热切地期待着像 C++中不存在的反射这样的特性,同时抱怨缺少模板。但同样,使用界面、事件等的细微差别是我必须学习的技能。令人高兴的是,我在 C#诞生之初就开始使用它,因此我的技能已经能够随着语言的发展而发展,编写 LINQ、lambda 表达式以及其他在 C# 4.0 和 5.0 中发现的概念。
当然,在读了比雅尼·斯特劳斯特鲁普的《C++编程语言》几周后,我正在写我的第一个面向对象的 C++应用,但是我做得好吗?当然不是。当我开始做 C#开发时,我热切地期待着像 C++中不存在的反射这样的特性,同时抱怨缺少模板。但同样,使用界面、事件等的细微差别是我必须学习的技能。令人高兴的是,我在 C#诞生之初就开始使用它,因此我的技能已经能够随着语言的发展而发展,编写 LINQ、lambda 表达式以及其他在 C# 4.0 和 5.0 中发现的概念。
C# 3.0 引入了函数式编程,包括 lambda 表达式和查询表达式。看起来 C# 6.0 将继续增加函数式编程风格支持,增加属性和方法表达式。
没有一种函数式编程语言是容易学的。函数式编程语言往往非常“符号丰富”,有时甚至很难理解一行代码。阅读函数类型的定义也很重要,虽然类型推断会有很大的帮助,但也会使它变得混乱。
因此,如果您想减少应用程序开发过程中的时间和复杂性,您必须对该语言有深入的了解。对于像 F#这样的函数式编程语言,这意味着不仅要学习语法,还要学习不同的思维方式。希望这本书在这个问题上提供了一些指导。
因此,如果您想减少应用开发过程中的时间和复杂性,您必须对该语言有深入的了解。对于像 F#这样的函数式编程语言,这意味着不仅要学习语法,还要学习不同的思维方式。希望这本书在这个问题上提供了一些指导。
函数式编程有*和*两个方面有可能减少开发时间,两者都是不变性的直接结果。第一,没有副作用,意味着函数是潜在的“可证明正确的”数学方程。给定相同的输入,函数将返回相同的结果。对其他需要关注的功能没有副作用,每个功能本身都不会受到副作用的影响。在我看来,副作用,以及更普遍的状态管理,是一些最难充分测试的东西,导致了人们常说的一句话“我不知道它为什么这么做。”不变性的第二个结果是编写多任务、异步操作变得容易。可变结构需要同步。对于像 F#这样的语言,同步不是问题,因为结构是不可变的。
在这两种情况下,语言本身促进了直接影响实现的编码风格,导致应用程序的自然“正确性”和轻松异步执行操作的能力。随着计算机被生产出更多的物理和虚拟处理器,随着程序员开始利用图形处理器中的大量并行处理流,拥有一种隐含地导致“正确性”并支持异步计算的语言对于即将到来的数据挖掘任务和多个信息流的实时处理至关重要。
在这两种情况下,语言本身促进了直接影响实现的编码风格,导致应用的自然“正确性”和轻松异步执行操作的能力。随着计算机被生产出更多的物理和虚拟处理器,随着程序员开始利用图形处理器中的大量并行处理流,拥有一种隐含地导致“正确性”并支持异步计算的语言对于即将到来的数据挖掘任务和多个信息流的实时处理至关重要。
在我看来,这是像 F#这样的函数式编程语言的最大优势,也是学习如何“函数式”思考的充分理由
\ No newline at end of file
......@@ -446,7 +446,7 @@ Hive 继续通过 AES 加密、SHA 和 MD5 哈希以及 Hive 2.0.0 中提供的
Java UDFs 是最简单的操作。您编写一个扩展 org . Apache . Hadoop . hive . QL . exec . UDF 的类,然后构建一个 JAR 并将其复制到 Hive 的辅助文件夹(用 HIVE_AUX_JARS_PATH 设置指定)。接下来,使用创建临时函数[别名]将该类注册为[UDF _ 类名]。这样,您可以使用 UDF 别名调用该函数。
流媒体控制台应用程序更复杂一些。我们将使用 Python,一个简单的将增值税加到整数的应用程序,如代码清单 111 所示。
流媒体控制台应用更复杂一些。我们将使用 Python,一个简单的将增值税加到整数的应用,如代码清单 111 所示。
111:一个简单的 Python 脚本
......
......@@ -2,6 +2,6 @@
HTTP 协议使我们能够从 Amazon.com 购买微波炉,在脸书聊天中与老朋友重聚,并在 YouTube 上观看有趣的猫视频。HTTP 是万维网背后的协议。它允许美国数据中心的网络服务器将信息发送到澳大利亚的网吧,在那里一个年轻的学生可以阅读描述中国明朝的网页。
在本书中,我们将从软件开发人员的角度来看 HTTP。对 HTTP 有一个扎实的理解可以帮助你写出更好的 web 应用和 web 服务。当出现问题时,它还可以帮助您调试应用程序和服务。我们将涵盖所有基础知识,包括与 HTTP 相关的资源、消息、连接和安全性。
在本书中,我们将从软件开发人员的角度来看 HTTP。对 HTTP 有一个扎实的理解可以帮助你写出更好的 web 应用和 web 服务。当出现问题时,它还可以帮助您调试应用和服务。我们将涵盖所有基础知识,包括与 HTTP 相关的资源、消息、连接和安全性。
我们将从查看资源开始。
\ No newline at end of file
......@@ -17,7 +17,7 @@
2. `food.com`**的主人**。该主机名告诉浏览器托管资源的计算机的名称。计算机将使用域名系统(DNS)将`food.com`转换为网络地址,然后它将准确知道向哪里发送资源请求。您也可以使用 IP 地址指定 URL 的主机部分。
3. `/recipe/grilled-cauliflower-19710/`**的 URL 路径**。food.com 主机应该识别此路径请求的特定资源,并做出适当的响应。
有时,网址会指向主机文件系统或硬盘上的文件。例如,网址`http://food.com/logo.jpg`可能指向 food.com 服务器上确实存在的图片。然而,资源也可以是动态的。网址`http://food.com/recipes/brocolli`可能不是指 food.com 服务器上的真实文件。相反,某种应用程序正在 food.com 主机上运行,它将接受该请求,并使用数据库中的内容构建资源。该应用程序可能使用 ASP.NET、PHP、Perl、Ruby on Rails 或其他一些网络技术构建,这些技术知道如何通过创建供浏览器显示的 HTML 来响应传入的请求。
有时,网址会指向主机文件系统或硬盘上的文件。例如,网址`http://food.com/logo.jpg`可能指向 food.com 服务器上确实存在的图片。然而,资源也可以是动态的。网址`http://food.com/recipes/brocolli`可能不是指 food.com 服务器上的真实文件。相反,某种应用正在 food.com 主机上运行,它将接受该请求,并使用数据库中的内容构建资源。该应用可能使用 ASP.NET、PHP、Perl、Ruby on Rails 或其他一些网络技术构建,这些技术知道如何通过创建供浏览器显示的 HTML 来响应传入的请求。
事实上,这些天许多网站试图避免在他们的网址中有任何真实的文件名。首先,文件名通常与特定的技术相关联,比如。微软 ASP.NET 技术。许多网址将比托管和服务它们的技术更长久。其次,许多网站希望将关键词放入一个网址中(比如西兰花食谱的网址中有`/recipe/broccoli/`)。在网址中有这些关键词是搜索引擎优化的一种形式,它将在搜索引擎结果中对资源进行更高的排名。如今,描述性关键字,而不是文件名,对网址很重要。
......@@ -43,7 +43,7 @@
```
`?`之后的一切(问号)被称为**查询**。该查询也称为**查询字符串**,包含目标网站要使用或解释的信息。查询字符串的外观没有正式的标准,因为技术上是由应用程序来解释它找到的值,但是您会看到大多数用于传递名称-值对的查询字符串都是以`name1=value1&name2=value2`的形式出现的。
`?`之后的一切(问号)被称为**查询**。该查询也称为**查询字符串**,包含目标网站要使用或解释的信息。查询字符串的外观没有正式的标准,因为技术上是由应用来解释它找到的值,但是您会看到大多数用于传递名称-值对的查询字符串都是以`name1=value1&name2=value2`的形式出现的。
例如:
......@@ -99,13 +99,13 @@
```
^字符和空格字符都经过了百分比编码。大多数网络应用程序框架将提供一个简单的网址编码应用编程接口。在服务器端,您应该通过编码应用编程接口运行动态创建的网址,以防网址中出现不安全的字符。
^字符和空格字符都经过了百分比编码。大多数网络应用框架将提供一个简单的网址编码应用编程接口。在服务器端,您应该通过编码应用编程接口运行动态创建的网址,以防网址中出现不安全的字符。
## 资源和媒体类型
到目前为止,我们专注于网址,并简化了其他一切。但是,当我们在浏览器中输入一个网址时,这意味着什么?通常这意味着我们想要检索或查看一些资源。网络上有大量的资料可以查看,稍后我们还将看到 HTTP 如何使我们能够创建、删除和更新资源。目前,我们将继续关注检索。
对于我们想要检索的资源类型,我们还不是很明确。网络上有成千上万种不同的资源类型——图像、超文本文档、XML 文档、视频、音频、可执行应用程序、微软 Word 文档等等。
对于我们想要检索的资源类型,我们还不是很明确。网络上有成千上万种不同的资源类型——图像、超文本文档、XML 文档、视频、音频、可执行应用、微软 Word 文档等等。
为了让主机正确地为资源服务,为了让客户端正确地显示资源,所涉及的各方必须对资源的类型具体而精确。资源是图像吗?资源是电影吗?我们不希望我们的网络浏览器尝试将 PNG 图像渲染为文本,也不希望他们尝试将超文本解释为图像。
......
# 二、信息
在本章中,我们将查看 HTTP 事务中交换的消息。我们将学习消息类型、HTTP 头和状态代码。理解 HTTP 消息中的内容对于在网络上工作的开发人员来说至关重要。您不仅可以通过正确的消息类型来构建更好的应用程序,还可以在 web 应用程序不工作时发现问题并进行调试。
在本章中,我们将查看 HTTP 事务中交换的消息。我们将学习消息类型、HTTP 头和状态代码。理解 HTTP 消息中的内容对于在网络上工作的开发人员来说至关重要。您不仅可以通过正确的消息类型来构建更好的应用,还可以在 web 应用不工作时发现问题并进行调试。
## 请求和响应
......@@ -12,7 +12,7 @@ HTTP 是一种请求和响应协议。客户端使用服务器能够理解的精
## 原始请求和响应
网络浏览器知道如何通过打开与服务器的网络连接并以文本形式发送 HTTP 消息来发送 HTTP 请求。这个请求没有什么神奇的——它只是一个纯 ASCII 文本的命令,并根据 HTTP 规范进行了格式化。任何可以通过网络发送数据的应用程序都可以发出 HTTP 请求。您甚至可以使用像 Telnet 这样的应用程序从命令行发出手动请求。正常的远程登录会话通过端口 23 连接,但是正如我们在第一章中所了解的,HTTP 的默认网络端口是端口 80。
网络浏览器知道如何通过打开与服务器的网络连接并以文本形式发送 HTTP 消息来发送 HTTP 请求。这个请求没有什么神奇的——它只是一个纯 ASCII 文本的命令,并根据 HTTP 规范进行了格式化。任何可以通过网络发送数据的应用都可以发出 HTTP 请求。您甚至可以使用像 Telnet 这样的应用从命令行发出手动请求。正常的远程登录会话通过端口 23 连接,但是正如我们在第一章中所了解的,HTTP 的默认网络端口是端口 80。
下图是一个远程登录会话的屏幕截图,该会话通过端口 80 连接到 odetocode.com,发出一个 HTTP 请求,并接收一个 HTTP 响应。
......@@ -29,7 +29,7 @@ HTTP 是一种请求和响应协议。客户端使用服务器能够理解的精
请注意,默认情况下,远程登录客户端不会安装在 Windows 7、Windows Server 2008 R2、Windows Vista 或 Windows Server 2008 上。您可以按照[http://TechNet . Microsoft . com/en-us/library/cc 771275(v = ws . 10)中列出的步骤安装客户端。aspx](http://technet.microsoft.com/en-us/library/cc771275(v=ws.10).aspx) 。
该命令告诉操作系统启动远程登录应用程序,并告诉远程登录应用程序通过端口 80 连接到 www.odetocode.com。
该命令告诉操作系统启动远程登录应用,并告诉远程登录应用通过端口 80 连接到 www.odetocode.com。
一旦远程登录连接,我们可以键入一个 HTTP 请求消息。第一行是通过键入以下文本,然后按**进入**创建的:
......@@ -45,7 +45,7 @@ HTTP 是一种请求和响应协议。客户端使用服务器能够理解的精
```
该主机信息是 HTTP 1.1 请求消息中必需的信息。这样做的技术原因是帮助支持多个网站的服务器,即 www.odetocode.com 和 www.odetofood.com 都可以托管在同一个服务器上,消息中的主机信息将帮助 web 服务器将请求定向到适当的 web 应用程序
该主机信息是 HTTP 1.1 请求消息中必需的信息。这样做的技术原因是帮助支持多个网站的服务器,即 www.odetocode.com 和 www.odetofood.com 都可以托管在同一个服务器上,消息中的主机信息将帮助 web 服务器将请求定向到适当的 web 应用。
输入前两行后,我们可以按**进入**两次,将消息发送到服务器。您接下来在远程登录窗口中看到的是来自网络服务器的 HTTP 响应。我们将在后面详细讨论,但是回复说我们想要的资源(www.odetocode.com 的默认主页)已经移动了。它已经搬到了 odetocode.com。现在该由客户端来解析这个响应消息,并向 odetocode.com 而不是 www.odetocode.com 发送请求,如果它想要检索主页的话。任何网络浏览器都会自动转到新位置。
......@@ -78,7 +78,7 @@ HTTP 规范中有一部分谈到了“安全”的 HTTP 方法。**安全方法*
图 3:刷新开机自检请求
由于类似这样的警告,许多网络应用程序总是试图让客户端查看`GET`请求的结果。当用户点击按钮将`POST`信息发送到服务器(比如提交订单)后,服务器将处理该信息,并通过一个 HTTP 重定向(比如我们在远程登录窗口中看到的重定向)做出响应,告诉浏览器到`GET`其他资源。浏览器会发出`GET`请求,服务器会回复一个“谢谢订单”资源,然后用户可以随意多次安全刷新或打印页面。这是一种常见的网页设计模式,称为`**POST**`**/重定向/** `**GET**`模式。
由于类似这样的警告,许多网络应用总是试图让客户端查看`GET`请求的结果。当用户点击按钮将`POST`信息发送到服务器(比如提交订单)后,服务器将处理该信息,并通过一个 HTTP 重定向(比如我们在远程登录窗口中看到的重定向)做出响应,告诉浏览器到`GET`其他资源。浏览器会发出`GET`请求,服务器会回复一个“谢谢订单”资源,然后用户可以随意多次安全刷新或打印页面。这是一种常见的网页设计模式,称为`**POST**`**/重定向/** `**GET**`模式。
既然我们对`POST``GET`有了更多的了解,那么我们就来谈谈一些常见的场景,看看什么时候使用不同的方法。
......@@ -127,7 +127,7 @@ HTTP 规范中有一部分谈到了“安全”的 HTTP 方法。**安全方法*
```
请注意,表单输入包含在 HTTP 消息中。这与我们在[第 1 章](1.html#heading_id_13)中看到的参数在 URL 中的出现方式非常相似。接收这个请求的 web 应用程序解析这些值并创建用户帐户。然后,应用程序可以通过多种方式做出响应,但是有三种常见的响应:
请注意,表单输入包含在 HTTP 消息中。这与我们在[第 1 章](1.html#heading_id_13)中看到的参数在 URL 中的出现方式非常相似。接收这个请求的 web 应用解析这些值并创建用户帐户。然后,应用可以通过多种方式做出响应,但是有三种常见的响应:
1. 用超文本标记语言回应,告诉用户帐户已经创建。这样做将让用户查看`POST`请求的结果,如果他或她刷新页面,这可能会导致问题——它可能会尝试再次注册它们!
2. 像我们之前看到的那样,使用重定向指令进行响应,让浏览器发出一个安全的`GET`页面请求,告知用户帐户已经创建。
......@@ -160,9 +160,9 @@ HTTP 规范中有一部分谈到了“安全”的 HTTP 方法。**安全方法*
## 方法和资源一词
我们已经谈了很多关于资源作为服务器文件系统上的物理资源的问题。很多时候,像 PDF 文件、视频文件、图像文件和脚本文件*这样的资源确实作为物理文件存在于服务器上。然而,许多现代网络应用程序内部指向的网址并不真正指向文件。像 ASP.NET 和 Ruby on Rails 这样的技术会拦截对资源的请求,并以它们认为合适的方式做出响应。他们可能会从数据库中读取一个文件,并在 HTTP 响应中返回内容,使其看起来好像资源真的存在于服务器本身上。*
我们已经谈了很多关于资源作为服务器文件系统上的物理资源的问题。很多时候,像 PDF 文件、视频文件、图像文件和脚本文件*这样的资源确实作为物理文件存在于服务器上。然而,许多现代网络应用内部指向的网址并不真正指向文件。像 ASP.NET 和 Ruby on Rails 这样的技术会拦截对资源的请求,并以它们认为合适的方式做出响应。他们可能会从数据库中读取一个文件,并在 HTTP 响应中返回内容,使其看起来好像资源真的存在于服务器本身上。*
一个很好的例子是我们之前使用的`POST`例子,它导致了对`/account/create`的请求。很可能在“帐户”目录中没有名为“创建”的真实文件。相反,web 服务器上的某个东西接收这个请求,读取并验证用户信息,并在数据库中创建一条记录。`/account/create`资源是虚拟的,不存在。但是,您越是能够将虚拟资源视为真实资源,您的应用程序架构和设计就越能坚持 HTTP 的优势。
一个很好的例子是我们之前使用的`POST`例子,它导致了对`/account/create`的请求。很可能在“帐户”目录中没有名为“创建”的真实文件。相反,web 服务器上的某个东西接收这个请求,读取并验证用户信息,并在数据库中创建一条记录。`/account/create`资源是虚拟的,不存在。但是,您越是能够将虚拟资源视为真实资源,您的应用架构和设计就越能坚持 HTTP 的优势。
## HTTP 请求头
......@@ -203,7 +203,7 @@ HTTP 规范定义了许多头。有些标头是通用标头,可以出现在请
| **表头** | **描述** |
| 参照(r) | 当用户点击一个链接时,客户端可以在这个标题中发送引用页面的网址。 |
| 用户代理 | 发出请求的用户代理(软件)的相关信息。许多应用程序使用这个标题中的信息(如果有的话)来找出是哪个浏览器发出的请求(Internet Explorer 6 对 Internet Explorer 9 对 Chrome 等)。). |
| 用户代理 | 发出请求的用户代理(软件)的相关信息。许多应用使用这个标题中的信息(如果有的话)来找出是哪个浏览器发出的请求(Internet Explorer 6 对 Internet Explorer 9 对 Chrome 等)。). |
| 接受 | 描述用户代理愿意接受的媒体类型。该报头用于内容协商。 |
| 接受-语言 | 描述用户代理喜欢的语言。 |
| 饼干 | 包含 cookie 信息,我们将在后面的章节中讨论。Cookie 信息通常有助于服务器跟踪或识别用户。 |
......@@ -289,14 +289,14 @@ HTTP 响应的结构类似于 HTTP 请求。回应的部分包括:
| four hundred | 错误的请求 | 服务器无法理解该请求。请求可能使用了不正确的语法。 |
| Four hundred and three | 被禁止的 | 服务器拒绝访问资源。 |
| Four hundred and four | 未发现 | 一个流行的代码表示找不到资源。 |
| Five hundred | 内部服务器错误 | 服务器在处理请求时遇到错误。通常是因为 web 应用程序中的编程错误。 |
| Five hundred | 内部服务器错误 | 服务器在处理请求时遇到错误。通常是因为 web 应用中的编程错误。 |
| Five hundred and three | 服务不可用 | 服务器当前不会处理该请求。当服务器因负载过重而限制请求时,可能会出现此状态代码。 |
响应状态代码是 HTTP 消息中非常重要的一部分,因为它们告诉客户端发生了什么(或者在重定向的情况下,下一步该去哪里)。
## HTTP 状态代码与您的应用程序
## HTTP 状态代码与您的应用
请记住,HTTP 状态代码是指示在 HTTP 级别发生了什么的代码。它不一定反映应用程序内部发生的事情。例如,假设用户向服务器提交了一个登录表单,但没有填写姓氏字段。如果您的应用程序需要姓氏,它将无法为用户创建帐户。这并不意味着您必须返回一个指示失败的 HTTP 错误代码。您可能希望发生完全相反的情况——您希望用 200(正常)状态代码成功地向客户端返回一些内容。内容将告诉用户没有提供姓氏。从应用程序的角度来看,该请求是失败的,但从 HTTP 的角度来看,该请求已成功处理。这在 web 应用程序中是正常的。
请记住,HTTP 状态代码是指示在 HTTP 级别发生了什么的代码。它不一定反映应用内部发生的事情。例如,假设用户向服务器提交了一个登录表单,但没有填写姓氏字段。如果您的应用需要姓氏,它将无法为用户创建帐户。这并不意味着您必须返回一个指示失败的 HTTP 错误代码。您可能希望发生完全相反的情况——您希望用 200(正常)状态代码成功地向客户端返回一些内容。内容将告诉用户没有提供姓氏。从应用的角度来看,该请求是失败的,但从 HTTP 的角度来看,该请求已成功处理。这在 web 应用中是正常的。
## 响应标题
......
......@@ -4,9 +4,9 @@
## 网络旋风之旅
为了理解 HTTP 连接,我们必须稍微了解一下在 HTTP 下面的层中发生了什么。像许多应用程序一样,网络通信由层组成。**通信栈**中的每一层负责特定且有限数量的职责。
为了理解 HTTP 连接,我们必须稍微了解一下在 HTTP 下面的层中发生了什么。像许多应用一样,网络通信由层组成。**通信栈**中的每一层负责特定且有限数量的职责。
例如,HTTP 就是我们所说的应用层协议,因为它允许两个应用程序通过网络进行通信。通常,其中一个应用程序是网络浏览器,另一个应用程序是像 IIS 或 Apache 这样的网络服务器。我们看到了 HTTP 消息如何允许浏览器向服务器请求资源。但是,HTTP 规范没有说明消息实际上是如何通过网络到达服务器的——这是低层协议的工作。来自 web 浏览器的消息必须向下传播一系列层,当它到达 web 服务器时,它向上传播一系列层以到达 web 服务过程。
例如,HTTP 就是我们所说的应用层协议,因为它允许两个应用通过网络进行通信。通常,其中一个应用是网络浏览器,另一个应用是像 IIS 或 Apache 这样的网络服务器。我们看到了 HTTP 消息如何允许浏览器向服务器请求资源。但是,HTTP 规范没有说明消息实际上是如何通过网络到达服务器的——这是低层协议的工作。来自 web 浏览器的消息必须向下传播一系列层,当它到达 web 服务器时,它向上传播一系列层以到达 web 服务过程。
![](img/img004.png)
......@@ -14,9 +14,9 @@
HTTP 下面的层是**传输层协议**。几乎所有的 HTTP 流量都通过 **TCP** (传输控制协议的缩写)传输,尽管这不是 HTTP 所要求的。当用户在浏览器中键入网址时,浏览器首先从网址中提取主机名(和端口号,如果有的话),并通过指定服务器地址(从主机名导出)和端口(默认为 80)打开一个 **TCP 套接字**
一旦应用程序有了一个开放的套接字,它就可以开始将数据写入套接字。浏览器唯一需要担心的是将格式正确的 HTTP 请求消息写入套接字。TCP 层接受数据,并确保消息传递到服务器时不会丢失或复制。TCP 会自动重新发送任何可能在传输过程中丢失的信息,这就是为什么 TCP 被称为*可靠协议*的原因。除了错误检测,TCP 还提供流量控制。TCP 中的流量控制算法将确保发送方发送数据的速度不会太快,以至于接收方无法处理数据。在这个网络和设备繁多的世界里,流量控制非常重要。
一旦应用有了一个开放的套接字,它就可以开始将数据写入套接字。浏览器唯一需要担心的是将格式正确的 HTTP 请求消息写入套接字。TCP 层接受数据,并确保消息传递到服务器时不会丢失或复制。TCP 会自动重新发送任何可能在传输过程中丢失的信息,这就是为什么 TCP 被称为*可靠协议*的原因。除了错误检测,TCP 还提供流量控制。TCP 中的流量控制算法将确保发送方发送数据的速度不会太快,以至于接收方无法处理数据。在这个网络和设备繁多的世界里,流量控制非常重要。
简而言之,TCP 提供了对成功传递 HTTP 消息至关重要的服务,但它是以透明的方式提供的,因此大多数应用程序不需要担心 TCP。如上图所示,TCP 只是 HTTP 下面的第一层。传输层的 TCP 之后是作为网络层协议的 IP。
简而言之,TCP 提供了对成功传递 HTTP 消息至关重要的服务,但它是以透明的方式提供的,因此大多数应用不需要担心 TCP。如上图所示,TCP 只是 HTTP 下面的第一层。传输层的 TCP 之后是作为网络层协议的 IP。
**IP****互联网协议**的简称。TCP 负责错误检测、流量控制和整体可靠性,而 IP 负责获取信息,并通过各种交换机、路由器、网关、中继器和其他设备将信息从一个网络移动到下一个网络以及世界各地。IP 尽力在目的地传递数据(但它不能保证传递——这是 TCP 的工作)。IP 要求计算机有一个地址(著名的 IP 地址,例如 208.192.32.40)。IP 还负责将数据分解成数据包(通常称为数据报),有时还会对这些数据包进行分段和重组,以便针对特定网段进行优化。
......@@ -26,7 +26,7 @@ HTTP 下面的层是**传输层协议**。几乎所有的 HTTP 流量都通过 *
## 带套接字和 C#的快速 HTTP 请求
如果您想知道编写一个发出 HTTP 请求的应用程序是什么样子的,那么下面的 C#代码就是一个简单的例子,说明代码可能是什么样子的。这段代码没有任何错误处理,并试图向控制台窗口写入任何服务器响应(因此您需要请求一个文本资源),但它适用于简单的请求。以下代码示例的副本可从[https://bitbucket.org/syncfusiontech/http-succinctly](https://bitbucket.org/syncfusiontech/http-succinctly/)获得。示例名称是 sockets-sample。
如果您想知道编写一个发出 HTTP 请求的应用是什么样子的,那么下面的 C#代码就是一个简单的例子,说明代码可能是什么样子的。这段代码没有任何错误处理,并试图向控制台窗口写入任何服务器响应(因此您需要请求一个文本资源),但它适用于简单的请求。以下代码示例的副本可从[https://bitbucket.org/syncfusiontech/http-succinctly](https://bitbucket.org/syncfusiontech/http-succinctly/)获得。示例名称是 sockets-sample。
```cs
using System;
......@@ -128,7 +128,7 @@ HTTP 下面的层是**传输层协议**。几乎所有的 HTTP 流量都通过 *
在网络的旧时代,大多数资源都是文本的。你可以向网络服务器请求一个文档,离开并阅读五分钟,然后请求另一个文档。世界很简单。
对于今天的网络,大多数网页需要不止一个资源来完全呈现。web 应用程序中的每个页面都有一个或多个图像、一个或多个 JavaScript 文件以及一个或多个 CSS 文件。对主页的初始请求产生 30 或 50 个额外的请求来检索与页面相关的所有其他资源并不罕见。
对于今天的网络,大多数网页需要不止一个资源来完全呈现。web 应用中的每个页面都有一个或多个图像、一个或多个 JavaScript 文件以及一个或多个 CSS 文件。对主页的初始请求产生 30 或 50 个额外的请求来检索与页面相关的所有其他资源并不罕见。
在过去,浏览器与服务器建立连接、发送请求、接收响应并关闭连接也很简单。如果今天的网络浏览器一次打开一个连接,并等待每个资源完全下载后再开始下一次下载,网络会感觉非常慢。互联网充满了延迟。信号必须传输很长的距离,并通过不同的硬件。建立 TCP 连接也有一些开销。正如我们在 Wireshark 截图中看到的,在 HTTP 事务开始之前,需要完成三步握手。
......@@ -156,7 +156,7 @@ HTTP 下面的层是**传输层协议**。几乎所有的 HTTP 流量都通过 *
在一个请求-响应事务完成后,持久连接保持打开状态。这种行为给用户代理留下了一个已经打开的套接字,它可以使用该套接字继续向服务器发出请求,而无需打开新套接字的开销。持久连接还避免了慢速启动策略,这是 TCP 拥塞控制的一部分,使持久连接随着时间的推移表现更好。简而言之,持久连接减少了内存使用,减少了 CPU 使用,减少了网络拥塞,减少了延迟,并且总体上改善了页面的响应时间。但是,就像生活中的一切一样,也有不好的一面。
如前所述,服务器只能支持有限数量的传入连接。确切的数字取决于可用的内存量、服务器软件的配置、应用程序的性能以及许多其他变量。很难给出一个确切的数字,但是一般来说,如果您谈论支持数千个并发连接,您将不得不开始测试,看看服务器是否支持负载。事实上,许多服务器被配置为将并发连接数限制在远远低于服务器崩溃的程度。该配置是一种安全措施,有助于防止拒绝服务攻击。对于某人来说,创建一个程序来打开到服务器的数千个持久连接并阻止服务器响应真正的客户端是相对容易的。持久连接是一种性能优化,但也是一个漏洞。
如前所述,服务器只能支持有限数量的传入连接。确切的数字取决于可用的内存量、服务器软件的配置、应用的性能以及许多其他变量。很难给出一个确切的数字,但是一般来说,如果您谈论支持数千个并发连接,您将不得不开始测试,看看服务器是否支持负载。事实上,许多服务器被配置为将并发连接数限制在远远低于服务器崩溃的程度。该配置是一种安全措施,有助于防止拒绝服务攻击。对于某人来说,创建一个程序来打开到服务器的数千个持久连接并阻止服务器响应真正的客户端是相对容易的。持久连接是一种性能优化,但也是一个漏洞。
按照漏洞的思路来思考,我们也不得不思考保持持久连接的开放时间。在一个无限可扩展性的世界中,只要用户代理程序在运行,连接就可以保持开放。但是,因为服务器支持有限数量的连接,所以大多数服务器被配置为在空闲一段时间(例如,在 Apache 中为 5 秒)后关闭持久连接。用户代理也可以在一段空闲时间后关闭连接。对关闭的连接的唯一可见性是通过像 Wireshark 这样的网络分析器。
......
# 四、网络架构
在第一章中,我们讨论了资源,但主要集中在网址和如何解释网址上。然而,资源是 HTTP 的核心。既然我们已经理解了 HTTP 消息、方法和连接,我们就可以重新审视资源了。在本章中,我们将讨论在设计 web 应用程序和 web 服务时使用资源的真正本质。
在第一章中,我们讨论了资源,但主要集中在网址和如何解释网址上。然而,资源是 HTTP 的核心。既然我们已经理解了 HTTP 消息、方法和连接,我们就可以重新审视资源了。在本章中,我们将讨论在设计 web 应用和 web 服务时使用资源的真正本质。
## 资源还原
......@@ -10,35 +10,35 @@
* “芝加哥披萨”的搜索结果
* 患者 123 的病史
所有这些资源都是我们构建应用程序所围绕的资源类型,列表中的共同主题是每个项目如何重要到足以识别和命名。如果我们可以识别一个资源,我们也可以给这个资源一个网址,让某人找到这个资源。有一个网址是一件很方便的事情。当然,给定一个网址,你就可以找到一个资源,但是你也可以通过在超链接中嵌入网址或者在电子邮件中发送它,把这个网址交给其他人。
所有这些资源都是我们构建应用所围绕的资源类型,列表中的共同主题是每个项目如何重要到足以识别和命名。如果我们可以识别一个资源,我们也可以给这个资源一个网址,让某人找到这个资源。有一个网址是一件很方便的事情。当然,给定一个网址,你就可以找到一个资源,但是你也可以通过在超链接中嵌入网址或者在电子邮件中发送它,把这个网址交给其他人。
但是,有很多事情你不能用网址来做。相反,有很多事情是一个网址做不到的。例如,URL 不能将客户端或服务器限制在特定类型的技术上。大家都说 HTTP。如果您的客户端是 C++并且您的 web 应用程序是在 Ruby 中,这并不重要。
但是,有很多事情你不能用网址来做。相反,有很多事情是一个网址做不到的。例如,URL 不能将客户端或服务器限制在特定类型的技术上。大家都说 HTTP。如果您的客户端是 C++并且您的 web 应用是在 Ruby 中,这并不重要。
此外,URL 不能强制服务器使用任何特定技术来存储资源。资源可以是文件系统上的文档,但是 web 框架也可以响应对资源的请求,并使用存储在文件中、存储在数据库中、从 web 服务中检索的信息来构建资源,或者从一天中的当前时间获取资源。
一个 URL 甚至不能指定特定资源的表示,一个资源可以有多个表示。正如我们之前了解到的,客户端可以使用 HTTP 请求消息中的头来请求特定的表示。客户端可以请求特定的语言或特定的内容类型。如果您曾经使用过允许内容协商的 web 应用程序,那么您已经看到了资源的灵活性。JavaScript 可以以 JSON 格式请求患者 123 的数据,C#可以以 XML 格式请求相同的资源,浏览器可以以 HTML 格式请求数据。它们都使用相同的资源,但是使用三种不同的表示。
一个 URL 甚至不能指定特定资源的表示,一个资源可以有多个表示。正如我们之前了解到的,客户端可以使用 HTTP 请求消息中的头来请求特定的表示。客户端可以请求特定的语言或特定的内容类型。如果您曾经使用过允许内容协商的 web 应用,那么您已经看到了资源的灵活性。JavaScript 可以以 JSON 格式请求患者 123 的数据,C#可以以 XML 格式请求相同的资源,浏览器可以以 HTML 格式请求数据。它们都使用相同的资源,但是使用三种不同的表示。
还有一件事是网址不能做的——它不能说用户想用资源做什么*。网址没有说我是要检索资源还是编辑资源。HTTP 请求消息的工作是使用 HTTP 标准方法之一来描述这个意图。正如我们在[第 2 章](2.html#heading_id_23)中所谈到的,标准 HTTP 方法数量有限,包括`GET`、`POST`、`PUT`和`DELETE`。*
*当你开始考虑资源和网址时,就像我们在本章中所做的那样,你开始把网络看作是你的应用程序的一部分,一个你可以构建的灵活的架构层。要深入了解这一思路,请参阅罗伊·菲尔丁的著名论文《建筑风格和基于网络的软件架构设计》。本文介绍了体系结构的表示状态转移(REST)风格,并对本节和下一节中的思想和概念进行了更详细的描述。文章位于[http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm](http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm)
*当你开始考虑资源和网址时,就像我们在本章中所做的那样,你开始把网络看作是你的应用的一部分,一个你可以构建的灵活的架构层。要深入了解这一思路,请参阅罗伊·菲尔丁的著名论文《建筑风格和基于网络的软件架构设计》。本文介绍了体系结构的表示状态转移(REST)风格,并对本节和下一节中的思想和概念进行了更详细的描述。文章位于[http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm](http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm)
## 可见协议——HTTP
到目前为止,我们一直在关注一个网址*不能做什么*,而我们应该关注一个网址*能做什么*。或者更确切地说,专注于一个网址和 HTTP 能做什么,因为它们在一起工作得很好。在他的论文中,菲尔丁描述了接受 HTTP 的好处。这些优势包括可扩展性、简单性、可靠性和松散耦合。HTTP 提供这些好处的部分原因是,您可以将 URL 视为客户端和服务器应用程序之间的指针或间接单元。同样,URL 本身并不决定特定的资源表示、技术实现或客户端的意图。相反,客户端可以在 HTTP 消息中表达所需的意图和表示。
到目前为止,我们一直在关注一个网址*不能做什么*,而我们应该关注一个网址*能做什么*。或者更确切地说,专注于一个网址和 HTTP 能做什么,因为它们在一起工作得很好。在他的论文中,菲尔丁描述了接受 HTTP 的好处。这些优势包括可扩展性、简单性、可靠性和松散耦合。HTTP 提供这些好处的部分原因是,您可以将 URL 视为客户端和服务器应用之间的指针或间接单元。同样,URL 本身并不决定特定的资源表示、技术实现或客户端的意图。相反,客户端可以在 HTTP 消息中表达所需的意图和表示。
HTTP 消息是简单的纯文本消息。HTTP 消息的美妙之处在于请求和响应都是完全自描述的。请求包括 HTTP 方法(客户端想要做什么)、资源路径以及提供所需表示信息的附加头。响应包括指示事务结果的状态代码,但也包括带有缓存指令的头、资源的内容类型、资源的长度以及可能的其他有价值的元数据。
因为事务所需的所有信息都包含在消息中,并且因为信息可见且易于解析,所以当消息在客户端应用程序和服务器应用程序之间移动时,HTTP 应用程序可以依赖许多提供价值的服务。
因为事务所需的所有信息都包含在消息中,并且因为信息可见且易于解析,所以当消息在客户端应用和服务器应用之间移动时,HTTP 应用可以依赖许多提供价值的服务。
## 增值
当一个 HTTP 消息从一台机器上的一个进程的内存空间移动到另一台机器上的一个进程的内存空间时,它可以通过几个检查和可能修改消息的软件和硬件。一个很好的例子是 web 服务器应用程序本身。像 Apache 或 IIS 这样的网络服务器将是服务器上传入的 HTTP 请求的第一批接收者之一,作为网络服务器,它可以将消息路由到适当的应用程序
当一个 HTTP 消息从一台机器上的一个进程的内存空间移动到另一台机器上的一个进程的内存空间时,它可以通过几个检查和可能修改消息的软件和硬件。一个很好的例子是 web 服务器应用本身。像 Apache 或 IIS 这样的网络服务器将是服务器上传入的 HTTP 请求的第一批接收者之一,作为网络服务器,它可以将消息路由到适当的应用
网络服务器可以在决定向何处发送消息时使用消息中的信息,如网址或主机头。服务器还可以对消息执行其他操作,例如将消息记录到本地文件中。服务器上的应用程序不需要担心日志记录,因为服务器被配置为记录所有消息。
网络服务器可以在决定向何处发送消息时使用消息中的信息,如网址或主机头。服务器还可以对消息执行其他操作,例如将消息记录到本地文件中。服务器上的应用不需要担心日志记录,因为服务器被配置为记录所有消息。
同样,当应用程序创建一个 HTTP 响应消息时,服务器有机会在离开时与消息进行交互。同样,这可能是一个简单的日志记录操作,但也可能是对消息本身的直接修改。例如,服务器可以知道客户端是否支持 gzip 压缩,因为客户端可以通过 HTTP 请求中的`Accept-Encoding`头来通告这一事实。压缩允许服务器获取 100 千字节的资源,并将其转换为 25 千字节的资源,以实现更快的传输。您可以将许多 web 服务器配置为对某些内容类型(通常是文本类型)自动使用压缩,这种情况的发生无需应用程序本身担心压缩。压缩是 web 服务器软件本身提供的附加价值。
同样,当应用创建一个 HTTP 响应消息时,服务器有机会在离开时与消息进行交互。同样,这可能是一个简单的日志记录操作,但也可能是对消息本身的直接修改。例如,服务器可以知道客户端是否支持 gzip 压缩,因为客户端可以通过 HTTP 请求中的`Accept-Encoding`头来通告这一事实。压缩允许服务器获取 100 千字节的资源,并将其转换为 25 千字节的资源,以实现更快的传输。您可以将许多 web 服务器配置为对某些内容类型(通常是文本类型)自动使用压缩,这种情况的发生无需应用本身担心压缩。压缩是 web 服务器软件本身提供的附加价值。
应用程序不必担心记录 HTTP 事务或压缩,这都归功于自我描述的 HTTP 消息,它允许基础设施的其他部分处理和转换消息。当消息在网络中移动时,这种类型的处理也会发生。
应用不必担心记录 HTTP 事务或压缩,这都归功于自我描述的 HTTP 消息,它允许基础设施的其他部分处理和转换消息。当消息在网络中移动时,这种类型的处理也会发生。
## 代理
......@@ -56,7 +56,7 @@ A **反向代理**是比客户端更靠近服务器的代理服务器,对客
图 6:正向和反向代理
这两种类型的代理都可以提供广泛的服务。如果我们回到前面讨论的 gzip 压缩场景,代理服务器有能力压缩响应消息体。公司可能会使用反向代理服务器进行压缩,以减轻应用程序所在的网络服务器的计算负荷。现在,应用程序和 web 服务器都不必担心压缩。相反,压缩是一种通过代理分层的功能。这就是 HTTP 的妙处。
这两种类型的代理都可以提供广泛的服务。如果我们回到前面讨论的 gzip 压缩场景,代理服务器有能力压缩响应消息体。公司可能会使用反向代理服务器进行压缩,以减轻应用所在的网络服务器的计算负荷。现在,应用和 web 服务器都不必担心压缩。相反,压缩是一种通过代理分层的功能。这就是 HTTP 的妙处。
其他一些流行的代理服务包括。
......@@ -68,17 +68,17 @@ A **反向代理**是比客户端更靠近服务器的代理服务器,对客
**缓存代理**可以存储频繁访问的资源的副本,并直接响应请求这些资源的消息。我们将在下一节中详细讨论缓存。
最后,值得指出的是,代理不一定是物理服务器。Fiddler 是上一章提到的一个工具,它是一个 HTTP 调试器,允许您捕获和检查 HTTP 消息。Fiddler 的工作原理是告诉 Windows 将所有传出的 HTTP 流量转发到 IP 地址 127.0.0.1 上的端口 8888。这个 IP 地址是环回地址,这意味着流量直接进入本地机器,Fiddler 现在正在端口 8888 上监听。Fiddler 接收 HTTP 请求消息,记录它,将其转发到目的地,并在将响应转发到本地应用程序之前捕获响应。您可以通过转到**工具****互联网选项**,点击**连接**选项卡,然后点击**局域网设置**按钮,在互联网浏览器(IE)中查看代理设置。在**代理服务器**区域,点击**高级**按钮查看代理服务器详细信息。
最后,值得指出的是,代理不一定是物理服务器。Fiddler 是上一章提到的一个工具,它是一个 HTTP 调试器,允许您捕获和检查 HTTP 消息。Fiddler 的工作原理是告诉 Windows 将所有传出的 HTTP 流量转发到 IP 地址 127.0.0.1 上的端口 8888。这个 IP 地址是环回地址,这意味着流量直接进入本地机器,Fiddler 现在正在端口 8888 上监听。Fiddler 接收 HTTP 请求消息,记录它,将其转发到目的地,并在将响应转发到本地应用之前捕获响应。您可以通过转到**工具****互联网选项**,点击**连接**选项卡,然后点击**局域网设置**按钮,在互联网浏览器(IE)中查看代理设置。在**代理服务器**区域,点击**高级**按钮查看代理服务器详细信息。
![Description: http://odetocode.com/aimages/http/proxy.png](img/img007.png)
图 7:互联网浏览器中的代理设置
代理是 HTTP 如何影响网络应用程序或网站架构的一个完美例子。您可以在不影响应用程序的情况下将许多服务分层到网络中。我们想要更详细研究的一个服务是缓存。
代理是 HTTP 如何影响网络应用或网站架构的一个完美例子。您可以在不影响应用的情况下将许多服务分层到网络中。我们想要更详细研究的一个服务是缓存。
## 缓存
缓存是为了提高性能和可伸缩性而进行的优化。当对同一资源表示有多个请求时,服务器可以通过网络一次又一次地为每个请求发送相同的字节。或者,代理服务器或客户端可以在本地缓存表示,并减少完全检索所需的时间和带宽。缓存可以减少延迟,帮助防止瓶颈,并允许网络应用程序在每个用户同时出现购买最新产品或查看最新新闻稿时存活下来。缓存也是一个很好的例子,说明了 HTTP 消息头中的元数据如何促进额外的层和服务。
缓存是为了提高性能和可伸缩性而进行的优化。当对同一资源表示有多个请求时,服务器可以通过网络一次又一次地为每个请求发送相同的字节。或者,代理服务器或客户端可以在本地缓存表示,并减少完全检索所需的时间和带宽。缓存可以减少延迟,帮助防止瓶颈,并允许网络应用在每个用户同时出现购买最新产品或查看最新新闻稿时存活下来。缓存也是一个很好的例子,说明了 HTTP 消息头中的元数据如何促进额外的层和服务。
首先要知道的是有两种类型的缓存。
......@@ -88,7 +88,7 @@ A **反向代理**是比客户端更靠近服务器的代理服务器,对客
不幸的是,关于缓存什么、何时缓存以及何时使缓存项无效(即将其踢出缓存)的规则很复杂,并且被一些遗留行为和不兼容的实现所困扰。尽管如此,我还是要努力指出一些关于缓存应该知道的事情。
在 HTTP 1.1 中,HTTP `GET`请求的状态代码为 200(正常)的响应消息在默认情况下是可缓存的(这意味着代理和客户端缓存响应是合法的)。应用程序可以通过在 HTTP 响应中使用正确的标头来影响此默认值。在 HTTP 1.1 中,这个头是`**Cache-Control**`头,虽然你也可以在很多消息中看到`**Expires**`头。`Expires`头仍然存在,尽管在 HTTP 1.1 中被否决了,但它得到了广泛的支持。`**Pragma**`是用于控制缓存行为的头的另一个例子,但它也只是为了向后兼容。在本书中,我将重点介绍`Cache-Control`
在 HTTP 1.1 中,HTTP `GET`请求的状态代码为 200(正常)的响应消息在默认情况下是可缓存的(这意味着代理和客户端缓存响应是合法的)。应用可以通过在 HTTP 响应中使用正确的标头来影响此默认值。在 HTTP 1.1 中,这个头是`**Cache-Control**`头,虽然你也可以在很多消息中看到`**Expires**`头。`Expires`头仍然存在,尽管在 HTTP 1.1 中被否决了,但它得到了广泛的支持。`**Pragma**`是用于控制缓存行为的头的另一个例子,但它也只是为了向后兼容。在本书中,我将重点介绍`Cache-Control`
HTTP 响应的值可以是`**public**``**private**``**no-cache**``public`值意味着公共代理服务器可以缓存响应。`private`值表示只有浏览器可以缓存响应。`no-cache`的值意味着没有人应该缓存响应。还有一个`**no-store**`值,意味着消息可能包含敏感信息,不应该被持久化,而应该尽快从内存中删除。
......
......@@ -8,13 +8,13 @@ HTTP 是一种无状态协议,这意味着每个请求-响应事务都独立
HTTP 的无状态特性是网络成功的驱动因素之一。我们在上一章中看到的分层服务,如缓存,都成为可能(或至少更容易),因为每条消息都包含处理消息所需的所有信息。代理服务器和 web 服务器可以检查、转换和缓存消息。没有缓存,网络就无法扩展以满足互联网的需求。
然而,我们在 HTTP 之上构建的大多数 web 应用程序和服务都是高度有状态的。
然而,我们在 HTTP 之上构建的大多数 web 应用和服务都是高度有状态的。
银行应用程序希望用户在允许用户查看其帐户相关资源之前登录。当每个无状态请求到达私有资源时,应用程序希望确保用户已经过身份验证。另一个例子是当用户想在一个三页的向导中打开一个帐户并填写表单时。在允许用户提交第二页之前,应用程序需要确保向导的第一页已经完成。
银行应用希望用户在允许用户查看其帐户相关资源之前登录。当每个无状态请求到达私有资源时,应用希望确保用户已经过身份验证。另一个例子是当用户想在一个三页的向导中打开一个帐户并填写表单时。在允许用户提交第二页之前,应用需要确保向导的第一页已经完成。
幸运的是,在 web 应用程序中有许多存储状态的选项。一种方法是在传输给客户端的资源中嵌入状态,这样应用程序所需的所有状态都会在下一个请求中返回。这种方法通常需要一些隐藏的输入字段,并且最适合短期状态(比如在三页向导中移动所需的状态)。在资源中嵌入状态将所有状态都保留在 HTTP 消息中,因此这是一种高度可扩展的方法,但它会使应用程序编程复杂化。
幸运的是,在 web 应用中有许多存储状态的选项。一种方法是在传输给客户端的资源中嵌入状态,这样应用所需的所有状态都会在下一个请求中返回。这种方法通常需要一些隐藏的输入字段,并且最适合短期状态(比如在三页向导中移动所需的状态)。在资源中嵌入状态将所有状态都保留在 HTTP 消息中,因此这是一种高度可扩展的方法,但它会使应用编程复杂化。
另一种选择是将状态存储在服务器上(或服务器后面)。对于必须存在很长时间的状态,此选项是必需的。假设用户提交一个表单来更改他或她的电子邮件地址。电子邮件地址必须始终与用户相关联,因此应用程序可以获取新地址,验证地址,并将地址存储在数据库、文件中,或者调用 web 服务让其他人负责保存地址。
另一种选择是将状态存储在服务器上(或服务器后面)。对于必须存在很长时间的状态,此选项是必需的。假设用户提交一个表单来更改他或她的电子邮件地址。电子邮件地址必须始终与用户相关联,因此应用可以获取新地址,验证地址,并将地址存储在数据库、文件中,或者调用 web 服务让其他人负责保存地址。
对于服务器端存储,许多 web 开发框架(如 ASP.NET)也提供了对“用户会话”的访问。会话可能存在于内存或数据库中,但开发人员可以在会话中存储信息,并在每个后续请求中检索信息。存储在会话中的数据仅限于单个用户(实际上是用户的浏览会话),不能在多个用户之间共享。
......@@ -67,7 +67,7 @@ HTTP 的无状态特性是网络成功的驱动因素之一。我们在上一章
```
当标识到达时,服务器软件可以从内存数据结构、数据库或分布式缓存中快速查找任何相关的用户数据。您可以配置大多数 web 应用程序框架来操作 cookies 并自动查找会话状态。例如,在 ASP.NET,`Session`对象公开了一个读取和写入用户会话状态的简单应用编程接口。作为开发人员,我们永远不必担心发送`Set-Cookie`头,或者读取传入的 cookies 来找到相关的会话状态。在幕后,ASP.NET 将管理会话 cookie。
当标识到达时,服务器软件可以从内存数据结构、数据库或分布式缓存中快速查找任何相关的用户数据。您可以配置大多数 web 应用框架来操作 cookies 并自动查找会话状态。例如,在 ASP.NET,`Session`对象公开了一个读取和写入用户会话状态的简单应用编程接口。作为开发人员,我们永远不必担心发送`Set-Cookie`头,或者读取传入的 cookies 来找到相关的会话状态。在幕后,ASP.NET 将管理会话 cookie。
```cs
Session["firstName"] = "Scott"; // writing session state
......@@ -78,7 +78,7 @@ HTTP 的无状态特性是网络成功的驱动因素之一。我们在上一章
再次值得指出的是,存储在会话对象中的`firstName``lastName`数据是**而不是进入 cookie** 。cookie 只包含一个会话标识符。与会话标识符相关联的值在服务器上是安全的。默认情况下,会话数据进入内存中的数据结构,并保持活动状态 20 分钟。当会话 cookie 在请求中到达时,ASP.NET 将使用存储在 cookie 中的标识找到用户数据后,将正确的会话数据与`Session`对象相关联。如果没有带有会话标识的传入 cookie,ASP.NET 将创建一个带有`Set-Cookie`头的 cookie。
关于会话标识符的一个安全问题是,它们如何打开某人劫持另一个用户的会话的可能性。例如,如果我使用像 Fiddler 这样的工具来跟踪 HTTP 流量,我可能会看到一个`Set-Cookie`头来自一个内部有`SessionID=12`的服务器。我可能会猜测其他用户已经有了 11 的`SessionID`,并创建一个带有该 ID 的 HTTP 请求,只是为了看看我是否可以窃取或查看其他用户的 HTML。为了解决这个问题,大多数网络应用程序将使用大随机数作为标识符(ASP.NET 使用 120 位的随机性)。ASP.NET 会话标识符如下所示,这使得猜测其他人的会话标识变得更加困难。
关于会话标识符的一个安全问题是,它们如何打开某人劫持另一个用户的会话的可能性。例如,如果我使用像 Fiddler 这样的工具来跟踪 HTTP 流量,我可能会看到一个`Set-Cookie`头来自一个内部有`SessionID=12`的服务器。我可能会猜测其他用户已经有了 11 的`SessionID`,并创建一个带有该 ID 的 HTTP 请求,只是为了看看我是否可以窃取或查看其他用户的 HTML。为了解决这个问题,大多数网络应用将使用大随机数作为标识符(ASP.NET 使用 120 位的随机性)。ASP.NET 会话标识符如下所示,这使得猜测其他人的会话标识变得更加困难。
```cs
Set-Cookie: ASP.NET_SessionId=en5yl2yopwkdamv2ur5c3z45;
......@@ -106,7 +106,7 @@ Set-Cookie:名称=值;到期时间= 2012 年 7 月 9 日星期一格林尼治
到目前为止,我们已经说过,一旦网站设置了 cookie,cookie 就会随着后续的每一个请求传播到网站(假设 cookie 没有过期)。然而,并不是所有的 cookies 都会传播到每个网站。用户代理应该发送到站点的唯一 cookie 是由同一站点提供给用户代理的 cookie。将来自 Amazon.com 的 cookies 放在对 google.com 的 HTTP 请求中是没有意义的。这种行为只会带来额外的安全和隐私问题。如果您在对 www.server.com 请求的响应中设置了一个 cookie,则生成的 cookie 将只在对 www.server.com 的请求中传播。
web 应用程序还可以更改 cookie 的范围,将 cookie 限制在特定的主机或域,甚至特定的资源路径。网络应用程序使用`**domain**``**path**`属性控制范围。
web 应用还可以更改 cookie 的范围,将 cookie 限制在特定的主机或域,甚至特定的资源路径。网络应用使用`**domain**``**path**`属性控制范围。
```cs
HTTP/1.1 200 OK
......@@ -117,7 +117,7 @@ web 应用程序还可以更改 cookie 的范围,将 cookie 限制在特定的
`domain`属性允许 cookie 跨子域。换句话说,如果您设置了来自 www.server.com 的 cookie,用户代理将只向 www.server.com 发送 cookie。上一个例子中的域还允许 cookie 传播到 server.com 域中的任何 URL,包括 images.server.com、help.server.com 和普通 server.com。您不能使用 domain 属性跨域,因此在对. server.com 的响应中将域设置为. microsoft.com 是不合法的,用户代理应该拒绝该 cookie。
`path`属性可以将 cookie 限制在特定的资源路径上。在前面的例子中,只有当请求网址指向`/stuff``/stuff`下方的位置(如`/stuff/images`)时,cookie 才会传播到 server.com 站点。当多个团队在不同的路径上构建 web 应用程序时,路径设置可以帮助组织 cookies。
`path`属性可以将 cookie 限制在特定的资源路径上。在前面的例子中,只有当请求网址指向`/stuff``/stuff`下方的位置(如`/stuff/images`)时,cookie 才会传播到 server.com 站点。当多个团队在不同的路径上构建 web 应用时,路径设置可以帮助组织 cookies。
## 饼干的缺点
......@@ -208,9 +208,9 @@ Windows 身份验证的优点是即使不使用安全的 HTTP 也是安全的,
## 基于表单的身份验证
表单身份验证是互联网上最流行的用户身份验证方法。基于表单的身份验证不是标准的身份验证协议,不使用`WWW-Authenticate``Authorization`头。然而,许多 web 应用程序框架为基于表单的身份验证提供了一些现成的支持。
表单身份验证是互联网上最流行的用户身份验证方法。基于表单的身份验证不是标准的身份验证协议,不使用`WWW-Authenticate``Authorization`头。然而,许多 web 应用框架为基于表单的身份验证提供了一些现成的支持。
使用基于表单的身份验证,应用程序将通过将用户重定向到登录页面来响应匿名用户对安全资源的请求。重定向是一个 HTTP 302 临时重定向。通常,用户请求的网址可能包含在重定向位置的查询字符串中,这样一旦用户完成登录,应用程序就可以将用户重定向到他或她试图访问的安全资源。
使用基于表单的身份验证,应用将通过将用户重定向到登录页面来响应匿名用户对安全资源的请求。重定向是一个 HTTP 302 临时重定向。通常,用户请求的网址可能包含在重定向位置的查询字符串中,这样一旦用户完成登录,应用就可以将用户重定向到他或她试图访问的安全资源。
```cs
HTTP/1.1 302 Found
......@@ -218,7 +218,7 @@ Windows 身份验证的优点是即使不使用安全的 HTTP 也是安全的,
```
基于表单的身份验证的登录页面是一个 HTML 表单,其中包含供用户输入凭据的输入。当用户单击提交时,表单值将`POST`发送到应用程序需要获取凭证并根据数据库记录或操作系统验证它们的目的地。
基于表单的身份验证的登录页面是一个 HTML 表单,其中包含供用户输入凭据的输入。当用户单击提交时,表单值将`POST`发送到应用需要获取凭证并根据数据库记录或操作系统验证它们的目的地。
```cs
<form method="post">
......@@ -230,7 +230,7 @@ Windows 身份验证的优点是即使不使用安全的 HTTP 也是安全的,
```
请注意,基于表单的身份验证将以纯文本形式传输用户凭据,因此,与基本身份验证一样,基于表单的身份验证是不安全的,除非您使用安全的 HTTP。响应带有凭证的`POST`消息(假设凭证是好的),应用程序通常会将用户重定向回安全资源,并且还会设置一个 cookie,指示用户现在已通过身份验证。
请注意,基于表单的身份验证将以纯文本形式传输用户凭据,因此,与基本身份验证一样,基于表单的身份验证是不安全的,除非您使用安全的 HTTP。响应带有凭证的`POST`消息(假设凭证是好的),应用通常会将用户重定向回安全资源,并且还会设置一个 cookie,指示用户现在已通过身份验证。
```cs
HTTP/1.1 302 Found
......@@ -239,13 +239,13 @@ Windows 身份验证的优点是即使不使用安全的 HTTP 也是安全的,
```
对于 ASP.NET,身份验证票据(即`.ASPXAUTH` cookie 值)被加密和散列以防止篡改。但是,如果没有安全的 HTTP,cookie 很容易被拦截,因此会话劫持仍然是一个潜在的问题。然而,表单身份验证仍然很受欢迎,因为它允许应用程序完全控制登录体验和凭据验证。
对于 ASP.NET,身份验证票据(即`.ASPXAUTH` cookie 值)被加密和散列以防止篡改。但是,如果没有安全的 HTTP,cookie 很容易被拦截,因此会话劫持仍然是一个潜在的问题。然而,表单身份验证仍然很受欢迎,因为它允许应用完全控制登录体验和凭据验证。
## 开标
虽然基于表单的身份验证赋予应用程序对用户身份验证的完全控制,但许多应用程序不需要这种级别的控制。具体来说,应用程序不希望管理和验证用户名和密码(用户也不希望每个网站都有不同的用户名和密码)。OpenID 是分散认证的开放标准。使用 OpenID,用户向 OpenID 身份提供者注册,身份提供者是唯一需要存储和验证用户凭据的站点。周围有很多 OpenID 提供商,包括谷歌、雅虎和 Verisign。
虽然基于表单的身份验证赋予应用对用户身份验证的完全控制,但许多应用不需要这种级别的控制。具体来说,应用不希望管理和验证用户名和密码(用户也不希望每个网站都有不同的用户名和密码)。OpenID 是分散认证的开放标准。使用 OpenID,用户向 OpenID 身份提供者注册,身份提供者是唯一需要存储和验证用户凭据的站点。周围有很多 OpenID 提供商,包括谷歌、雅虎和 Verisign。
当应用程序需要对用户进行身份验证时,它会与用户和用户的身份提供者一起工作。用户最终必须向身份提供者验证他或她的用户名和密码,但是由于加密令牌和秘密的存在,应用程序将知道身份验证是否成功。谷歌在其“谷歌账户用户联合登录”网页([https://developers.google.com/accounts/docs/OpenID](https://developers.google.com/accounts/docs/OpenID))上概述了这一过程。
当应用需要对用户进行身份验证时,它会与用户和用户的身份提供者一起工作。用户最终必须向身份提供者验证他或她的用户名和密码,但是由于加密令牌和秘密的存在,应用将知道身份验证是否成功。谷歌在其“谷歌账户用户联合登录”网页([https://developers.google.com/accounts/docs/OpenID](https://developers.google.com/accounts/docs/OpenID))上概述了这一过程。
虽然与表单身份验证相比,OpenID 提供了许多潜在的好处,但由于实现、调试和维护 OpenID 登录舞蹈的复杂性,它一直面临着缺乏采用的问题。我们不得不希望工具包和框架继续发展,使 OpenID 认证方法变得更加容易。
......@@ -265,7 +265,7 @@ HTTPS 要求服务器拥有加密证书。证书在 HTTPS 通信建立期间被
* **HTTPS 的所有流量都在请求和响应**中加密,包括 HTTP 头和消息体,以及 URL 中主机名之后的所有内容。这意味着路径和查询字符串数据以及所有 cookies 都被加密。HTTPS 防止会话劫持,因为没有窃听者可以检查消息并窃取 cookie。
* **由于服务器证书,服务器被认证给客户端。**如果你正在通过 HTTPS 与 mybigbank.com 通话,你可以确定你的信息确实是发往 mybigbank.com,而不是某个在网络上安装代理服务器来拦截来自 mybigbank.com 的请求和欺骗响应流量的人
* **HTTPS 不认证客户端。**如果应用程序需要知道用户的身份,它们仍然需要实现表单身份验证或前面提到的其他身份验证协议之一。HTTPS 确实使基于表单的身份验证和基本身份验证更加安全,因为所有数据都是加密的。有可能将客户端证书用于 HTTPS,客户端证书将以最安全的方式对客户端进行身份验证。然而,客户端证书通常不在开放的互联网上使用,因为没有多少用户会购买和安装个人证书。公司可能要求员工的客户端证书才能访问公司服务器,但在这种情况下,公司可以充当证书颁发机构,并向员工颁发他们创建和管理的证书。
* **HTTPS 不认证客户端。**如果应用需要知道用户的身份,它们仍然需要实现表单身份验证或前面提到的其他身份验证协议之一。HTTPS 确实使基于表单的身份验证和基本身份验证更加安全,因为所有数据都是加密的。有可能将客户端证书用于 HTTPS,客户端证书将以最安全的方式对客户端进行身份验证。然而,客户端证书通常不在开放的互联网上使用,因为没有多少用户会购买和安装个人证书。公司可能要求员工的客户端证书才能访问公司服务器,但在这种情况下,公司可以充当证书颁发机构,并向员工颁发他们创建和管理的证书。
HTTPS 确实有一些缺点,其中大部分都与表现有关。HTTPS 的计算成本很高,大型网站通常使用专门的硬件(SSL 加速器)来减轻网络服务器的加密计算负担。HTTPS 流量也不可能缓存在公共缓存中,但是用户代理可能会将 HTTPS 响应保存在自己的私有缓存中。最后,HTTPS 连接的建立成本很高,需要在客户端和服务器之间进行额外的握手来交换密钥,并确保每个人都使用正确的安全协议进行通信。持久连接有助于分摊这一成本。
......@@ -273,4 +273,4 @@ HTTPS 确实有一些缺点,其中大部分都与表现有关。HTTPS 的计
## 我们在哪里?
在本章中,我们已经讨论了 cookies、身份验证和安全 HTTP。如果您已经阅读了所有五章,我希望您已经找到了一些有价值的信息,这些信息将帮助您编写、维护和调试网络应用程序。
\ No newline at end of file
在本章中,我们已经讨论了 cookies、身份验证和安全 HTTP。如果您已经阅读了所有五章,我希望您已经找到了一些有价值的信息,这些信息将帮助您编写、维护和调试网络应用。
\ No newline at end of file
# 零、简介
移动应用是科技行业增长最快的领域之一,iPhone 和 iPad 一直走在移动革命的前沿。为这些平台开发应用程序为大量移动用户打开了大门。不幸的是,底层技术的多样性对于 iOS 新手来说可能是压倒性的,从 [iOS 开发者库](http://developer.apple.com/library/ios/navigation/index.html)获得的 1,500 多个官方帮助文档并没有准确地提供对该平台的平易近人的介绍。 *iOS 简洁地*的目标是提供 iOS 环境的简明概述。
移动应用是科技行业增长最快的领域之一,iPhone 和 iPad 一直走在移动革命的前沿。为这些平台开发应用为大量移动用户打开了大门。不幸的是,底层技术的多样性对于 iOS 新手来说可能是压倒性的,从 [iOS 开发者库](http://developer.apple.com/library/ios/navigation/index.html)获得的 1,500 多个官方帮助文档并没有准确地提供对该平台的平易近人的介绍。 *iOS 简洁地*的目标是提供 iOS 环境的简明概述。
## iOS 和 iOS 软件开发工具包
iOS 是 iPhone 和 iPad 应用背后的操作系统。它负责低级系统任务,如管理内存、打开和关闭应用程序以及向屏幕呈现像素。在这个核心操作系统之上是一组**框架**,它们是为常见编程问题提供可重用解决方案的 C 和 Objective-C 库。例如, [UIKit 框架](http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKit_Framework/_index.html)为按钮、文本字段和其他几个用户界面组件定义了类。您可以利用现有的 [UIButton](http://developer.apple.com/library/ios/#documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html) 类,而不是从头开始实现自己的按钮。
iOS 是 iPhone 和 iPad 应用背后的操作系统。它负责低级系统任务,如管理内存、打开和关闭应用以及向屏幕呈现像素。在这个核心操作系统之上是一组**框架**,它们是为常见编程问题提供可重用解决方案的 C 和 Objective-C 库。例如, [UIKit 框架](http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKit_Framework/_index.html)为按钮、文本字段和其他几个用户界面组件定义了类。您可以利用现有的 [UIButton](http://developer.apple.com/library/ios/#documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html) 类,而不是从头开始实现自己的按钮。
核心操作系统和这些更高级别的框架一起组成了 **iOS 软件开发工具包** (SDK)。iOS 软件开发工具包的目标是让你专注于开发*你的应用程序所做的事情,而不是被*如何做*所困扰。基于它们提供的抽象级别,软件开发工具包被分为几层。下图显示了这些层以及它们包含的一些流行框架:*
核心操作系统和这些更高级别的框架一起组成了 **iOS 软件开发工具包** (SDK)。iOS 软件开发工具包的目标是让你专注于开发*你的应用所做的事情,而不是被*如何做*所困扰。基于它们提供的抽象级别,软件开发工具包被分为几层。下图显示了这些层以及它们包含的一些流行框架:*
![](img/image001.png)
......@@ -16,8 +16,8 @@ iOS 是 iPhone 和 iPad 应用背后的操作系统。它负责低级系统任
## 关于 *iOS 简洁*
*iOS 简洁地说*是 iPhone 和 iPad 应用开发两部分系列的后半部分。第一本书, *Objective-C 简洁地*,涵盖了 Objective-C 语言和几乎所有应用程序使用的核心数据结构。考虑到这一点, *iOS 简洁地*假设您已经对 Objective-C 感到满意,并且至少对 Xcode 集成开发环境(IDE)有了基本的熟悉。
*iOS 简洁地说*是 iPhone 和 iPad 应用开发两部分系列的后半部分。第一本书, *Objective-C 简洁地*,涵盖了 Objective-C 语言和几乎所有应用使用的核心数据结构。考虑到这一点, *iOS 简洁地*假设您已经对 Objective-C 感到满意,并且至少对 Xcode 集成开发环境(IDE)有了基本的熟悉。
这本书从探索 iOS 开发背后的基本设计模式开始。我们将学习如何使用非常简单的单场景应用程序创建用户界面。然后,我们将把这些知识扩展到更复杂的多场景应用程序中。至此,您应该已经对 iOS 工作流程有了扎实的掌握。剩下的章节关注常见的开发任务,如访问文件、为不同的受众本地化素材以及播放声音。
这本书从探索 iOS 开发背后的基本设计模式开始。我们将学习如何使用非常简单的单场景应用创建用户界面。然后,我们将把这些知识扩展到更复杂的多场景应用中。至此,您应该已经对 iOS 工作流程有了扎实的掌握。剩下的章节关注常见的开发任务,如访问文件、为不同的受众本地化素材以及播放声音。
本书样本代码可从[https://bitbucket.org/syncfusion/ios-succinctly](https://bitbucket.org/syncfusion/ios-succinctly)下载。
\ No newline at end of file
此差异已折叠。
# 二、多场景应用
前一章介绍了 iOS 应用程序开发的基本工作流程,但我们在单视图应用程序的范围内工作。然而,大多数现实世界的应用程序需要多个场景来分层呈现数据。虽然管理多场景应用程序有多种类型的组织模式,但本章将介绍一种最常见的模式:主-细节应用程序
前一章介绍了 iOS 应用开发的基本工作流程,但我们在单视图应用的范围内工作。然而,大多数现实世界的应用需要多个场景来分层呈现数据。虽然管理多场景应用有多种类型的组织模式,但本章将介绍一种最常见的模式:主-细节应用
最小的主-细节应用程序由一个“主”场景和一个“细节”场景组成,其中“主”场景提供了可供选择的数据项列表,而“细节”场景则在用户从主场景中选择项目时显示项目的细节。在你的 iPhone 上打开 Mail 应用程序,你会发现一个主细节应用程序的好例子。收件箱列出您的邮件,使其成为主场景,当您选择其中一个时,详细场景用于显示邮件内容、发件人、任何附件等。
最小的主-细节应用由一个“主”场景和一个“细节”场景组成,其中“主”场景提供了可供选择的数据项列表,而“细节”场景则在用户从主场景中选择项目时显示项目的细节。在你的 iPhone 上打开 Mail 应用,你会发现一个主细节应用的好例子。收件箱列出您的邮件,使其成为主场景,当您选择其中一个时,详细场景用于显示邮件内容、发件人、任何附件等。
在大多数情况下,多场景应用程序使用上一章中讨论的相同工作流。我们仍将通过界面构建器添加用户界面组件来创建布局,并使用动作、出口和委托将它们连接到我们的代码。然而,拥有多个场景意味着我们将拥有多个视图控制器,因此我们需要使用新的`UINavigationController`类来组织它们的交互。我们还将学习如何使用 segues 配置场景转换。
在大多数情况下,多场景应用使用上一章中讨论的相同工作流。我们仍将通过界面构建器添加用户界面组件来创建布局,并使用动作、出口和委托将它们连接到我们的代码。然而,拥有多个场景意味着我们将拥有多个视图控制器,因此我们需要使用新的`UINavigationController`类来组织它们的交互。我们还将学习如何使用 segues 配置场景转换。
## 创建主-细节项目
本章的示例项目将是一个简单的联系人列表,它允许用户管理他们的朋友列表以及他们各自的联系信息。要创建示例项目,请选择**文件** *>* **新建** *>* **项目**,并选择**主-详细应用程序**。这将使我们有机会探索新的导航组件和组织结构,以及如何处理从一个场景到另一个场景的过渡。
本章的示例项目将是一个简单的联系人列表,它允许用户管理他们的朋友列表以及他们各自的联系信息。要创建示例项目,请选择**文件** *>* **新建** *>* **项目**,并选择**主-详细应用**。这将使我们有机会探索新的导航组件和组织结构,以及如何处理从一个场景到另一个场景的过渡。
![](img/image030.png)
图 31:创建主-细节应用程序模板
图 31:创建主-细节应用模板
**产品名称**字段中使用*友好列表*,在**组织名称**中使用您喜欢的任何名称,在**公司标识符**中使用*自我教育*。和之前的 app 一样,确保选择 **iPhone** 是选择**设备****使用故事板****使用自动参考计数**:
......@@ -24,7 +24,7 @@
## 模板概述
我们将在模板的现有代码上构建,所以让我们快速查看一下默认应用程序。点击 Xcode 左上角的**运行**按钮或按 Cmd+R 编译应用程序,在 iOS 模拟器中启动。您应该会在导航栏中看到一个名为**大师**的空列表,其中有一个**编辑**按钮和一个**添加**按钮(加号)。点击**添加**按钮将在列表中插入一个新项目,选择该项目将过渡到细节场景。两个场景如下图所示。
我们将在模板的现有代码上构建,所以让我们快速查看一下默认应用。点击 Xcode 左上角的**运行**按钮或按 Cmd+R 编译应用,在 iOS 模拟器中启动。您应该会在导航栏中看到一个名为**大师**的空列表,其中有一个**编辑**按钮和一个**添加**按钮(加号)。点击**添加**按钮将在列表中插入一个新项目,选择该项目将过渡到细节场景。两个场景如下图所示。
| ![](img/image032.jpg) | ![](img/image033.jpg) |
......@@ -36,7 +36,7 @@
### 申请代表
与前一章一样,`AppDelegate`类允许您对应用程序生命周期中的重要事件做出反应。我们的朋友列表应用程序不需要任何自定义的启动行为,所以我们根本不会编辑这个类。
与前一章一样,`AppDelegate`类允许您对应用生命周期中的重要事件做出反应。我们的朋友列表应用不需要任何自定义的启动行为,所以我们根本不会编辑这个类。
### 视图控制器
......@@ -68,13 +68,13 @@
图 34:模板的默认故事板
界面构建器现在管理三个控制器,而不是单一的视图控制器。考虑到我们的应用程序只有*两个*场景,这可能看起来很奇怪,但是`MasterViewController``DetailViewController`都嵌入在一个`UINavigationController`实例中。这个导航控制器就是为什么我们会在应用程序的顶部看到一个导航栏,它让我们在主场景和细节场景之间来回导航。我们将在本章中讨论更多关于配置导航控制器的内容。
界面构建器现在管理三个控制器,而不是单一的视图控制器。考虑到我们的应用只有*两个*场景,这可能看起来很奇怪,但是`MasterViewController``DetailViewController`都嵌入在一个`UINavigationController`实例中。这个导航控制器就是为什么我们会在应用的顶部看到一个导航栏,它让我们在主场景和细节场景之间来回导航。我们将在本章中讨论更多关于配置导航控制器的内容。
这个模板还应该阐明为什么**maintoryboard .故事板**文件被称为“故事板”——它不仅可视化场景本身,而且可视化这些场景之间的流动。与前一章一样,指向导航控制器的箭头表明它是根控制器。但是,我们也看到了从导航控制器到`MasterViewController`和从`MasterViewController``DetailViewController`的另一个箭头。这些箭头定义了应用程序中所有视图控制器之间的关系和转换。
这个模板还应该阐明为什么**maintoryboard .故事板**文件被称为“故事板”——它不仅可视化场景本身,而且可视化这些场景之间的流动。与前一章一样,指向导航控制器的箭头表明它是根控制器。但是,我们也看到了从导航控制器到`MasterViewController`和从`MasterViewController``DetailViewController`的另一个箭头。这些箭头定义了应用中所有视图控制器之间的关系和转换。
## 模型数据
与前一章不同,这个应用程序将使用一个专用的类来表示它的模型数据。我们将使用`Person`类来存储每个朋友的联系信息。在 Xcode 中创建新文件,选择**目标-C 类**,在**类**字段输入*人*,如下图:
与前一章不同,这个应用将使用一个专用的类来表示它的模型数据。我们将使用`Person`类来存储每个朋友的联系信息。在 Xcode 中创建新文件,选择**目标-C 类**,在**类**字段输入*人*,如下图:
![](img/image035.png)
......@@ -112,7 +112,7 @@
```
这就是我们表示应用程序背后的数据所需的全部内容。该类的实例将在`MasterViewController``DetailViewController`场景之间传递,这将使用各种用户界面组件显示它们。
这就是我们表示应用背后的数据所需的全部内容。该类的实例将在`MasterViewController``DetailViewController`场景之间传递,这将使用各种用户界面组件显示它们。
## 主场景
......@@ -134,7 +134,7 @@
图 37:导航控制器提供的内置导航按钮
场景之间切换的内置功能使导航控制器成为配置复杂应用程序流的简单方法。下一节讨论如何定义导航控制器场景之间的过渡。
场景之间切换的内置功能使导航控制器成为配置复杂应用流的简单方法。下一节讨论如何定义导航控制器场景之间的过渡。
### Segues
......@@ -184,7 +184,7 @@
如果将**内容**字段设置为**动态原型**,则可以通过复制界面构建器中设计的原型单元格来创建新单元格。*静态单元格*则不可复制,产生静态表格。这意味着当您想要动态插入或删除行时,应该使用**动态原型**,当您的表格总是显示相同数量的信息时,应该使用**静态单元格**。保持主场景的桌子动态。我们将为细节场景使用静态表。
当您使用原型单元时,您需要给每个原型一个唯一的标识符,以便可以从您的源代码中访问它(就像 segue ID 一样)。要编辑原型单元的标识,请在场景编辑器或界面构建器中选择该单元,并打开**属性检查器**。该特定原型的标识符可以在**标识符**字段中设置,如下图所示。因为我们在这个应用程序中只有一个原型单元,所以您可以保留默认的**单元**值,但是对于实际的应用程序,您应该给每个原型一个描述性的标识符。
当您使用原型单元时,您需要给每个原型一个唯一的标识符,以便可以从您的源代码中访问它(就像 segue ID 一样)。要编辑原型单元的标识,请在场景编辑器或界面构建器中选择该单元,并打开**属性检查器**。该特定原型的标识符可以在**标识符**字段中设置,如下图所示。因为我们在这个应用中只有一个原型单元,所以您可以保留默认的**单元**值,但是对于实际的应用,您应该给每个原型一个描述性的标识符。
![](img/image044.png)
......@@ -196,7 +196,7 @@
图 45:主场景的桌面视图的插座连接
表视图的数据源是一种特殊的委托,它为表中的每一行提供信息。除了原始数据,还需要一个表视图委托来定义表的行为和每行的外观。与应用程序和文本字段委托一样,它们分别通过名为 [UITableViewDataSource](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html)[UITableViewDelegate](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html) 的协议来实现。
表视图的数据源是一种特殊的委托,它为表中的每一行提供信息。除了原始数据,还需要一个表视图委托来定义表的行为和每行的外观。与应用和文本字段委托一样,它们分别通过名为 [UITableViewDataSource](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html)[UITableViewDelegate](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html) 的协议来实现。
在这种情况下,`MasterViewController`类既充当数据源又充当委托,这就是为什么主-细节模板在**主视图控制器. m** 中包含像`tableView:cellForRowAtIndexPath:``tableView:canEditRowAtIndexPath:`这样的方法。在下一节中,我们将改变这些方法来改变朋友列表的外观。
......@@ -397,7 +397,7 @@ segue 与旧的细节场景一起被删除,因此新的表格视图还不是
图 55:将标签组件连接到详图控制器
当您编译应用程序时,您应该能够从主列表中选择项目,并在详细场景中查看它们的详细信息。注意我们只能*显示*细节;我们还不能编辑它们。
当您编译应用时,您应该能够从主列表中选择项目,并在详细场景中查看它们的详细信息。注意我们只能*显示*细节;我们还不能编辑它们。
![](img/image056.jpg)
......@@ -409,7 +409,7 @@ segue 与旧的细节场景一起被删除,因此新的表格视图还不是
本章的最后一项工作是添加另一个场景,让我们编辑所选项目。我们将使用**模态分段**来实现这个新场景,而不是推送分段。模态片段在现有场景的“顶部”呈现目的地场景,很像桌面计算机中的弹出窗口。这不会影响导航层次结构,因此父级`UINavigationController`不再负责场景之间的导航,而是在必要时以模态方式呈现的场景会自行消失。
例如,我们将在现有的细节场景和新的编辑场景之间添加一个模态分段,然后我们将使用**展开分段**回到原始场景。这给了我们一个新的工具来控制我们的应用程序的流程,它也提供了一个机会,让我们对导航条更加熟悉。
例如,我们将在现有的细节场景和新的编辑场景之间添加一个模态分段,然后我们将使用**展开分段**回到原始场景。这给了我们一个新的工具来控制我们的应用的流程,它也提供了一个机会,让我们对导航条更加熟悉。
### 创建编辑场景
......@@ -457,7 +457,7 @@ segue 与旧的细节场景一起被删除,因此新的表格视图还不是
图 63:将栏按钮更改为编辑按钮
这些预定义的类型允许您访问默认的系统图标,这些图标提供了跨应用程序的一致用户体验。对于**添加** *、* **编辑** *、* **完成** *、*和其他基于文本的按钮来说,这并不是什么大不了的事情,但对于像**撰写** *这样的图标类型来说,这可能会有很大的不同:*
这些预定义的类型允许您访问默认的系统图标,这些图标提供了跨应用的一致用户体验。对于**添加** *、* **编辑** *、* **完成** *、*和其他基于文本的按钮来说,这并不是什么大不了的事情,但对于像**撰写** *这样的图标类型来说,这可能会有很大的不同:*
![](img/image064.png)
......@@ -521,7 +521,7 @@ segue 与旧的细节场景一起被删除,因此新的表格视图还不是
图 72:编辑场景的完整布局
请注意**保存**按钮是亮蓝色的,符合 iOS UX 的惯例。同样,这些默认的**标识符**有助于确保跨应用程序的一致用户界面。
请注意**保存**按钮是亮蓝色的,符合 iOS UX 的惯例。同样,这些默认的**标识符**有助于确保跨应用的一致用户界面。
### 对编辑视图控制器进行编码
......@@ -705,7 +705,7 @@ segue 与旧的细节场景一起被删除,因此新的表格视图还不是
图 78:文档大纲中的展开部分
与推送和模态分段不同,展开分段在界面构建器中没有可视化表示,因此文档大纲是您选择它们的唯一方式。我们的最后一步是通过**属性检查器**为这两个片段添加唯一的标识符。将`cancelInput`用于**取消**按钮,将`saveInput`用于**保存**按钮(注意,这是我们分别在`cancel:``save:`方法中检查的标识符)。同样,因为我们的示例应用程序非常简单,所以添加 segue 标识符更像是一个最佳实践步骤,而不是必须的。
与推送和模态分段不同,展开分段在界面构建器中没有可视化表示,因此文档大纲是您选择它们的唯一方式。我们的最后一步是通过**属性检查器**为这两个片段添加唯一的标识符。将`cancelInput`用于**取消**按钮,将`saveInput`用于**保存**按钮(注意,这是我们分别在`cancel:``save:`方法中检查的标识符)。同样,因为我们的示例应用非常简单,所以添加 segue 标识符更像是一个最佳实践步骤,而不是必须的。
![](img/image079.png)
......@@ -738,6 +738,6 @@ segue 与旧的细节场景一起被删除,因此新的表格视图还不是
## 总结
在本章中,我们学习了如何在一个应用程序中管理多个场景。我们实验了`UITableViewControllers``UINavigationControllers`,以及各种片段。本章最重要的概念之一是我们如何在每个场景之间传输数据:通过`prepareForSegue:sender:`方法和`save:``cancel:`方法进行展开。大多数应用程序实际上只是复杂数据结构的用户友好的编辑器,所以理解这些数据是如何传递的对有效组织 iOS 项目有很大帮助。
在本章中,我们学习了如何在一个应用中管理多个场景。我们实验了`UITableViewControllers``UINavigationControllers`,以及各种片段。本章最重要的概念之一是我们如何在每个场景之间传输数据:通过`prepareForSegue:sender:`方法和`save:``cancel:`方法进行展开。大多数应用实际上只是复杂数据结构的用户友好的编辑器,所以理解这些数据是如何传递的对有效组织 iOS 项目有很大帮助。
前两章涵盖了创建简单用户界面所需的所有知识。在本书的剩余部分,我们将探索用于访问媒体素材、本地化资源和播放 UI 音效的其他 iOS 框架。***
\ No newline at end of file
此差异已折叠。
# 四、本地化
到目前为止,我们所有的示例项目都假设我们的应用程序是为说英语的人准备的,但是许多应用程序可以从对非英语受众开放中受益。应用商店负责向合适的受众展示我们的应用,但作为开发人员,我们的工作是对其进行配置,以便向不同地区的用户显示适当的资源。这个过程叫做**本地化**
到目前为止,我们所有的示例项目都假设我们的应用是为说英语的人准备的,但是许多应用可以从对非英语受众开放中受益。应用商店负责向合适的受众展示我们的应用,但作为开发人员,我们的工作是对其进行配置,以便向不同地区的用户显示适当的资源。这个过程叫做**本地化**
幸运的是,iOS 让使用捆绑包本地化资源变得异常容易。`NSBundle`类通过考虑用户的首选语言自动选择合适的素材。例如,如果您为说英语的人和说西班牙语的人提供了相同图像的不同版本,上一章中讨论的`pathForResource:ofType:`方法会根据用户的设置返回不同的文件路径。这是您不应该使用硬编码路径直接访问捆绑包资源的主要原因之一。
通常需要本地化的应用程序的三个方面是包含特定语言的图像、音频或视频、硬编码字符串和故事板。在本章中,我们将简要介绍使用`NSBundle`的内置国际化功能本地化媒体资源和硬编码字符串。故事板文件可以使用相同的过程进行本地化。
通常需要本地化的应用的三个方面是包含特定语言的图像、音频或视频、硬编码字符串和故事板。在本章中,我们将简要介绍使用`NSBundle`的内置国际化功能本地化媒体资源和硬编码字符串。故事板文件可以使用相同的过程进行本地化。
## 创建示例应用程序
## 创建示例应用
本章的示例是一个简单的应用程序,它根据用户的首选语言显示不同的图像或字符串。创建一个新的单一视图应用程序,并将其称为“国际化”一如既往,应选择**使用故事板****使用自动参考计数**
本章的示例是一个简单的应用,它根据用户的首选语言显示不同的图像或字符串。创建一个新的单一视图应用,并将其称为“国际化”一如既往,应选择**使用故事板****使用自动参考计数**
## 启用本地化
使应用程序多语言的第一步是将支持的语言添加到项目中。在项目导航器中,选择项目图标:
使应用多语言的第一步是将支持的语言添加到项目中。在项目导航器中,选择项目图标:
![](img/image096.png)
......@@ -30,11 +30,11 @@
图 98:添加西班牙语本地化
现在可以将每个资源的西班牙语版本添加到应用程序捆绑包中。
现在可以将每个资源的西班牙语版本添加到应用捆绑包中。
## 定位图像
接下来,我们将研究媒体素材的本地化。在本书的资源包中,你会发现一个名为`syncfusion-icon-en.png`的文件。将此文件拖到项目导航器中,将其添加到应用程序捆绑包中,并将其重命名为`syncfusion-icon.png`。然后,通过将**视图控制器. m** 中的`viewDidLoad`方法更改为以下内容,将其显示在视图中:
接下来,我们将研究媒体素材的本地化。在本书的资源包中,你会发现一个名为`syncfusion-icon-en.png`的文件。将此文件拖到项目导航器中,将其添加到应用捆绑包中,并将其重命名为`syncfusion-icon.png`。然后,通过将**视图控制器. m** 中的`viewDidLoad`方法更改为以下内容,将其显示在视图中:
```objc
- (void)viewDidLoad {
......@@ -73,7 +73,7 @@
图 99:以编程方式向视图添加图像
您还应该在输出面板中看到路径`Internationalization.app/syncfusion-icon.png`。这里没有什么新东西,只是应用程序包顶层的一个图像——但是,一旦我们本地化了图像文件,这种情况就会改变。
您还应该在输出面板中看到路径`Internationalization.app/syncfusion-icon.png`。这里没有什么新东西,只是应用包顶层的一个图像——但是,一旦我们本地化了图像文件,这种情况就会改变。
为此,在项目导航器中选择图像,打开**实用程序**面板,点击**本地化**部分下的**本地化**
......@@ -119,23 +119,23 @@
这会在 Finder 中显示**es.lproj/**文件夹的内容,这为我们提供了手动替换文件的机会。删除现有的**syncfusion-icon.png**文件,将资源包中的**syncfusion-icon-es.png**文件复制到**es.lproj/**中。务必将其更名为**syncfusion-icon.png**。同一文件的本地化版本具有相同的文件名非常重要,这样`NSBundle`就可以找到它们。替换文件后,当您在 Xcode 中选择两个本地化时,您应该会看到不同的图像。
这应该是为了本地化我们的图像文件。要测试它,您可以像在真实设备中一样更改设备语言——通过“设置”应用程序。在模拟器中点击设备的主页按钮,点击并向右拖动屏幕,启动*设置*应用程序。在**通用** > **国际** > **语言**下,可以选择设备语言。
这应该是为了本地化我们的图像文件。要测试它,您可以像在真实设备中一样更改设备语言——通过“设置”应用。在模拟器中点击设备的主页按钮,点击并向右拖动屏幕,启动*设置*应用。在**通用** > **国际** > **语言**下,可以选择设备语言。
![](img/image106.jpg)
图 106:在 iOS 模拟器中更改设备语言
选择**西班牙语**,重新打开您的应用程序。您应该会看到西班牙语版本的**syncfusion-icon.png**(您可能需要关闭模拟器并再次编译程序)。还要注意的是`NSLog()`输出的文件路径现在是:`Internationalization.app/es.lproj/syncfusion-icon.png`
选择**西班牙语**,重新打开您的应用。您应该会看到西班牙语版本的**syncfusion-icon.png**(您可能需要关闭模拟器并再次编译程序)。还要注意的是`NSLog()`输出的文件路径现在是:`Internationalization.app/es.lproj/syncfusion-icon.png`
图 107:显示图像文件的本地化版本
如您所见,使用`NSBundle`的内置功能本地化文件非常容易。想法是使用`NSBundle`作为应用程序代码和它们所依赖的素材之间的抽象。这将本地化过程与开发过程隔离开来,使得外包翻译变得非常容易。
如您所见,使用`NSBundle`的内置功能本地化文件非常容易。想法是使用`NSBundle`作为应用代码和它们所依赖的素材之间的抽象。这将本地化过程与开发过程隔离开来,使得外包翻译变得非常容易。
本地化视频和音频文件使用与刚才讨论的完全相同的过程。然而,为国际读者准备文本需要更多的工作。
## 本地化文本
当您处理多语言应用程序时,硬编码字符串必须抽象成捆绑素材,以便`NSBundle`可以在运行时加载正确的语言。iOS 使用所谓的**字符串文件**来存储应用程序中所有字符串的翻译。创建这个字符串文件后,可以使用上一节中讨论的相同方法对其进行本地化。
当您处理多语言应用时,硬编码字符串必须抽象成捆绑素材,以便`NSBundle`可以在运行时加载正确的语言。iOS 使用所谓的**字符串文件**来存储应用中所有字符串的翻译。创建这个字符串文件后,可以使用上一节中讨论的相同方法对其进行本地化。
让我们改变我们的`viewDidLoad`方法,当用户点击按钮时,显示一个按钮并输出一条消息:
......@@ -175,11 +175,11 @@
```
左侧是您将用来引用应用程序代码中已翻译字符串的键。这些键是任意的字符串,但是开发人员通常使用描述如何使用该字符串的语义名称,或者使用其母语中的目标短语。在字符串文件中,我们选择了前者。每个键的值都跟在等号后面。请务必在每一行的末尾包含一个分号,否则当您试图运行应用程序时会发生可怕的事情。
左侧是您将用来引用应用代码中已翻译字符串的键。这些键是任意的字符串,但是开发人员通常使用描述如何使用该字符串的语义名称,或者使用其母语中的目标短语。在字符串文件中,我们选择了前者。每个键的值都跟在等号后面。请务必在每一行的末尾包含一个分号,否则当您试图运行应用时会发生可怕的事情。
与媒体素材一样,您可以通过`NSBundle`访问**可本地化字符串**的内容。`localizedStringForKey:value:table:`方法从特定的字符串文件中返回键值。`value`参数允许您在找不到键的情况下指定默认返回值,而`table`参数确定要使用哪个字符串文件。当您为`table`指定`nil`时,将使用默认的`Localizable.strings`文件。
由于访问翻译后的字符串是如此常见的任务,Foundation Framework 还提供了一个方便的`NSLocalizedString()`宏,您可以将其用作`localizedStringForKey:value:table:`的简单快捷方式。它传递一个空字符串给`value`参数和`nil``table`参数。对于大多数应用程序来说,`NSLocalizedString()`是您访问本地化文本真正需要的。
由于访问翻译后的字符串是如此常见的任务,Foundation Framework 还提供了一个方便的`NSLocalizedString()`宏,您可以将其用作`localizedStringForKey:value:table:`的简单快捷方式。它传递一个空字符串给`value`参数和`nil``table`参数。对于大多数应用来说,`NSLocalizedString()`是您访问本地化文本真正需要的。
因此,让我们将按钮的标题配置更改为使用`NSLocalizedString()`:
......@@ -226,11 +226,11 @@
图 111:将设备语言更改为西班牙语
这就是在 iOS 应用程序中本地化字符串的全部内容。同样,将所有的翻译文本放在一个文件中——完全从应用程序代码中抽象出来——可以很容易地外包本地化工作。这是一件非常好的事情,因为大多数开发人员不会流利地说他们希望将其应用程序翻译成的所有语言。
这就是在 iOS 应用中本地化字符串的全部内容。同样,将所有的翻译文本放在一个文件中——完全从应用代码中抽象出来——可以很容易地外包本地化工作。这是一件非常好的事情,因为大多数开发人员不会流利地说他们希望将其应用翻译成的所有语言。
## 本地化信息列表
还有一个重要的细节尚未解决——应用程序名称的本地化。如果你看看 iOS 模拟器的主屏幕,你会发现你的应用图标下的标题还没有被翻译成西班牙语。如果你已经经历了在你的应用程序中本地化字符串*的麻烦,你还不如花点时间翻译一点元数据。*
还有一个重要的细节尚未解决——应用名称的本地化。如果你看看 iOS 模拟器的主屏幕,你会发现你的应用图标下的标题还没有被翻译成西班牙语。如果你已经经历了在你的应用中本地化字符串*的麻烦,你还不如花点时间翻译一点元数据。*
*应用的显示名称在`CFBundleDisplayName`键下的`Info.plist`中定义。iOS 没有强制你翻译主`Internationalization-Info.plist`文件中的值,而是给你一个专用的字符串文件,用本地化的值覆盖某些配置选项。在项目导航器的**支持文件**组中,打开 **InfoPlist.strings** 文件。这就像我们在前一节中创建的 Localizable.strings 文件一样,只是它应该只为`Info.plist`键提供值。将以下内容添加到您的 **InfoPlist.strings** 文件:
......@@ -239,7 +239,7 @@
```
现在,如果您重置模拟器并进行干净的构建,您应该会在应用程序图标下看到一个西班牙语标题。
现在,如果您重置模拟器并进行干净的构建,您应该会在应用图标下看到一个西班牙语标题。
![](img/image112.jpg)
......@@ -247,6 +247,6 @@
## 总结
在本章中,我们学习了如何使用`NSBundle`本地化媒体素材、文本和元数据。通过将需要本地化的资源抽象成独立的文件,并通过`pathForResource:ofType:`这样的方法间接引用它们,就有可能将您的应用程序翻译成另一种语言,而不需要接触任何一行应用程序代码。这是 iOS 非常强大的功能,尤其是考虑到 iPhone 和 iPad 设备的国际流行。
在本章中,我们学习了如何使用`NSBundle`本地化媒体素材、文本和元数据。通过将需要本地化的资源抽象成独立的文件,并通过`pathForResource:ofType:`这样的方法间接引用它们,就有可能将您的应用翻译成另一种语言,而不需要接触任何一行应用代码。这是 iOS 非常强大的功能,尤其是考虑到 iPhone 和 iPad 设备的国际流行。
*iOS 的最后一章简洁地*简单介绍了 iOS 应用的内置音频支持。正如我们在前几章中提到的,音频文件使用与图像和字符串文件相同的包结构。然而,我们将讨论控制音频播放的高级工具,而不是关注如何访问这些资源。***
\ No newline at end of file
......@@ -530,7 +530,7 @@ Check the length of the set. Can also use .size()
jQuery 提供了`noConflict()`方法,它有几个用途——即能够用另一个别名替换`$`。这可以在三个方面有所帮助:它可以将`$`符号的使用放弃给另一个库,帮助避免潜在的冲突,并提供为 jQuery 对象定制名称空间/别名的能力。
例如,假设您正在为 XYZ 公司构建一个网络应用程序。定制 jQuery 可能会很好,这样您就可以使用`XYZ('div').show()`来代替使用`jQuery('div').show()``$('div').show()`了。
例如,假设您正在为 XYZ 公司构建一个网络应用。定制 jQuery 可能会很好,这样您就可以使用`XYZ('div').show()`来代替使用`jQuery('div').show()``$('div').show()`了。
样本:sample15.html
......
# 零、简介
创建数据驱动的用户界面是 web 开发人员最复杂的工作之一。它需要对接口及其底层数据进行仔细的管理。例如,考虑一个电子商务网站的简单购物车界面。当用户从购物车中删除一个项目时,您必须从基础数据集中删除该项目,从购物车的 HTML 页面中删除关联的元素,并更新总价。除了最琐碎的应用程序之外,找出哪些 HTML 元素依赖于特定的数据是一项容易出错的工作。
创建数据驱动的用户界面是 web 开发人员最复杂的工作之一。它需要对接口及其底层数据进行仔细的管理。例如,考虑一个电子商务网站的简单购物车界面。当用户从购物车中删除一个项目时,您必须从基础数据集中删除该项目,从购物车的 HTML 页面中删除关联的元素,并更新总价。除了最琐碎的应用之外,找出哪些 HTML 元素依赖于特定的数据是一项容易出错的工作。
![](img/image001.png)
......@@ -12,7 +12,7 @@
图 2:使用knockout自动跟踪依赖关系
这允许您关注应用程序背后的数据。设置完 HTML 模板后,您可以专门使用 JavaScript 数据对象。使用knockout. js,从购物车中移除一个项目所要做的就是从代表用户购物车项目的 JavaScript 数组中移除它。相应的 HTML 元素将自动从页面中移除,总价将重新计算。
这允许您关注应用背后的数据。设置完 HTML 模板后,您可以专门使用 JavaScript 数据对象。使用knockout. js,从购物车中移除一个项目所要做的就是从代表用户购物车项目的 JavaScript 数组中移除它。相应的 HTML 元素将自动从页面中移除,总价将重新计算。
换句话说,knockout. js 允许你为你的 JavaScript 对象设计一个自我更新的显示。
......@@ -28,7 +28,7 @@ knockout. js 是一个完全用 JavaScript 编写的*客户端*库。这使得
### 可扩张的
虽然knockout. js 附带了将近 24 个定义数据显示方式的绑定,但您可能仍然需要特定于应用程序的行为(例如,用户提交的电影评论的星级小部件)。幸运的是,knockout. js 使您可以轻松添加自己的绑定,让您完全控制如何将数据转换为 HTML。而且,由于这些自定义绑定被集成到核心模板语言中,所以在应用程序的其他部分重用小部件并不重要。
虽然knockout. js 附带了将近 24 个定义数据显示方式的绑定,但您可能仍然需要特定于应用的行为(例如,用户提交的电影评论的星级小部件)。幸运的是,knockout. js 使您可以轻松添加自己的绑定,让您完全控制如何将数据转换为 HTML。而且,由于这些自定义绑定被集成到核心模板语言中,所以在应用的其他部分重用小部件并不重要。
![](img/image003.png)
......@@ -44,6 +44,6 @@ knockout. js 是*而不是*是为了替代 jQuery、Prototype 或 MooTools。它
![](img/image004.png)
图 4:knockout. js 补充了一个完整的 web 应用程序堆栈
图 4:knockout. js 补充了一个完整的 web 应用堆栈
这种高水平的专门化使得 knowledge . js 与任何其他客户端和服务器端技术兼容,但这也意味着 knowledge . js 通常需要功能更全面的 JavaScript 框架的配合。从这个意义上来说,knockout. js 更多的是对传统 web 应用程序堆栈的*补充*,而不是其不可分割的一部分。*
\ No newline at end of file
这种高水平的专门化使得 knowledge . js 与任何其他客户端和服务器端技术兼容,但这也意味着 knowledge . js 通常需要功能更全面的 JavaScript 框架的配合。从这个意义上来说,knockout. js 更多的是对传统 web 应用堆栈的*补充*,而不是其不可分割的一部分。*
\ No newline at end of file
......@@ -12,7 +12,7 @@ knockout. js 使用模型-视图-视图模型(MVVM)设计模式,这是经典
* **模型:**存储在数据库、cookie 或其他一些持久存储中的用户购物车的内容。knockout. js 并不关心您的数据是如何存储的,而是由您来决定模型存储和knockout. js 之间的通信。通常,您将通过 AJAX 调用来保存和加载模型数据。
* **视图:**向用户显示的 HTML/CSS 购物车页面。将视图连接到视图模型后,当视图模型改变时,它将自动显示新的、删除的和更新的项目。
* **ViewModel:** 表示购物车的纯 JavaScript 对象,包括项目列表和用于与模型交互的保存/加载方法。将您的 HTML 视图与视图模型连接后,您的应用程序只需要担心如何操作这个对象。
* **ViewModel:** 表示购物车的纯 JavaScript 对象,包括项目列表和用于与模型交互的保存/加载方法。将您的 HTML 视图与视图模型连接后,您的应用只需要担心如何操作这个对象。
## 看得见的
......@@ -34,4 +34,4 @@ knockout. js 使用**可观测到的**来跟踪视图模型的属性。从概念
## 摘要
模型-视图-视图模型设计模式、可观测的对象和绑定为knockout. js 库提供了基础。一旦你理解了这些概念,学习 knowledge . js 就是一件简单的事情,弄清楚如何通过各种内置绑定来访问观察对象和操纵它们。在下一章中,我们将通过构建一个简单的“你好,世界!”应用程序。
\ No newline at end of file
模型-视图-视图模型设计模式、可观测的对象和绑定为knockout. js 库提供了基础。一旦你理解了这些概念,学习 knowledge . js 就是一件简单的事情,弄清楚如何通过各种内置绑定来访问观察对象和操纵它们。在下一章中,我们将通过构建一个简单的“你好,世界!”应用。
\ No newline at end of file
# 二、你好,knockout
这一章旨在对knockout. js 的主要组成部分进行高层次的调查。通过实现一个具体的示例应用程序,我们将看到knockout的视图模型、视图、观察点和绑定如何交互来创建一个动态用户界面。
这一章旨在对knockout. js 的主要组成部分进行高层次的调查。通过实现一个具体的示例应用,我们将看到knockout的视图模型、视图、观察点和绑定如何交互来创建一个动态用户界面。
首先,我们将创建一个简单的 HTML 页面来保存我们所有的代码,然后我们将定义一个 ViewModel 对象,公开一些属性,甚至添加一个交互式绑定,这样我们就可以对用户的点击做出反应。
......@@ -146,12 +146,12 @@ knockout. js 的全套交互式绑定将在[第 6 章](06.html#_Chapter_6_Intera
## 摘要
本章详细介绍了knockout. js 的核心方面。正如我们所看到的,设置基于knockout. js 的 web 应用程序有三个步骤:
本章详细介绍了knockout. js 的核心方面。正如我们所看到的,设置基于knockout. js 的 web 应用有三个步骤:
1. 创建一个 ViewModel 对象,并将其注册到 Kellow . js。
2. 将 HTML 元素绑定到视图模型的属性之一。
3. 使用可观测的对象将属性公开给knockout
您可以将视图元素绑定到可观测的属性看作是为一个 JavaScript 对象构建一个 HTML 模板。模板设置好之后,您可以完全忘记 HTML,只关注应用程序背后的视图模型数据。这就是knockout的全部意义
您可以将视图元素绑定到可观测的属性看作是为一个 JavaScript 对象构建一个 HTML 模板。模板设置好之后,您可以完全忘记 HTML,只关注应用背后的视图模型数据。这就是knockout的全部意义
在下一章中,我们将通过创建依赖于其他属性的可观测值,以及保存数据列表的可观测数组,来探索 well as 自动依赖跟踪器背后的真正力量。
\ No newline at end of file
......@@ -45,7 +45,7 @@
这应该会将该行更改为“玛丽·史密斯的购物车”同样,请记住,读取或设置可观测值应该通过函数调用来完成,而不是赋值(`=`)运算符。
计算出的可观测值提供了许多与敲除. js 的视图自动同步相同的好处。计算的可观测值让您可以围绕原子属性构建应用程序,并将依赖关系跟踪委托给 Lenking . js,而不必跟踪哪些属性依赖于 ViewModel 的其他部分。
计算出的可观测值提供了许多与敲除. js 的视图自动同步相同的好处。计算的可观测值让您可以围绕原子属性构建应用,并将依赖关系跟踪委托给 Lenking . js,而不必跟踪哪些属性依赖于 ViewModel 的其他部分。
## 可观测阵列
......@@ -58,7 +58,7 @@
```
这只是一个存储一些属性的简单数据对象。请注意,可以给多个对象提供可观测的属性,knockout. js 将自行管理所有的相互依赖关系。换句话说,可以在单个应用程序中创建多个视图模型之间的关系。
这只是一个存储一些属性的简单数据对象。请注意,可以给多个对象提供可观测的属性,knockout. js 将自行管理所有的相互依赖关系。换句话说,可以在单个应用中创建多个视图模型之间的关系。
接下来,我们将创建几个新的`Product`类的实例,并将它们添加到用户的虚拟购物车中。在`PersonViewModel`内部,定义一个新的可观测属性,称为`shoppingCart`:
......@@ -115,7 +115,7 @@
当你点击此按钮时,视图模型的`addProduct()`方法被执行。而且,由于`shoppingCart`是一个可观测的数组,所以knockout. js 会插入另一个`<tr>`元素来显示新项目。与每当我们更改底层数组时试图手动更新`<table>`相比,让knockout. js 跟踪这样的列表项更不容易出错。
还值得指出的是,knockout. js 总是使同步用户界面所需的*最小化*变化量。不是每次添加或删除一个项目就重新生成整个列表,knockout. js 跟踪 DOM 的哪些部分受到影响,并且只更新*那些元素。这种内置的优化可以将您的应用程序扩展到数百甚至数千个项目,而不会牺牲响应能力。*
还值得指出的是,knockout. js 总是使同步用户界面所需的*最小化*变化量。不是每次添加或删除一个项目就重新生成整个列表,knockout. js 跟踪 DOM 的哪些部分受到影响,并且只更新*那些元素。这种内置的优化可以将您的应用扩展到数百甚至数千个项目,而不会牺牲响应能力。*
### 删除项目
......
......@@ -107,7 +107,7 @@
```
在可观测的数组、`foreach`绑定和前面讨论的绑定上下文属性之间,您应该拥有在您的knockout. js web 应用程序中利用数组所需的所有工具。
在可观测的数组、`foreach`绑定和前面讨论的绑定上下文属性之间,您应该拥有在您的knockout. js web 应用中利用数组所需的所有工具。
## 打折产品
......@@ -140,7 +140,7 @@
```
只有折扣大于`0`的商品才会出现`<td>`元素中的所有内容。另外,由于`discount`是一个可观测到的,每当条件改变时,knockout. js 会自动重新评估。这只是knockout. js 帮助您专注于驱动应用程序的数据的又一种方式。
只有折扣大于`0`的商品才会出现`<td>`元素中的所有内容。另外,由于`discount`是一个可观测到的,每当条件改变时,knockout. js 会自动重新评估。这只是knockout. js 帮助您专注于驱动应用的数据的又一种方式。
![](img/image015.png)
......
# 五、外观绑定
在上一章中,我们看到了 Quinch . js 的控制流绑定如何为视图代码提供一个基本的模板系统。控制流绑定为应用程序提供了可视化结构,但是一个成熟的模板系统需要的不仅仅是结构。knockout. js 的外观绑定让您可以精确控制单个元素的样式和格式。
在上一章中,我们看到了 Quinch . js 的控制流绑定如何为视图代码提供一个基本的模板系统。控制流绑定为应用提供了可视化结构,但是一个成熟的模板系统需要的不仅仅是结构。knockout. js 的外观绑定让您可以精确控制单个元素的样式和格式。
在撰写本文时,knockout. js 附带了六个绑定来控制 HTML 元素的外观:
......@@ -145,6 +145,6 @@
这一章介绍了knockout. js 的外观绑定。当满足特定条件时,这些绑定中的许多会更改 HTML 元素。直接在绑定中定义这些条件是设计模板的一种直观方式,它将视图为中心的代码保持在视图模型之外。
请记住,knockout. js 的目标是通过在数据发生变化时自动同步视图,让您专注于应用程序背后的数据。一旦定义了绑定,就再也不用担心它们了(当然,除非您改变视图模型的结构)。
请记住,knockout. js 的目标是通过在数据发生变化时自动同步视图,让您专注于应用背后的数据。一旦定义了绑定,就再也不用担心它们了(当然,除非您改变视图模型的结构)。
本章中展示的外观绑定提供了您需要的所有工具来*显示*您的数据,但是它们不允许我们向视图组件添加任何用户交互。在下一章中,我们将看一下 Dellow . js 是如何管理表单域的。
\ No newline at end of file
......@@ -23,7 +23,7 @@ knockout. js 包括 11 个用于与用户交互的绑定:
像上一章中介绍的外观绑定一样,这些都是在 HTML 元素的数据绑定属性中定义的。它们中的一些(像`click`绑定)对任何元素都有效,但是其他的(像`checked`)只能用于特定的元素。
使用knockout. js 管理 HTML 表单的一个主要好处是你*仍然*只需要担心数据。每当用户更改表单元素的值时,视图模型将自动反映该更新。这使得将用户输入集成到应用程序的其余部分变得非常容易。
使用knockout. js 管理 HTML 表单的一个主要好处是你*仍然*只需要担心数据。每当用户更改表单元素的值时,视图模型将自动反映该更新。这使得将用户输入集成到应用的其余部分变得非常容易。
## 一个超文本标记语言表单
......@@ -75,7 +75,7 @@ knockout. js 包括 11 个用于与用户交互的绑定:
```
`value: firstName`绑定确保了`<input>`元素的文本始终与视图模型的`firstName`属性相同,无论它是由用户还是由您的应用程序更改的。`lastName`物业也是如此。
`value: firstName`绑定确保了`<input>`元素的文本始终与视图模型的`firstName`属性相同,无论它是由用户还是由您的应用更改的。`lastName`物业也是如此。
![](img/image020.png)
......@@ -422,12 +422,12 @@ HTML 的`<select>`元素的另一种呈现方式是多选列表。配置多选
```
通过在应用程序的其他地方设置此属性,可以精确控制窗体中的焦点流。此外,还可以使用`hasfocus`通过多个表单域跟踪用户进度。
通过在应用的其他地方设置此属性,可以精确控制窗体中的焦点流。此外,还可以使用`hasfocus`通过多个表单域跟踪用户进度。
## 摘要
本章介绍了交互式绑定,它利用了敲除器对 HTML 表单字段的自动依赖跟踪。与外观绑定不同,交互绑定是*双向*绑定——对用户界面组件的更改会自动反映在视图模型中,对视图模型属性的赋值会触发淘汰机. js 相应地更新视图。
交互式绑定、外观绑定和控制流绑定组成了 Quicken . js 的模板工具包。他们的共同目标是为您的 web 应用程序提供一个以数据为中心的界面。一旦您使用这些绑定定义了数据的表示,您所要担心的就是操作底层的视图模型。这是开发动态 web 应用程序的一种更加健壮的方法。
交互式绑定、外观绑定和控制流绑定组成了 Quicken . js 的模板工具包。他们的共同目标是为您的 web 应用提供一个以数据为中心的界面。一旦您使用这些绑定定义了数据的表示,您所要担心的就是操作底层的视图模型。这是开发动态 web 应用的一种更加健壮的方法。
本章从视图和视图模型的角度讨论表单。交互式绑定是访问用户输入的一种直观的、可扩展的方法,但是我们还没有讨论如何将这些数据从前端获取到服务器端脚本中。下一章将通过将敲除. js 与 jQuery 的 AJAX 功能相集成来解决这个问题。**
\ No newline at end of file
# 七、访问外部数据
对于大多数 web 应用程序来说,如果不能将数据传递给服务器,收集用户输入相对来说是没有用的。在本章中,我们将学习如何使用 AJAX 请求从服务器发送和接收信息。这将把*模型*放回模型-视图-视图模型设计模式中
对于大多数 web 应用来说,如果不能将数据传递给服务器,收集用户输入相对来说是没有用的。在本章中,我们将学习如何使用 AJAX 请求从服务器发送和接收信息。这将把*模型*放回模型-视图-视图模型设计模式中
![](img/image027.png)
......@@ -37,7 +37,7 @@
## 正在加载数据
你可能注意到了,与前几章不同,我们所有的观察点都是空的。我们将使用 jQuery 的`$.getJSON()`方法从服务器加载数据,而不是将数据硬编码到我们的视图模型中。首先,让我们制作一个用于加载数据的按钮(通常,当应用程序启动时,您会自动加载数据,但这样我们就可以一步一步地看到一切是如何工作的):
你可能注意到了,与前几章不同,我们所有的观察点都是空的。我们将使用 jQuery 的`$.getJSON()`方法从服务器加载数据,而不是将数据硬编码到我们的视图模型中。首先,让我们制作一个用于加载数据的按钮(通常,当应用启动时,您会自动加载数据,但这样我们就可以一步一步地看到一切是如何工作的):
```js
<p><button data-bind='click: loadUserData'>Load Data</button></p>
......@@ -75,7 +75,7 @@
## 保存数据
对于普通的 web 应用程序,保存数据是一件简单的事情,将对象转换成 JSON,然后用类似 jQuery 的`$.post()`方法将其发送到服务器。对于knockout. js 应用程序来说,事情有些复杂。不可能使用标准的 JSON 序列化程序将对象转换为字符串,因为视图模型使用可观测的对象,而不是普通的 JavaScript 属性。请记住,可观测对象实际上是函数,因此尝试序列化它们并将结果发送到服务器会有意想不到的结果。
对于普通的 web 应用,保存数据是一件简单的事情,将对象转换成 JSON,然后用类似 jQuery 的`$.post()`方法将其发送到服务器。对于knockout. js 应用来说,事情有些复杂。不可能使用标准的 JSON 序列化程序将对象转换为字符串,因为视图模型使用可观测的对象,而不是普通的 JavaScript 属性。请记住,可观测对象实际上是函数,因此尝试序列化它们并将结果发送到服务器会有意想不到的结果。
幸运的是,knockout. js 为这个问题提供了一个简单的解决方案:`ko.toJSON()`实用函数。将一个对象传递给`ko.toJSON()`会用其当前值替换该对象的所有可观测属性,并将结果作为 JSON 字符串返回。
......@@ -115,7 +115,7 @@ knockout. js 的`mapping`插件通过让您自动将从服务器加载的 JSON
```
当我们的应用程序加载时,它会立即对初始用户数据发出 AJAX 请求。您的`/get-intial-data`服务器端脚本应该返回与本章[加载数据](#heading_id_68)部分的示例 JSON 输出相同的内容。一旦数据被加载,我们通过`ko.mapping.fromJS()`创建一个视图模型。这将采用脚本生成的本机 JavaScript 对象,并将每个属性转换为可观测的。除了`saveUserData()``loadUserData()`方法,这个动态生成的视图模型具有与`PersonViewModel`完全相同的功能。
当我们的应用加载时,它会立即对初始用户数据发出 AJAX 请求。您的`/get-intial-data`服务器端脚本应该返回与本章[加载数据](#heading_id_68)部分的示例 JSON 输出相同的内容。一旦数据被加载,我们通过`ko.mapping.fromJS()`创建一个视图模型。这将采用脚本生成的本机 JavaScript 对象,并将每个属性转换为可观测的。除了`saveUserData()``loadUserData()`方法,这个动态生成的视图模型具有与`PersonViewModel`完全相同的功能。
此时,我们只使用来自服务器的数据初始化了我们的视图模型*。`mapping`插件也让我们*以同样的方式更新*一个现有的视图模型。让我们继续向视图模型添加一个显式的`loadUserData()`方法:*
......
# 九、总结
gentle . js 是一个纯 JavaScript 库,它使得构建动态的、以数据为中心的用户界面变得非常容易。我们学习了如何使用可观测对象公开视图模型属性,将 HTML 元素绑定到这些可观测对象,使用交互式绑定管理用户输入,将数据导出到服务器端脚本,以及使用自定义绑定制作组件动画。希望您已经准备好将这些知识移植到您的真实网络应用程序中。
gentle . js 是一个纯 JavaScript 库,它使得构建动态的、以数据为中心的用户界面变得非常容易。我们学习了如何使用可观测对象公开视图模型属性,将 HTML 元素绑定到这些可观测对象,使用交互式绑定管理用户输入,将数据导出到服务器端脚本,以及使用自定义绑定制作组件动画。希望您已经准备好将这些知识移植到您的真实网络应用中。
这本书涵盖了绝大多数的knockout. js 应用编程接口,但仍有许多细微差别有待发现。这些主题包括:聚合数据类型的自定义绑定,`throttle`扩展程序,用于计算的可观测值的异步评估,以及手动订阅可观测值的事件。然而,所有这些都是高级主题,对于典型的 web 应用程序来说不应该是必需的。尽管如此,knockout. js 提供了大量的可扩展性机会供您探索。
\ No newline at end of file
这本书涵盖了绝大多数的knockout. js 应用编程接口,但仍有许多细微差别有待发现。这些主题包括:聚合数据类型的自定义绑定,`throttle`扩展程序,用于计算的可观测值的异步评估,以及手动订阅可观测值的事件。然而,所有这些都是高级主题,对于典型的 web 应用来说不应该是必需的。尽管如此,knockout. js 提供了大量的可扩展性机会供您探索。
\ No newline at end of file
......@@ -2,4 +2,4 @@
地图总是有神奇的地方。自从第一批人类在泥土中抓出一个图像来分享好的狩猎场的位置以来,我们就对地图以及它们能传递多少信息着迷了。几个世纪以来,地图在准确性和复杂性方面都取得了巨大的进步,但直到最近,随着互联网的出现,地图仍然主要是基于纸张的。互联网是共享地图和寻找大量有趣的空间数据以创建地图的完美媒介。
不久前,将任何形式的交互式地图放在网络上的前景足以让最老练的开发人员做噩梦。如今,我们有了一些惊人的工具,即使是没有经验的开发人员也可以很容易地创建高度复杂的网络地图应用程序,只需要一个文本编辑器和一个互联网连接。创建令人惊叹的、功能强大的网络地图应用程序的最新最好的技术之一是 Leaflet.js。只需掌握一点 HTML、CSS 和一些基本的 JavaScript 知识,再加上本指南,您就拥有了开始使用所需的一切。
\ No newline at end of file
不久前,将任何形式的交互式地图放在网络上的前景足以让最老练的开发人员做噩梦。如今,我们有了一些惊人的工具,即使是没有经验的开发人员也可以很容易地创建高度复杂的网络地图应用,只需要一个文本编辑器和一个互联网连接。创建令人惊叹的、功能强大的网络地图应用的最新最好的技术之一是 Leaflet.js。只需掌握一点 HTML、CSS 和一些基本的 JavaScript 知识,再加上本指南,您就拥有了开始使用所需的一切。
\ No newline at end of file
......@@ -2,13 +2,13 @@
Leaflet. js 是一个超轻量级的映射库。它由大约 34KB 的压缩 JavaScript 组成,绝对没有外部依赖。Leaflet. js 真正不同寻常的是,它在不牺牲特性的情况下做到了这一点。尽管随着时间的推移,许多框架很快变得臃肿和复杂,但 Labber . js 在场景中仍然相对较新,并且是由开发人员 Vladimir Agafonkin 从头开始设计的,简单、直观且易于使用。
Leaflet.js 是开源的,有一个非常活跃的开发者社区。尽管核心库在设计上非常小(为了避免你的应用程序不得不下载大量它不依赖的代码),有许多插件可以用来扩展你的网络地图应用程序的功能。所以,如果你在看另一个网络地图框架,并想,“如果Leaflet. js 做到了,那不是很酷吗?”你几乎可以肯定,某个地方的某个人也想到了同样的事情,并为其编写了一个插件。
Leaflet.js 是开源的,有一个非常活跃的开发者社区。尽管核心库在设计上非常小(为了避免你的应用不得不下载大量它不依赖的代码),有许多插件可以用来扩展你的网络地图应用的功能。所以,如果你在看另一个网络地图框架,并想,“如果Leaflet. js 做到了,那不是很酷吗?”你几乎可以肯定,某个地方的某个人也想到了同样的事情,并为其编写了一个插件。
我可以继续介绍 lafob . js 的伟大设计及其惊人的功能,但这是一个简洁的指南,我们希望您能立即站起来并运行,并帮助您自己发现这些东西。让我们开始吧。
基本上,不多。您需要一个文本编辑器来编写代码;任何你熟悉的文本编辑器都可以正常工作。我使用的是一个跨平台编辑器,名为支架,是 Adobe 专门为网络开发设计的,但是你可以使用任何你喜欢的东西。尝试并获得一个支持 HTML、CSS 和 JavaScript 语法突出显示的工具,因为它将帮助您理解代码并快速发现任何语法错误。记事本++对于 Windows 用户来说是一个不错的选择。
你需要一个网络浏览器。同样,使用你最喜欢的,但我建议选择 Mozilla Firefox 或 Google Chrome,因为它们有如此优秀的开发工具。当你绞尽脑汁想知道为什么应用程序的某些功能不起作用,而 JavaScript 却不知道错误的本质时,这些确实很有帮助。
你需要一个网络浏览器。同样,使用你最喜欢的,但我建议选择 Mozilla Firefox 或 Google Chrome,因为它们有如此优秀的开发工具。当你绞尽脑汁想知道为什么应用的某些功能不起作用,而 JavaScript 却不知道错误的本质时,这些确实很有帮助。
我还建议您使用网络服务器来托管您的 HTML 页面和 JavaScript 代码。虽然可以通过直接在浏览器中打开代码文件来运行本书中的大多数示例,但是除了琐碎的实验之外,您可能还想使用 web 服务器。我用的是 XAMPP,它超级容易配置和使用,在 Windows 和 Mac 上都有。XAMPP 提供了一个安装程序来设置一个本地的 Apache 网络服务器,以及其他组件,当你开始扩展你对 Layeb . js 的知识时,你可能会发现这些组件很有用。这些组件包括 MySQL(世界上最流行的开源网络数据库)和 MariaDB,MySQL 的替代插件,以及用于服务器端脚本的 PHP 语言。
......@@ -16,7 +16,7 @@ Leaflet.js 是开源的,有一个非常活跃的开发者社区。尽管核心
只需为您选择的解决方案运行安装程序,启动它,并注意服务器的*文档根*在哪里,以及网络服务器运行在哪个*端口*上。文档根目录是文件系统中放置您创建的 HTML 和 JavaScript(以及 PHP,如果您遵循第 5 章中的示例)文件的位置。当您尝试通过 web 浏览器访问特定页面时,web 服务器会在文档根目录中查找相应的文件。您需要输入端口号作为网址的一部分,以便您选择的网络服务器可以拦截任何请求。
启动应用程序的图形用户界面控制面板,并确保 Apache 和 MySQL 服务正在运行。(MySQL 在这里是可选的,但是如果您想运行第 5 章中的数据库示例,您将在以后需要它。)这是 XAMPP 的样子:
启动应用的图形用户界面控制面板,并确保 Apache 和 MySQL 服务正在运行。(MySQL 在这里是可选的,但是如果您想运行第 5 章中的数据库示例,您将在以后需要它。)这是 XAMPP 的样子:
![](img/00003.jpeg)
......@@ -40,7 +40,7 @@ Apache 要求您将网页放在其 htdocs 文件夹中,在我的 XAMPP 环境
书中的每个代码列表都与一个文件相关,该文件在一个文件夹中进行了相应的编号,该文件夹以其所在章节的名称命名。例如*代码清单 1* 的源代码可以在名为 Ch01_gtk 的目录中找到,叫做 listing01.html。
我还包括了我在本书中提到的两个“助手”应用程序的源代码。它们可以在 zip 文件中的 extentfinder 和 mapdraw 目录中找到,也可以在以下位置在线访问:
我还包括了我在本书中提到的两个“助手”应用的源代码。它们可以在 zip 文件中的 extentfinder 和 mapdraw 目录中找到,也可以在以下位置在线访问:
* [范围探测器](http://www.appswithmaps.net/leaflet/extentfinder)
* [地图绘制工具](http://www.appswithmaps.net/leaflet/mapdraw)
......@@ -68,7 +68,7 @@ Apache 要求您将网页放在其 htdocs 文件夹中,在我的 XAMPP 环境
3. 创建地图对象。
4. 向地图添加图层。
有两种方法可以在应用程序中使用 libert . js:
有两种方法可以在应用中使用 libert . js:
1. 通过内容交付网络(CDN)参考该库的托管版本。
2. 下载Leaflet. js 库,并将其托管在您自己的网络服务器上。
......@@ -200,7 +200,7 @@ Apache 要求您将网页放在其 htdocs 文件夹中,在我的 XAMPP 环境
我们的地图对象只是一个容器。为了让我们的地图显示一些东西,我们需要添加一个或多个*层*
通常,网络地图会有多个图层。这些将包括显示地形、道路或其他上下文信息的基础地图;和操作层,它们包含用户特别感兴趣的任何数据,例如咖啡店、餐馆或徒步旅行路线的位置。通常,基础地图由第三方托管。操作数据也可以来自其他来源,但通常是我们自己提供的,可以硬编码到应用程序中,在运行时从数据库加载,或者由用户输入。
通常,网络地图会有多个图层。这些将包括显示地形、道路或其他上下文信息的基础地图;和操作层,它们包含用户特别感兴趣的任何数据,例如咖啡店、餐馆或徒步旅行路线的位置。通常,基础地图由第三方托管。操作数据也可以来自其他来源,但通常是我们自己提供的,可以硬编码到应用中,在运行时从数据库加载,或者由用户输入。
将地图视为离散的图层允许很大的灵活性,因为它允许我们根据用户想要看到的内容来显示或隐藏信息。例如,如果我们的用户只想看餐馆,那么我们可以隐藏我们的“咖啡店”层。如果他们不在市场上吃点心,而是想去山上,那么我们可以隐藏我们的“餐馆”和“咖啡店”图层,用一些卫星图像替换街道地图,这样他们就可以更好地理解这些小径通向哪里。
......@@ -231,9 +231,9 @@ Apache 要求您将网页放在其 htdocs 文件夹中,在我的 XAMPP 环境
在这里,我们定义了一个类型为 TileLayer 的新层。我们使用 TileLayer,因为大多数基础地图都是由大量的图像组成,这些图像被分割成小块,这样浏览器只需下载特定范围内所需的图像小块。我们将在下一章更详细地讨论层。
TileLayer 对象的构造函数将一个 URL 作为其第一个参数,该 URL 告诉我们的应用程序从哪里获取切片数据。URL 中的{s}、{z}、{x}和{y}占位符表示以下内容:
TileLayer 对象的构造函数将一个 URL 作为其第一个参数,该 URL 告诉我们的应用从哪里获取切片数据。URL 中的{s}、{z}、{x}和{y}占位符表示以下内容:
* {s}允许主域的一个子域为切片请求提供服务,使我们的应用程序能够同时发出多个请求,从而更快地下载切片。
* {s}允许主域的一个子域为切片请求提供服务,使我们的应用能够同时发出多个请求,从而更快地下载切片。
* {x}和{y}定义图块坐标。
* {z}代表缩放级别。
......@@ -263,12 +263,12 @@ TileLayer 对象的构造函数将一个 URL 作为其第一个参数,该 URL
恭喜你!您已经创建了您的第一张 Labber . js 地图,现在正式成为新地理学家。(关于你刚刚加入的俱乐部的更多信息,请参见[维基百科](https://en.wikipedia.org/wiki/Neogeography)。)
但是英国牛津可能不是一个对你来说很重要的地方。所以,作为一个练习,改变地图的范围来关注你的家乡。这需要知道你想要的范围的中心的纬度和经度。由于大多数人脑子里没有那种信息,我写了一个小助手应用程序,你可以在这里访问。只需找到您想要的范围,点击**获取地图代码**。当对话框出现时,复制它包含的代码,并使用它来替换应用程序中的映射构造函数代码。
但是英国牛津可能不是一个对你来说很重要的地方。所以,作为一个练习,改变地图的范围来关注你的家乡。这需要知道你想要的范围的中心的纬度和经度。由于大多数人脑子里没有那种信息,我写了一个小助手应用,你可以在这里访问。只需找到您想要的范围,点击**获取地图代码**。当对话框出现时,复制它包含的代码,并使用它来替换应用中的映射构造函数代码。
![](img/00008.jpeg)
图 5:使用范围查找器应用程序
图 5:使用范围查找器应用
| ![](img/00006.gif) | 注意:范围查找器应用程序精确到太多的小数位。你通常不需要那种准确度;纬度或经度坐标超过小数点后三位可能是多余的。 |
| ![](img/00006.gif) | 注意:范围查找器应用精确到太多的小数位。你通常不需要那种准确度;纬度或经度坐标超过小数点后三位可能是多余的。 |
在下一章中,我们将更详细地研究地图图层。
\ No newline at end of file
......@@ -10,7 +10,7 @@ Leaflet. js 区分了两种基本类型的地图图层:*基础图层*和*叠加
我们将在第三章讨论覆盖时讨论向量。现在,让我们看看一些不同类型的基础层,从上一章中看到的 L.TileLayer 开始。
这些图层由应用程序在用户关注地图的特定范围时请求的图像切片组成。在大比例下(用户放大到一个小的地理区域),有大量的瓦片,因为每平方英里有更多的细节要显示。在较小的比例下(用户缩小到一个广阔的地理区域),瓦片较少,因为每平方英里显示的细节较少。Leaflet.js 和切片图层提供程序根据您在 tile layer 构造函数中指定的 URL 计算特定范围需要显示哪些切片,该构造函数包含{x}、{y}和{z}占位符。这些占位符对应于切片服务用来定位特定切片的切片坐标和缩放级别。某些提供程序还接受{s}占位符,该占位符可用于在子域之间切换,因此可以并行下载切片以获得更好的性能。
这些图层由应用在用户关注地图的特定范围时请求的图像切片组成。在大比例下(用户放大到一个小的地理区域),有大量的瓦片,因为每平方英里有更多的细节要显示。在较小的比例下(用户缩小到一个广阔的地理区域),瓦片较少,因为每平方英里显示的细节较少。Leaflet.js 和切片图层提供程序根据您在 tile layer 构造函数中指定的 URL 计算特定范围需要显示哪些切片,该构造函数包含{x}、{y}和{z}占位符。这些占位符对应于切片服务用来定位特定切片的切片坐标和缩放级别。某些提供程序还接受{s}占位符,该占位符可用于在子域之间切换,因此可以并行下载切片以获得更好的性能。
接下来是一些更受欢迎的图块提供者的综述,以及您必须在 TileLayer 构造函数中使用的 URL。一些提供商将有限制带宽的使用策略。几乎所有这些都需要某种属性,您可以使用属性属性进行设置。这个属性几乎接受任何有效的 HTML,因此如果您愿意,您可以超链接回切片提供者的网站。有关具体的归属细节,请查看提供商的个人网站。
......@@ -92,7 +92,7 @@ Esri **:** 全球最大的地理信息系统公司。他们有一个非常高质
[**【cloud made】**](http://www.cloudmade.com/)[**MapBox**](http://www.mapbox.com/):这两家公司都提供瓷砖层。leaf 的创建者 Vladimir Agafonkin 现在为 MapBox 工作,leaf . js 框架是 MapBox 服务的核心部分。
在为应用程序寻找底图时,您可以考虑的另一个选项是 WMS(网络地图服务)图层。WMS 是一个公认的网络地图服务标准,由开放地理空间联盟定义。与我们目前看到的切片图层不同,WMS 影像是由地图服务器动态生成的,例如 ArcGIS Server、map server 或 GeoServer。地图服务器查询包含动态生成地图所需的所有数据的空间数据库,创建所需的图像,然后将它们发送到浏览器进行显示。以这种方式动态生成影像的好处(与使用预先创建的地图切片相反)包括不受创建切片时缩放级别的限制,能够选择在地图服务中显示哪些数据(图层),以及您可以请求透明图像。使用透明度可让您堆叠图层,而最上面的图层不会遮挡其下的图层。
在为应用寻找底图时,您可以考虑的另一个选项是 WMS(网络地图服务)图层。WMS 是一个公认的网络地图服务标准,由开放地理空间联盟定义。与我们目前看到的切片图层不同,WMS 影像是由地图服务器动态生成的,例如 ArcGIS Server、map server 或 GeoServer。地图服务器查询包含动态生成地图所需的所有数据的空间数据库,创建所需的图像,然后将它们发送到浏览器进行显示。以这种方式动态生成影像的好处(与使用预先创建的地图切片相反)包括不受创建切片时缩放级别的限制,能够选择在地图服务中显示哪些数据(图层),以及您可以请求透明图像。使用透明度可让您堆叠图层,而最上面的图层不会遮挡其下的图层。
作为一个行业标准,WMS 有很多服务,但不可否认的是,有些服务很难找到。这种方法令人兴奋的一点是,有了一点诀窍和免费可用的软件,如 QGIS(用于地图创建)、PostGIS(用于空间数据库)和 GeoServer(用作 WMS 服务器),您就可以创建自己的底图服务。所以,如果你曾经想在*权力的游戏*系列中创建维斯特洛的网络地图,那就尽情发挥吧!
......
# 三、添加覆盖
在最后一章中,我们对基础地图和叠加地图进行了区分。基础地图为构成应用程序基础的数据提供了一个“背景”,通常是以覆盖的形式。
在最后一章中,我们对基础地图和叠加地图进行了区分。基础地图为构成应用基础的数据提供了一个“背景”,通常是以覆盖的形式。
这些数据可以来自任何地方。您可以自己提供(例如,如果您经营一家自行车连锁店,并希望您的用户能够找到最近的一家),或者使用来自其他来源的数据(例如来自政府的人口统计数据或通过网络应用编程接口从远程服务器获得的数据,例如雅虎天气)。您甚至可能希望您的用户自己创建数据(例如,如果您正在构建一个应用程序,允许用户报告他们当地社区的涂鸦)。
这些数据可以来自任何地方。您可以自己提供(例如,如果您经营一家自行车连锁店,并希望您的用户能够找到最近的一家),或者使用来自其他来源的数据(例如来自政府的人口统计数据或通过网络应用编程接口从远程服务器获得的数据,例如雅虎天气)。您甚至可能希望您的用户自己创建数据(例如,如果您正在构建一个应用,允许用户报告他们当地社区的涂鸦)。
无论如何,您的应用程序数据很可能是点、线或多边形的形式。这些数据会在运行时动态呈现在地图上。Leaflet.js 提供了许多不同的类来帮助您实现这一点,在本章中,我们将深入探讨并开始使用一些更常见的类。
无论如何,您的应用数据很可能是点、线或多边形的形式。这些数据会在运行时动态呈现在地图上。Leaflet.js 提供了许多不同的类来帮助您实现这一点,在本章中,我们将深入探讨并开始使用一些更常见的类。
在地理信息系统术语中,点是最简单的空间类型,完全由其 x 和 y 坐标定义。Leaflet.js 有一个 Point 类,但它实际上只用于在屏幕中定义地图上的位置,而不是地图坐标。实例化点(x,y)的实例是指屏幕上的一个点:
......@@ -73,7 +73,7 @@ var pt = L 点(300,400);
默认情况下,地图标记的可点击属性为真,这意味着它可以响应鼠标事件,包括(但不限于)点击。
通过将可拖动属性设置为 true,您可以允许用户在地图上移动标记。这在某些用例中可能很方便,例如资产跟踪应用程序。但是为了真正有用,你需要弄清楚一个标记什么时候被移动了,移动到了哪里。
通过将可拖动属性设置为 true,您可以允许用户在地图上移动标记。这在某些用例中可能很方便,例如资产跟踪应用。但是为了真正有用,你需要弄清楚一个标记什么时候被移动了,移动到了哪里。
在第 4 章中,我们看一下地图和地图对象的事件,如标记。
......@@ -136,7 +136,7 @@ var pt = L 点(300,400);
图 13:地图上显示的多边形
某些多边形,如圆形和矩形,在网络地图应用程序中非常常见,通常表示地理边界,因此,Leaflet. js 提供了一些用于创建这些形状的实用程序类。不出所料,这就是 L.circle 类和 L.rectangle 类。
某些多边形,如圆形和矩形,在网络地图应用中非常常见,通常表示地理边界,因此,Leaflet. js 提供了一些用于创建这些形状的实用程序类。不出所料,这就是 L.circle 类和 L.rectangle 类。
L.rectangle 类是 L.polygon 的子类,因此您可以使用 L.polygon 的所有属性、方法和事件,以及*及其*父类 L.path 的属性、方法和事件
......@@ -450,7 +450,7 @@ L.rectangle 类是 L.polygon 的子类,因此您可以使用 L.polygon 的所
图 20:多多边形中的每个多边形显示相同的弹出窗口
因为试图在您的Leaflet. js 应用程序中发现您想要表示的位置和几何图形的坐标可能是一件痛苦的事情,所以我编写了一个简单的工具,您可以在这里访问。
因为试图在您的Leaflet. js 应用中发现您想要表示的位置和几何图形的坐标可能是一件痛苦的事情,所以我编写了一个简单的工具,您可以在这里访问。
要使用该工具,请放大到要创建要素的位置,然后使用地图左侧的绘制工具栏,并按照说明创建所需的几何图形。创建该几何图形的Leaflet. js 代码将出现在左侧窗格中。点击**复制到剪贴板**,代码就可以粘贴到您选择的编辑器或 IDE 中了。
......@@ -794,7 +794,7 @@ GeoJSON 是标准 JSON 的扩展,允许您描述几何图形。您可以使用
图 26:以美食为象征的外卖
有时在 GeoJSON 中过滤数据会很有用。也许 GeoJSON 来自外部来源,我们只对特定的特性感兴趣。我们甚至可能将这种能力扩展到我们的用户,并构建一个允许他们选择显示哪些功能的应用程序
有时在 GeoJSON 中过滤数据会很有用。也许 GeoJSON 来自外部来源,我们只对特定的特性感兴趣。我们甚至可能将这种能力扩展到我们的用户,并构建一个允许他们选择显示哪些功能的应用。
只需在 options 对象中使用 filter 属性,并给它一个函数,测试传递给它的值是否符合您的标准。返回 true 以显示要素,返回 false 以隐藏要素。在这个例子中,我们已经决定今晚不吃意大利菜(昨晚我们吃了很多披萨):
......
# 四、处理事件
现在,您有了一个包含地图和一些数据的应用程序,您通常会想要一种用户与之交互的方式。到目前为止,您启用的唯一交互是用户能够单击覆盖图中的功能,并看到您使用绑定到它的弹出窗口。bindPopup()方法。
现在,您有了一个包含地图和一些数据的应用,您通常会想要一种用户与之交互的方式。到目前为止,您启用的唯一交互是用户能够单击覆盖图中的功能,并看到您使用绑定到它的弹出窗口。bindPopup()方法。
当事情发生时,Leaflet. js 中的每个控件都会发出事件来提醒您的应用程序。例如,L.Map 类在编写时支持 34 个事件。这些事件的范围从您期望任何编程环境中的任何控件都具有的事件类型(如焦点、鼠标悬停和单击)到非常特定于它所提供的功能的事件类型(如重叠添加(当新的重叠添加到地图中时)和移动(当地图范围发生变化时))。
当事情发生时,Leaflet. js 中的每个控件都会发出事件来提醒您的应用。例如,L.Map 类在编写时支持 34 个事件。这些事件的范围从您期望任何编程环境中的任何控件都具有的事件类型(如焦点、鼠标悬停和单击)到非常特定于它所提供的功能的事件类型(如重叠添加(当新的重叠添加到地图中时)和移动(当地图范围发生变化时))。
此表列出了 L.Map 中支持的事件。它显示了事件的名称、事件触发时返回的对象以及描述。
......@@ -47,17 +47,17 @@
| 人口 | 弹出事件 | 当弹出窗口通过打开时。openPopup() |
| popupclose | 弹出事件 | 当弹出窗口通过关闭时。closePopup() |
这是Leaflet. js 中一个控件的事件列表(虽然可以说是最复杂的)。所有其他控件都发出自己的事件,这使得创建高度交互的 web 地图应用程序成为可能。
这是Leaflet. js 中一个控件的事件列表(虽然可以说是最复杂的)。所有其他控件都发出自己的事件,这使得创建高度交互的 web 地图应用成为可能。
在本章中,我们将使用地图控件的事件来演示Leaflet. js 中的事件处理。有关属于其他控件的事件的信息,请查看您感兴趣的控件的[Leaflet. js 文档](http://leafletjs.com/reference.html)
为了处理事件,您需要知道:
* 您希望应用程序开始注意到哪个事件
* 您希望应用开始注意到哪个事件
* 事件的名称
* 事件触发时返回的数据类型
让我们用一个例子来证明这一点。假设我们想要构建一个应用程序,允许用户点击地图,并在弹出窗口中显示他们点击的地图坐标。
让我们用一个例子来证明这一点。假设我们想要构建一个应用,允许用户点击地图,并在弹出窗口中显示他们点击的地图坐标。
查看表 1,我们可以看到我们想要监控的事件是地图的点击事件。为了开始捕获点击事件,我们需要为该事件创建一个事件处理程序。我们可以用地图做到这一点。on()方法,该方法将我们要处理的事件的名称(click)作为其第一个参数,并将响应该事件的函数(即*回调*)作为其第二个参数。
......@@ -87,13 +87,13 @@
```
如果您的代码是正确的并且没有语法错误,您可以启动应用程序并单击地图,您的处理程序应该会触发并显示一个消息框:
如果您的代码是正确的并且没有语法错误,您可以启动应用并单击地图,您的处理程序应该会触发并显示一个消息框:
![](img/00032.jpeg)
图 28:地图捕捉点击事件
如果您已经走了这么远,那么您知道您的应用程序正在监听地图点击事件。太好了。接下来要做的是捕获地图点击事件渴望传递给您的事件处理程序的信息,但这种信息目前被忽略了。
如果您已经走了这么远,那么您知道您的应用正在监听地图点击事件。太好了。接下来要做的是捕获地图点击事件渴望传递给您的事件处理程序的信息,但这种信息目前被忽略了。
为了处理事件数据,您需要知道正在返回什么类型的数据,然后调整回调函数来拦截和处理它。
......@@ -168,7 +168,7 @@
图 31:我们的“地理围栏”和标记
我们将使我们的标记可拖动,以便我们应用程序的用户可以在乡村移动它们。使标记可拖动就像将其可拖动属性设置为 true 一样简单。
我们将使我们的标记可拖动,以便我们应用的用户可以在乡村移动它们。使标记可拖动就像将其可拖动属性设置为 true 一样简单。
然后我们将连接两个事件处理程序来监控标记的 dragstart 和 dragend 事件。顾名思义,这些事件分别在用户开始和结束拖动标记时触发。
......
# 五、访问外部数据源
到目前为止,我们已经看到了如何通过将数据硬编码到我们的映射应用程序中来添加数据。如果你正在构建一些不完全琐碎的东西,那么这种方法是不会削减它的。没有人想为 10,000 个不同的位置创建标记代码!我们甚至没有讨论过用户可能想要通过您的应用程序更改数据的可能性。
到目前为止,我们已经看到了如何通过将数据硬编码到我们的映射应用中来添加数据。如果你正在构建一些不完全琐碎的东西,那么这种方法是不会削减它的。没有人想为 10,000 个不同的位置创建标记代码!我们甚至没有讨论过用户可能想要通过您的应用更改数据的可能性。
值得庆幸的是,有许多不同的方法可以将数据输入到您的Leaflet. js 应用程序中。在这一章中,我们将讨论一些您可以使用的最流行的技术。
值得庆幸的是,有许多不同的方法可以将数据输入到您的Leaflet. js 应用中。在这一章中,我们将讨论一些您可以使用的最流行的技术。
数据库是存储任何描述的数据的平台,所以让我们考虑如何使用空间组件来存储和检索数据,以便在网络地图中使用。
我们一直在创建运行在浏览器上的客户端应用程序。基于浏览器的应用程序通常不会直接访问数据库数据。它们要么涉及一些服务器端代码,要么涉及某种中间件——通常是某种描述的 web 服务——它访问数据库并使其对页面可用。
我们一直在创建运行在浏览器上的客户端应用。基于浏览器的应用通常不会直接访问数据库数据。它们要么涉及一些服务器端代码,要么涉及某种中间件——通常是某种描述的 web 服务——它访问数据库并使其对页面可用。
构建数据库驱动的 web 应用程序最常见的方法之一是使用 PHP 作为服务器端脚本,使用 MySQL 作为后端数据库。两者都已经存在很长时间了,并且是免费提供的,所以即使有更新、更好的平台,我们还是会坚持用 PHP 和 MySQL 作为第一个例子。
构建数据库驱动的 web 应用最常见的方法之一是使用 PHP 作为服务器端脚本,使用 MySQL 作为后端数据库。两者都已经存在很长时间了,并且是免费提供的,所以即使有更新、更好的平台,我们还是会坚持用 PHP 和 MySQL 作为第一个例子。
你可以直接从甲骨文网站下载 MySQL,或者像我一样,用一个“更友好”的包来为你安装和配置。这些程序与某种管理图形用户界面捆绑在一起,管理图形用户界面捆绑了 LAMP 堆栈的安装(Linux、Apache、MySQL 和 PHP)。虽然 Linux 是托管网络服务器的流行选择,但出于开发目的,您通常希望安装一个 Windows 或 Mac 专用的 LAMP 堆栈。正如我在第一章中提到的,我用 XAMPP 做这个。您需要确保 MySQL 服务正在运行。
......@@ -18,7 +18,7 @@
图 39:显示 MySQL 服务运行的 XAMPP 控制面板
现在我已经有了一个正在运行的数据库服务器,我需要创建一个数据库,并用一些数据填充它,然后我可以在我的Leaflet. js 应用程序中使用这些数据。XAMPP 将一个名为 myPhpAdmin 的图形用户界面捆绑到 MySQL 中,但是我喜欢在命令行上工作,所以我将在这里演示这一点。
现在我已经有了一个正在运行的数据库服务器,我需要创建一个数据库,并用一些数据填充它,然后我可以在我的Leaflet. js 应用中使用这些数据。XAMPP 将一个名为 myPhpAdmin 的图形用户界面捆绑到 MySQL 中,但是我喜欢在命令行上工作,所以我将在这里演示这一点。
首先,我需要登录 MySQL 服务器。我可以通过 XAMPP 控制面板中的 Shell 按钮来实现这一点,或者我可以将 MySQL 二进制文件添加到我的 PATH 中,并从标准终端访问它。XAMPP 为 MySQL 配置了一个根帐户,但是没有密码,所以让我们给根用户一个**传单**的密码。
......@@ -71,7 +71,7 @@
```
那是事物的数据库端;现在,我们需要一些服务器端代码来访问数据库,并以适合客户端应用程序阅读的格式返回结果。我将用 PHP 编写代码,使用 PHP 数据对象(PDO)来处理与数据库的交互。这个代码要么非常简单,要么非常迟钝,这取决于你是否了解 PHP。
那是事物的数据库端;现在,我们需要一些服务器端代码来访问数据库,并以适合客户端应用阅读的格式返回结果。我将用 PHP 编写代码,使用 PHP 数据对象(PDO)来处理与数据库的交互。这个代码要么非常简单,要么非常迟钝,这取决于你是否了解 PHP。
下面是我保存在一个名为 coffee.php 的文件中的代码,这个文件位于我用来创建显示地图的 HTML 页面的目录中。
......@@ -129,13 +129,13 @@
打印 json_encode `(` `$rows` `);`
这一行代码打印了 JSON 中的整个记录集。JSON 是一种轻量级的数据交换格式,非常适合我们的客户端应用程序处理。如果您在浏览器中启动 coffee.php 文件,您将看到如下内容:
这一行代码打印了 JSON 中的整个记录集。JSON 是一种轻量级的数据交换格式,非常适合我们的客户端应用处理。如果您在浏览器中启动 coffee.php 文件,您将看到如下内容:
![](img/00044.jpeg)
图 40:JSON 格式的数据库数据
对你来说,这可能看起来像一堆乱七八糟的废话。尽管 JSON 本身是一种公认的数据交换格式,但它的根在 JavaScript 中,它是用于创建 JavaScript 对象文字的语法。是的,这个东西只是一个很大的 JavaScript 对象,这使得引入我们的客户端应用程序变得微不足道。
对你来说,这可能看起来像一堆乱七八糟的废话。尽管 JSON 本身是一种公认的数据交换格式,但它的根在 JavaScript 中,它是用于创建 JavaScript 对象文字的语法。是的,这个东西只是一个很大的 JavaScript 对象,这使得引入我们的客户端应用变得微不足道。
执行从数据库中获取结果集并将其转换为可以流式传输到我们的网页中的 JSON 的神奇的 PHP 代码行是这样的:
......@@ -153,9 +153,9 @@
为了访问 JQuery,您必须在页面中的
这是我们客户端应用程序的起始代码。我已经突出显示了引用 JQuery CDN 的
这是我们客户端应用的起始代码。我已经突出显示了引用 JQuery CDN 的
代码清单 42:客户端应用程序,通过 CDN 引用 JQuery 框架
代码清单 42:客户端应用,通过 CDN 引用 JQuery 框架
```js
<!DOCTYPE html>
......@@ -206,7 +206,7 @@
```
*代码清单 43* 中的代码可以看出,我们已经用 OSM Mapnik 基础层构建了一个非常简单的映射应用程序。init()函数创建地图,添加图层,然后调用 showCoffeeShops()函数,这就是我们接下来要关注的地方。
*代码清单 43* 中的代码可以看出,我们已经用 OSM Mapnik 基础层构建了一个非常简单的映射应用。init()函数创建地图,添加图层,然后调用 showCoffeeShops()函数,这就是我们接下来要关注的地方。
代码清单 43:完整的 showCoffeeShops()函数
......@@ -317,17 +317,17 @@ var`visits``=``data``[``i``].``Visits``;`
![](img/00046.jpeg)
图 41:完成的应用程序
图 41:完成的应用
我们获取数据的另一种方法是使用第三方应用编程接口。这种技术被酷孩子称为创建“混搭”
您可以免费或通过付费订阅访问的 API 数量惊人:只需查看[这个网站](http://www.programmableweb.com/)获取灵感。其中许多提供了位置数据,而对于那些没有提供位置数据的人(比如推特应用编程接口),用地名对任何内容进行地理编码都非常容易。我们将在第 6 章中了解地理编码。
现在,让我们使用一个可以存储位置数据的应用编程接口,其中一个应用编程接口是 Flickr 照片搜索。本练习的任务是创建一个以英国伦敦市为中心的应用程序,并显示任何被地理标记为在那里拍摄的 Flickr 照片。
现在,让我们使用一个可以存储位置数据的应用编程接口,其中一个应用编程接口是 Flickr 照片搜索。本练习的任务是创建一个以英国伦敦市为中心的应用,并显示任何被地理标记为在那里拍摄的 Flickr 照片。
为了访问 Flickr 照片搜索应用编程接口,我们首先需要指定我们希望应用编程接口返回给我们什么样的信息。一旦我们做到了这一点,我们就获得了一个由各种查询参数组成的网址,这些参数指定了我们的应用程序将向 Flickr 服务发出的请求。
为了访问 Flickr 照片搜索应用编程接口,我们首先需要指定我们希望应用编程接口返回给我们什么样的信息。一旦我们做到了这一点,我们就获得了一个由各种查询参数组成的网址,这些参数指定了我们的应用将向 Flickr 服务发出的请求。
首先,访问 [Flickr API 应用程序花园](https://www.flickr.com/services/api/)页面,了解一下仅从这个供应商那里就可以获得的大量 API。然后,点击[T3T5 链接。](https://www.flickr.com/services/api/explore/flickr.photos.search)
首先,访问 [Flickr API 应用花园](https://www.flickr.com/services/api/)页面,了解一下仅从这个供应商那里就可以获得的大量 API。然后,点击[T3T5 链接。](https://www.flickr.com/services/api/explore/flickr.photos.search)
这将带您进入一个带有表单的页面,您需要在其中指定您希望 Flick Photo Search API 返回给您的信息。在表格中输入以下内容:
......@@ -337,13 +337,13 @@ var`visits``=``data``[``i``].``Visits``;`
* 最后,将页面底部的输出选项设置为 JSON。我们喜欢 JSON。
* 不要管其他的选择。
输入所有信息后,点击**调用方法……**按钮。如果一切正常,您应该会看到一个示例输出,在它下面,有一个看起来很吓人的自定义网址,您需要将其粘贴到我们即将构建的应用程序中。
输入所有信息后,点击**调用方法……**按钮。如果一切正常,您应该会看到一个示例输出,在它下面,有一个看起来很吓人的自定义网址,您需要将其粘贴到我们即将构建的应用中。
![Figure 42: Successful configuration of the Flickr Photo Search API ](img/00047.gif) ![](img/00048.jpeg)
这就是我们的出发点。我们有一个以伦敦为中心的地图,以 OSM·马普尼克为基础图层,我们正在调用一个名为 showPhotos()的函数,我们将在这里施展我们的 Flickr 魔法。
代码清单 44:我们的 Flickr API 应用程序的起点
代码清单 44:我们的 Flickr API 应用的起点
```js
<!DOCTYPE html>
......@@ -485,7 +485,7 @@ var`visits``=``data``[``i``].``Visits``;`
一旦我们实例化了 L.LayerJSON 对象,我们就可以使用 map.addLayer(jsonLayer)以正常方式将它添加到我们的地图中。
让我们运行应用程序并点击几个标记。请注意,这是一个实时提要,因此您的结果可能与我的结果有很大不同:
让我们运行应用并点击几个标记。请注意,这是一个实时提要,因此您的结果可能与我的结果有很大不同:
![](img/00051.jpeg)
......@@ -513,15 +513,15 @@ var`visits``=``data``[``i``].``Visits``;`
![](img/00053.jpeg)
图 46:最终的 Flickr 照片搜索 API 应用程序
图 46:最终的 Flickr 照片搜索 API 应用
我相信您已经开始意识到,有许多不同的方法可以将数据输入到您的Leaflet. js 应用程序中。但让我们再考虑一个。
我相信您已经开始意识到,有许多不同的方法可以将数据输入到您的Leaflet. js 应用中。但让我们再考虑一个。
KML 代表钥匙孔标记语言。全名对任何人来说都没什么意义了,但首字母缩略词确实有意义。这是一种基于 XML 的地理数据表示格式,谷歌已经在谷歌地球和谷歌地图应用程序中广泛使用,现在在其他地方也有相当多的追随者。KML 现已被公认为开放地理空间联盟的官方国际标准,该组织对我们如何存储和共享地理数据非常感兴趣。
KML 代表钥匙孔标记语言。全名对任何人来说都没什么意义了,但首字母缩略词确实有意义。这是一种基于 XML 的地理数据表示格式,谷歌已经在谷歌地球和谷歌地图应用中广泛使用,现在在其他地方也有相当多的追随者。KML 现已被公认为开放地理空间联盟的官方国际标准,该组织对我们如何存储和共享地理数据非常感兴趣。
锁眼钻头呢?这只是谷歌地球在 2004 年被谷歌收购锁眼公司之前的遗留问题。
无论如何,KML 很酷,因为你可以用它来表示二维或三维的任何地理数据。外面有一大堆,等着你去吸收你的 Leaflet.js 映射应用程序。只需在谷歌上搜索文件类型:kml,你就会发现很多——这就是我如何找到[美国地质勘探局地震谷歌地球/KML 文件页面](http://earthquake.usgs.gov/learn/kml.php)的。让我们在一个应用程序中使用他们的实时 KML 地震提要。
无论如何,KML 很酷,因为你可以用它来表示二维或三维的任何地理数据。外面有一大堆,等着你去吸收你的 Leaflet.js 映射应用。只需在谷歌上搜索文件类型:kml,你就会发现很多——这就是我如何找到[美国地质勘探局地震谷歌地球/KML 文件页面](http://earthquake.usgs.gov/learn/kml.php)的。让我们在一个应用中使用他们的实时 KML 地震提要。
![](img/00054.jpeg)
......@@ -539,7 +539,7 @@ KML 代表钥匙孔标记语言。全名对任何人来说都没什么意义了
通过快速跳转到 GitHub,我可以下载最新版本的 zip 文件,提取传单-omnivore.min.js,并将其放入我的 js 目录中,就像我们在 MySQL 示例中所做的那样。传单-杂食者的工作方式是下载 KML 数据,并将其格式化为传单 GeoJSON 层。
在 GitHub 页面上阅读一下,我就能获得创建应用程序所需的所有信息。这是密码。
在 GitHub 页面上阅读一下,我就能获得创建应用所需的所有信息。这是密码。
代码清单 47:用散页杂食插件加载 KML 数据
......
......@@ -30,7 +30,7 @@
创建地图后,将其范围设置为美国,并添加 OpenStreetmap 底图图层,这是我们的起点:
代码清单 48:地理编码应用程序的起点
代码清单 48:地理编码应用的起点
```js
<!DOCTYPE html>
......@@ -97,7 +97,7 @@
```
就这样!现在,当我们运行应用程序时,我们会在页面顶部看到一个不错的文本输入字段。我们可以输入一个地方的名称,或者地址的一部分,根据提供者数据的质量,得到或多或少有用的结果。
就这样!现在,当我们运行应用时,我们会在页面顶部看到一个不错的文本输入字段。我们可以输入一个地方的名称,或者地址的一部分,根据提供者数据的质量,得到或多或少有用的结果。
让我们尝试搜索谷歌在加州山景城的总部:
......
......@@ -4,7 +4,7 @@
通过保持Leaflet. js 的核心小并通过插件扩展其功能,该 API 是一种愉快的工作方式,并且没有损害其一些竞争对手的努力的膨胀。事情只是按照你期望的方式运行,这在这个领域是不寻常的。许多地图应用编程接口是由地理学家创建的,他们倾向于在他们的应用编程接口中使用对普通人来说意义不大的特性和术语。传单的创造者弗拉基米尔·阿加丰金(Vladimir Agafonkin)首先是一名网络开发人员——这表明了这一点,因为他已经建立了一个其他网络开发人员可以与之相关的应用编程接口。
在这本书里,我们介绍了大部分的核心 API,甚至还看了一些插件。如果你想大大扩展你的网络地图应用程序的功能,那么你应该看看插件的种类。传单. js 上的官方插件页面列出了很多,几乎涵盖了你能想象到的所有功能。
在这本书里,我们介绍了大部分的核心 API,甚至还看了一些插件。如果你想大大扩展你的网络地图应用的功能,那么你应该看看插件的种类。传单. js 上的官方插件页面列出了很多,几乎涵盖了你能想象到的所有功能。
![](img/00066.jpeg)
......
......@@ -2,16 +2,16 @@
![](img/image109.png)编者按:为了确保所有设备的语法高亮显示正确,示例代码列表已作为图像发布。要访问可以复制和粘贴的文本代码块,只需单击代码列表图像后的链接。本书的附录部分提供了所有代码清单。
本电子书的目标是通过指导您构建 CRM 示例应用程序的过程,教您如何使用 Visual Studio LightSwitch 构建面向移动的单页应用程序(SPA)。
本电子书的目标是通过指导您构建 CRM 示例应用的过程,教您如何使用 Visual Studio LightSwitch 构建面向移动的单页应用(SPA)。
![](img/image001.jpg)
图 1:移动业务应用程序
图 1:移动业务应用
这个应用程序是一个 HTML5 单页应用程序,目标是智能手机和平板电脑,创建它需要 LightSwitch 开发人员很短的时间。
这个应用是一个 HTML5 单页应用,目标是智能手机和平板电脑,创建它需要 LightSwitch 开发人员很短的时间。
这本书从一个非常简单的 hello world 应用程序开始。在学习了一些理论和 LightSwitch 词汇表 101 之后,您会发现几个实践章节,每个章节都更深入地描述了 LightSwitch 移动业务应用程序的不同方面:数据库项目、调整应用程序的视觉方面、编程模型和技术以及全局样式。最后,您将把应用程序部署到云中,我将通过提供一些指向其他学习内容的链接来结束本教程。
这本书从一个非常简单的 hello world 应用开始。在学习了一些理论和 LightSwitch 词汇表 101 之后,您会发现几个实践章节,每个章节都更深入地描述了 LightSwitch 移动业务应用的不同方面:数据库项目、调整应用的视觉方面、编程模型和技术以及全局样式。最后,您将把应用部署到云中,我将通过提供一些指向其他学习内容的链接来结束本教程。
我写这本书时考虑到了一个特殊的读者群:一个对一些一般性的技术术语很熟悉,但对特定的移动和 HTML 技术不太熟悉的读者。如果你是专家,请随意以更快的速度通读这本书。我相信 LightSwitch 快速应用程序开发方法仍然会很有趣和吸引人。
我写这本书时考虑到了一个特殊的读者群:一个对一些一般性的技术术语很熟悉,但对特定的移动和 HTML 技术不太熟悉的读者。如果你是专家,请随意以更快的速度通读这本书。我相信 LightSwitch 快速应用开发方法仍然会很有趣和吸引人。
如果你不熟悉 LightSwitch 的开发经验,不妨先简单阅读一下[*【LightSwitch】*](http://www.syncfusion.com/resources/techportal/ebooks/lightswitch)这本书,它以较慢的速度解释了 light switch 的基本概念,然后你应该继续阅读这本书,这本书专门涉猎移动应用。
\ No newline at end of file
# 第 1 章创建示例应用程序
# 第 1 章创建示例应用
如果你在这一章或这本书的任何部分遇到困难,可以从[bitbucket . org/syncfusiontech/light switch-mobile-business-apps-简洁地下载一个完整的 Visual Studio 2013 示例应用程序](https://bitbucket.org/syncfusiontech/lightswitch-mobile-business-apps-succinctly)
如果你在这一章或这本书的任何部分遇到困难,可以从[bitbucket . org/syncfusiontech/light switch-mobile-business-apps-简洁地下载一个完整的 Visual Studio 2013 示例应用。](https://bitbucket.org/syncfusiontech/lightswitch-mobile-business-apps-succinctly)
LightSwitch 移动商务应用程序在安装了 SP3 的 Visual Studio 2012 Professional 或更高版本中可用。
LightSwitch 移动商务应用在安装了 SP3 的 Visual Studio 2012 Professional 或更高版本中可用。
## 开始
要创建 hello world 示例应用程序,可以从“文件”>“新建项目”开始。
要创建 hello world 示例应用,可以从“文件”>“新建项目”开始。
您正在寻找的项目类型是一个光开关 HTML 应用程序,在光开关模板文件夹下。我选择 C#版本。
您正在寻找的项目类型是一个光开关 HTML 应用,在光开关模板文件夹下。我选择 C#版本。
![](img/image002.jpg)
......@@ -26,7 +26,7 @@ LightSwitch 移动商务应用程序在安装了 SP3 的 Visual Studio 2012 Prof
图 4:灯光开关主屏幕
LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开始。对于这个示例应用程序,我们将创建一个客户实体。
LightSwitch 主屏幕自动打开。如屏幕所示,应用从数据开始。对于这个示例应用,我们将创建一个客户实体。
要添加客户实体,请在主屏幕中单击**创建新表**,或者在解决方案资源管理器中右键单击服务器项目并选择**添加表**
......@@ -44,7 +44,7 @@ LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开
您还可以使用属性窗口中的属性来更改或添加简单的验证,如设置最小值和最大值,甚至将字段限制为严格的选择列表。
这在实际应用程序中是不够的,您需要自定义初始化、验证或授权,您可以从服务器或任何客户端的角度通过单击**编写代码**来添加这些内容。
这在实际应用中是不够的,您需要自定义初始化、验证或授权,您可以从服务器或任何客户端的角度通过单击**编写代码**来添加这些内容。
![](img/image006.jpg)
......@@ -54,7 +54,7 @@ LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开
## 创建屏幕
要完成 hello-world 应用程序,您需要创建几个屏幕。
要完成 hello-world 应用,您需要创建几个屏幕。
右键单击客户端项目,从上下文菜单中选择**添加屏幕**
......@@ -80,7 +80,7 @@ LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开
图 9:添加按钮向导
打开的添加按钮向导为您提供了编写自定义方法或选择现有方法的选项。现有的方法组合框显示了几个导航选项和几个可以对客户集合执行的操作。随着应用程序的增长和屏幕变得更加复杂,该组合框中现有方法的数量将会增加。现在,您可以将新的“添加”按钮绑定到新客户,并显示一个屏幕,通过选择“客户.添加和编辑新客户”方法来编辑该客户。
打开的添加按钮向导为您提供了编写自定义方法或选择现有方法的选项。现有的方法组合框显示了几个导航选项和几个可以对客户集合执行的操作。随着应用的增长和屏幕变得更加复杂,该组合框中现有方法的数量将会增加。现在,您可以将新的“添加”按钮绑定到新客户,并显示一个屏幕,通过选择“客户.添加和编辑新客户”方法来编辑该客户。
![](img/image010.png)
......@@ -94,7 +94,7 @@ LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开
单击**确定**将打开添加新屏幕向导,帮助生成您的详细屏幕。
接受该向导后,您的应用程序中将有两个屏幕:所有客户概览屏幕(浏览客户)和客户详细信息屏幕(客户)。应用程序中的第一个概览屏幕将是主屏幕。当应用程序启动时,它会自动打开。
接受该向导后,您的应用中将有两个屏幕:所有客户概览屏幕(浏览客户)和客户详细信息屏幕(客户)。应用中的第一个概览屏幕将是主屏幕。当应用启动时,它会自动打开。
既然您有了创建客户的详细屏幕,为什么不重用该屏幕来编辑客户呢?为此,您必须绑定列表上的 tab 手势(当最终用户点击或点击列表中的某个项目时会发生这种情况)来打开详细信息屏幕。
......@@ -118,13 +118,13 @@ LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开
## 探索应用
按 Ctrl+F5 构建并运行应用程序
按 Ctrl+F5 构建并运行应用。
您首先创建的浏览客户屏幕将自动打开。因为数据库中没有客户,所以它会相当空。
![](img/image015.jpg)
图 15:一个空的但功能齐全的应用程序
图 15:一个空的但功能齐全的应用
点击命令栏中的添加客户按钮(灰色页脚)会将新客户添加到列表中,并以模式对话框的形式打开添加编辑客户屏幕。
......@@ -132,7 +132,7 @@ LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开
图 16。添加编辑客户
当您继续填写第一个客户的详细信息时,您会注意到应用程序是如何尊重您在实体设计器中对客户实体建模的方式的。每个属性的适当业务类型将用于推断可视化特定字段的最佳方式。
当您继续填写第一个客户的详细信息时,您会注意到应用是如何尊重您在实体设计器中对客户实体建模的方式的。每个属性的适当业务类型将用于推断可视化特定字段的最佳方式。
![](img/image017.png)
......@@ -142,17 +142,17 @@ LightSwitch 主屏幕自动打开。如屏幕所示,应用程序从数据开
### 一些科技话题
恭喜你,你刚刚创建了一个只有半杯咖啡价值的全功能应用程序。我相信这个应用看起来不错,我很高兴地报告它也是技术杰作。
恭喜你,你刚刚创建了一个只有半杯咖啡价值的全功能应用。我相信这个应用看起来不错,我很高兴地报告它也是技术杰作。
乍看之下,您可能会错过的技术细节之一是响应性设计。让浏览器变得越来越小,你会注意到应用程序是如何仔细选择哪些元素要调整大小,哪些要保持固定大小,以便为最重要的内容保留尽可能多的屏幕空间。如果你把浏览器做得很小,你会注意到应用程序是如何将列数从两列减少到一列,以避免像智能手机这样的较小外形的布局混乱。
乍看之下,您可能会错过的技术细节之一是响应性设计。让浏览器变得越来越小,你会注意到应用是如何仔细选择哪些元素要调整大小,哪些要保持固定大小,以便为最重要的内容保留尽可能多的屏幕空间。如果你把浏览器做得很小,你会注意到应用是如何将列数从两列减少到一列,以避免像智能手机这样的较小外形的布局混乱。
![](img/image018.png)
图 18:布局被更新以适应设备的屏幕尺寸。
项目经理海因里希·温德尔发布了一篇文章,解释了团队设想的为多种外形设计适应性设计应用程序的策略,您可以在[http://blogs . msdn . com/b/light switch/archive/2013/03/12/design-for-multi-form-factors . aspx](http://blogs.msdn.com/b/lightswitch/archive/2013/03/12/designing-for-multiple-form-factors.aspx)上找到。
项目经理海因里希·温德尔发布了一篇文章,解释了团队设想的为多种外形设计适应性设计应用的策略,您可以在[http://blogs . msdn . com/b/light switch/archive/2013/03/12/design-for-multi-form-factors . aspx](http://blogs.msdn.com/b/lightswitch/archive/2013/03/12/designing-for-multiple-form-factors.aspx)上找到。
关于应用程序的第二个技术细节是它的内置分页机制,乍一看您可能会错过,尤其是在数据库中只有一条记录的情况下。
关于应用的第二个技术细节是它的内置分页机制,乍一看您可能会错过,尤其是在数据库中只有一条记录的情况下。
LightSwitch 通过实现 OData 协议的数据服务向 HTML 客户端公开服务层。OData 是一个开放标准,其中心是使用 HTTP 动词(GET、POST 等)和一个 URI 来识别资源,结合固定数量的操作符来请求过滤、排序、转换等。
......@@ -162,10 +162,10 @@ OData 协议、示例和生态系统可以在[http://OData.org](http://odata.org
![](img/image019.jpg)
图 19:应用程序对数据进行分页。
图 19:应用对数据进行分页。
如果记录超过 45 条,当用户向下滚动或滑动时,将异步获取下一批 45 条记录。
为了获得最佳性能,筛选由 SQL Server 完成,可以从屏幕设计器的属性窗口中关闭或自定义(不同的页面大小)。
请随意使用该应用程序,但不要过于依赖您创建的客户,因为我们很快将使用 SQL 脚本用示例数据替换他们。在下一节中,您将了解 LightSwitch 开发的高级概念。
\ No newline at end of file
请随意使用该应用,但不要过于依赖您创建的客户,因为我们很快将使用 SQL 脚本用示例数据替换他们。在下一节中,您将了解 LightSwitch 开发的高级概念。
\ No newline at end of file
......@@ -4,15 +4,15 @@
LightSwitch 没有一个官方的定义,由于它自第一次发布以来已经发展了很多,并且它可以帮助应对广泛的软件开发挑战,所以定义它并不是一件容易的事情。
就本电子书而言,LightSwitch 是框架和集成工具的结合,有助于专业开发人员在快速发布周期中构建高度专业化的 LOB 应用程序(独立的或作为更大生态系统的一部分)。它不需要在互操作性或灵活性上妥协,而是强制实施业经验证的标准和模式,并促进可扩展的架构设计。
就本电子书而言,LightSwitch 是框架和集成工具的结合,有助于专业开发人员在快速发布周期中构建高度专业化的 LOB 应用(独立的或作为更大生态系统的一部分)。它不需要在互操作性或灵活性上妥协,而是强制实施业经验证的标准和模式,并促进可扩展的架构设计。
## 什么是 LOB 应用?
业务线(LOB)应用程序是为特定公司私人使用而编写的应用程序。据估计,目前编写的所有软件中,大约 90%是 LOB 应用程序。每个业务线应用程序对于业务流程、公司文化和使用它的地理位置都是独特的。然而,有一些共同的标准。
业务线(LOB)应用是为特定公司私人使用而编写的应用。据估计,目前编写的所有软件中,大约 90%是 LOB 应用。每个业务线应用对于业务流程、公司文化和使用它的地理位置都是独特的。然而,有一些共同的标准。
大多数业务线应用程序在特定领域的软件结构中模拟真实世界,这种软件结构被恰当地称为模型。LightSwitch 开发人员将这些模型称为**实体**。需要存储实体,以便它们可以在运行之间重用,在不同的最终用户之间共享,甚至在不同的应用程序之间交换。一些业务线应用程序有一组非常独特的数据,可以存储在一个称为**内在数据源**的数据存储中,这是应用程序独有的。但是,业务线应用程序通常是更大的生态系统的一部分,并且会重用已经存在的数据源。
大多数业务线应用在特定领域的软件结构中模拟真实世界,这种软件结构被恰当地称为模型。LightSwitch 开发人员将这些模型称为**实体**。需要存储实体,以便它们可以在运行之间重用,在不同的最终用户之间共享,甚至在不同的应用之间交换。一些业务线应用有一组非常独特的数据,可以存储在一个称为**内在数据源**的数据存储中,这是应用独有的。但是,业务线应用通常是更大的生态系统的一部分,并且会重用已经存在的数据源。
**数据源**不一定指数据库。实体可以存储在各种来源中并从中检索:新的或现有的数据库(来自另一个活动的或旧的业务线应用程序)、网络服务(如 SharePoint 列表、TFS 工作项、其他业务线应用程序和第三方来源)甚至网络共享上的文件。
**数据源**不一定指数据库。实体可以存储在各种来源中并从中检索:新的或现有的数据库(来自另一个活动的或旧的业务线应用)、网络服务(如 SharePoint 列表、TFS 工作项、其他业务线应用和第三方来源)甚至网络共享上的文件。
实体代表现实生活中的对象(或其一部分)。它们不仅仅是数据结构,而是封装业务逻辑的智能二进制创作。某些业务逻辑对于实体或特定属性来说是唯一的,而其他逻辑在特定业务中甚至在一般情况下可能非常常见。LightSwitch 将这种常见的逻辑称为**业务类型**。业务类型是数据存储类型(字符串、int、二进制等)的超集。)具有一组独特的业务逻辑和验证规则,如货币、电子邮件地址和电话号码。
......@@ -22,21 +22,21 @@ LightSwitch 没有一个官方的定义,由于它自第一次发布以来已
在可能的情况下实施这些关系是最佳实践,但这在数据源中并不总是可能的。此外,根据业务,两个实体可能有关系,而不管它们是否保存在不同的、隔离的数据存储中。
几乎所有业务线应用程序都是为多用户目的而设计的。这意味着软件不能是一台个人电脑上的一整块字节,而是应该按照可重用性进行垂直切片,按照部署位置进行水平切片。这些水平切片的块通常称为层。多用户业务线应用程序通常由数据层、逻辑层和表示层组成。在 LightSwitch 开发人员的词汇中,这种多层架构中的这三种类型的层被称为**数据源****中间层、****客户端**。实体将真正存在于所有不同的层中。理想情况下,它们的业务逻辑和它们的关系也在每一层上执行,增加了层的**自治**的方式,从而增加了层的整体**可重用性**
几乎所有业务线应用都是为多用户目的而设计的。这意味着软件不能是一台个人电脑上的一整块字节,而是应该按照可重用性进行垂直切片,按照部署位置进行水平切片。这些水平切片的块通常称为层。多用户业务线应用通常由数据层、逻辑层和表示层组成。在 LightSwitch 开发人员的词汇中,这种多层架构中的这三种类型的层被称为**数据源****中间层、****客户端**。实体将真正存在于所有不同的层中。理想情况下,它们的业务逻辑和它们的关系也在每一层上执行,增加了层的**自治**的方式,从而增加了层的整体**可重用性**
每一层都是根据特定的架构或库**设计模式**在内部构建的。例如,客户端层可以根据**模型-视图-视图模型(MVVM)** 模式构建,其中视图模型层准备模型和可重用命令,以便于表示层(视图)使用。LOB 应用程序的最终用户通常是非技术熟练的人,他们用特定的业务术语思考他们的工作。优秀的 LOB 应用程序开发人员会理解这一点,并且不会将最终用户限制为只使用 CRUD 命令(创建、读取、更新和删除)或只显示网格中的所有数据。*(顺便说一下,我有恐女生症。)*优秀的 LOB 应用程序开发人员将了解应用程序的具体用途,并根据特定的业务流程和特定的终端使用排版、颜色、自定义布局和专门的控件。
每一层都是根据特定的架构或库**设计模式**在内部构建的。例如,客户端层可以根据**模型-视图-视图模型(MVVM)** 模式构建,其中视图模型层准备模型和可重用命令,以便于表示层(视图)使用。LOB 应用的最终用户通常是非技术熟练的人,他们用特定的业务术语思考他们的工作。优秀的 LOB 应用开发人员会理解这一点,并且不会将最终用户限制为只使用 CRUD 命令(创建、读取、更新和删除)或只显示网格中的所有数据。*(顺便说一下,我有恐女生症。)*优秀的 LOB 应用开发人员将了解应用的具体用途,并根据特定的业务流程和特定的终端使用排版、颜色、自定义布局和专门的控件。
这还包括**自适应设计**(布局或控件根据设备的类型或屏幕因素而变化),利用设备特定的功能或支持语音或触摸手势(如果适用),以及在某些情况下支持多种语言。
最后,当开发人员完成新特性时,代码被推送到源代码管理,如果需要的话进行编译,然后部署。发布周期最好尽可能短,这样反馈可以尽早且经常地被纳入。一个好的**部署模型**应该是**高度自动化的**以免减缓发布周期。
最终用户然后安装应用程序(或者简单地浏览到 web 应用程序),并开始使用他们可以访问的内容。存在大量已知的**认证**和有时复杂的**授权**模型,以确保数据和业务流程仅被授予具有适当授权的用户。
最终用户然后安装应用(或者简单地浏览到 web 应用),并开始使用他们可以访问的内容。存在大量已知的**认证**和有时复杂的**授权**模型,以确保数据和业务流程仅被授予具有适当授权的用户。
## 光开关 IDE
LightSwitch IDE 主要利用专门的设计人员来设计实体、查询和屏幕。这些设计者抽象了技术方面,消除了许多繁琐的工作,让你作为一个专业的开发人员最初只关注业务方面。
如果像上一章一样启动应用程序,实体设计器将自动打开:右键单击服务器项目的数据源文件夹,然后选择添加表。
如果像上一章一样启动应用,实体设计器将自动打开:右键单击服务器项目的数据源文件夹,然后选择添加表。
![](img/image020.png)
......@@ -48,7 +48,7 @@ LightSwitch IDE 主要利用专门的设计人员来设计实体、查询和屏
图 21:内在数据源
该数据源将生成一个相关的内部数据库,即 SQL Server 或 SQL Azure 数据库,该数据库将保存特定于您的应用程序的所有实体(**内部数据源**)。
该数据源将生成一个相关的内部数据库,即 SQL Server 或 SQL Azure 数据库,该数据库将保存特定于您的应用的所有实体(**内部数据源**)。
LightSwitch 还有连接现有数据源(**数据源**)的选项。从同一上下文菜单中选择“添加数据源”选项将打开一个向导,帮助您连接到各种选项。
......@@ -58,11 +58,11 @@ LightSwitch 还有连接现有数据源(**数据源**)的选项。从同一上
数据库允许您连接到任何现有的数据库。
SharePoint 创建到 SharePoint 网站的连接,以便您可以在应用程序中使用任何 SharePoint 列表。
SharePoint 创建到 SharePoint 网站的连接,以便您可以在应用中使用任何 SharePoint 列表。
OData 服务允许您连接到通过开放数据协议([http://OData.org](http://OData.org))公开的任何网络服务。反过来,每个 LightSwitch 应用程序都使用 JSON Light(一个 OData 实现)向 LightSwitch 或第三方客户端公开中间层。这意味着您可以使用 OData Service 连接将新的 LightSwitch 应用程序连接到已经部署的 LightSwitch 应用程序中的实体,从而提高**的可重用性**
OData 服务允许您连接到通过开放数据协议([http://OData.org](http://OData.org))公开的任何网络服务。反过来,每个 LightSwitch 应用都使用 JSON Light(一个 OData 实现)向 LightSwitch 或第三方客户端公开中间层。这意味着您可以使用 OData Service 连接将新的 LightSwitch 应用连接到已经部署的 LightSwitch 应用中的实体,从而提高**的可重用性**
WCF 放射免疫服务可以是任何继承自域服务基类的类。这允许开发人员在 LightSwitch 应用程序和他们可以从代码连接到的任何东西之间快速地用代码创建适配器:CSV 或 XML 文件、SOAP 服务、Office 文档或他们想要的任何专有格式。
WCF 放射免疫服务可以是任何继承自域服务基类的类。这允许开发人员在 LightSwitch 应用和他们可以从代码连接到的任何东西之间快速地用代码创建适配器:CSV 或 XML 文件、SOAP 服务、Office 文档或他们想要的任何专有格式。
实体设计者通过确保您在逻辑所属的地方实现它来促进面向对象的原则:由实体封装。每个字段都有一个业务类型(唯一的****业务类型**)。LightSwitch 几乎有 20 种内置业务类型,从简单的数据类型(如布尔值或字符串)到更复杂的类型(如电子邮件或货币)。**
......@@ -104,7 +104,7 @@ WCF 放射免疫服务可以是任何继承自域服务基类的类。这允许
图 28:视图中内容项的可用控件和属性
此外,每个 ContentItem 节点在属性窗口中公开附加属性,以进一步控制布局、大小、字体和其他属性。移动应用程序中的活动级联样式表(CSS)或 Silverlight 桌面应用程序中的选定主题当然会进一步增强这一点。您还可以添加自定义代码来重写呈现。LightSwitch 还提供了专门的布局控件来排列、分组和组织用户界面中的元素,并能够从头开始创建自定义控件。通过**排版、颜色、自定义布局和专用控件**增强应用程序所需的所有工具都可用,我们将在后面的章节中尽可能多地介绍。
此外,每个 ContentItem 节点在属性窗口中公开附加属性,以进一步控制布局、大小、字体和其他属性。移动应用中的活动级联样式表(CSS)或 Silverlight 桌面应用中的选定主题当然会进一步增强这一点。您还可以添加自定义代码来重写呈现。LightSwitch 还提供了专门的布局控件来排列、分组和组织用户界面中的元素,并能够从头开始创建自定义控件。通过**排版、颜色、自定义布局和专用控件**增强应用所需的所有工具都可用,我们将在后面的章节中尽可能多地介绍。
除了外观,一些属性还允许您设置动作或编写自定义代码,以通过单击来响应特定的**触摸手势**
......@@ -114,29 +114,29 @@ WCF 放射免疫服务可以是任何继承自域服务基类的类。这允许
请注意,屏幕设计器中没有选项、属性或按钮来帮助创建**自适应设计,**,因为这是现成的,100%免费提供的。
设计好应用后,就该选择**认证**模型了。在解决方案资源管理器中选择 LightSwitch 应用程序,并打开属性。“访问控制”选项卡将允许您通过单击单选按钮来选择适合公司现有 IT 基础架构的身份验证模式。
设计好应用后,就该选择**认证**模型了。在解决方案资源管理器中选择 LightSwitch 应用,并打开属性。“访问控制”选项卡将允许您通过单击单选按钮来选择适合公司现有 IT 基础架构的身份验证模式。
![](img/image030.jpg)
图 30:访问控制选项卡
在同一个选项卡中,开发人员可以向应用程序添加自定义权限。然后可以在代码中检查这些权限,以允许或限制最终用户执行特定命令或打开特定屏幕,还可以用于垂直甚至水平数据安全,例如编辑实体上的特定字段,甚至对数据库隐藏特定行。然后,管理员(拥有安全管理权限的任何人)可以将最终用户分组到用户组中(或者在 Windows 身份验证的情况下重用活动目录安全组),并将这些权限的子集分配给每个组。这允许**授权**像业务要求的那样细粒度。
在同一个选项卡中,开发人员可以向应用添加自定义权限。然后可以在代码中检查这些权限,以允许或限制最终用户执行特定命令或打开特定屏幕,还可以用于垂直甚至水平数据安全,例如编辑实体上的特定字段,甚至对数据库隐藏特定行。然后,管理员(拥有安全管理权限的任何人)可以将最终用户分组到用户组中(或者在 Windows 身份验证的情况下重用活动目录安全组),并将这些权限的子集分配给每个组。这允许**授权**像业务要求的那样细粒度。
从常规属性选项卡中,您可以从 41 种受支持的语言中选择应用程序的语言。
从常规属性选项卡中,您可以从 41 种受支持的语言中选择应用的语言。
![](img/image031.png)
图 31:光开关应用程序的一般属性
图 31:光开关应用的一般属性
单个应用程序也可以同时支持多种语言。这本书没有涉及到,但是你可以在[http://msdn . Microsoft . com/en-us/library/vstudio/xx130603 . aspx](http://msdn.microsoft.com/en-us/library/vstudio/xx130603.aspx)找到更多信息。
单个应用也可以同时支持多种语言。这本书没有涉及到,但是你可以在[http://msdn . Microsoft . com/en-us/library/vstudio/xx130603 . aspx](http://msdn.microsoft.com/en-us/library/vstudio/xx130603.aspx)找到更多信息。
根据您的 LightSwitch 应用程序类型,可用选项卡的数量会有所不同。我们的使命是创建一个移动业务应用程序,但是如果您也想使用 LightSwitch 创建云业务应用程序,只需从 Office/SharePoint 节点下的云业务应用程序项目模板开始您的旅程。
根据您的 LightSwitch 应用类型,可用选项卡的数量会有所不同。我们的使命是创建一个移动业务应用,但是如果您也想使用 LightSwitch 创建云业务应用,只需从 Office/SharePoint 节点下的云业务应用项目模板开始您的旅程。
![](img/image032.jpg)
图 32:云业务应用项目模板
此项目模板将创建一个 LightSwitch 应用程序,该应用程序预先配置为部署到 SharePoint 2013 服务器,无论是在内部还是在云中,如 Office 365 站点。SharePoint 开发不在本电子书范围内,但如果您想了解更多相关主题,请点击此链接:[http://msdn . Microsoft . com/en-us/library/vstudio/jj 969620 . aspx](http://msdn.microsoft.com/en-us/library/vstudio/jj969620.aspx)
此项目模板将创建一个 LightSwitch 应用,该应用预先配置为部署到 SharePoint 2013 服务器,无论是在内部还是在云中,如 Office 365 站点。SharePoint 开发不在本电子书范围内,但如果您想了解更多相关主题,请点击此链接:[http://msdn . Microsoft . com/en-us/library/vstudio/jj 969620 . aspx](http://msdn.microsoft.com/en-us/library/vstudio/jj969620.aspx)
回到当前项目可用的选项卡,让我们看看扩展选项卡。LightSwitch 有一个 SDK,可以从[http://visualstudiogallery . msdn . Microsoft . com/2381 b 03 B- 5c 71-4847-a58e-5 CFA 48d 418 DC](http://visualstudiogallery.msdn.microsoft.com/2381b03b-5c71-4847-a58e-5cfa48d418dc)下载。使用这个软件开发工具包,您可以为不同的数据源、新的业务类型控件、屏幕模板,甚至公司特定的外壳和主题创建额外的、可重用的适配器。请注意,在撰写本文时,这四个扩展仅限于桌面客户端使用。然后,这些扩展将被打包到一个 VSIX 安装程序中。一旦您安装了这样一个 VSIX,您就可以在这个选项卡中按照 LightSwitch 项目激活它。
......@@ -144,7 +144,7 @@ WCF 放射免疫服务可以是任何继承自域服务基类的类。这允许
![http://www.syncfusion.com/content/en-us/producimg/lightswitimg/SlidingBanner/banner2.png](img/image033.png)
图 33:带有灯光开关控件的 SilverLight 应用程序示例
图 33:带有灯光开关控件的 SilverLight 应用示例
请记住,这些 VSIX 文件也必须安装在您的构建服务器上,否则它将无法根据刚从**源代码控制**中提取的源代码编译您的 LightSwitch 项目。LightSwitch 在 IDE 中使用编辑器,但在幕后,LightSwitch 解决方案包含可以检入或推送到任何源代码管理的普通项目,就像任何其他项目一样。在[http://blogs . msdn . com/b/LightSwitch/archive/2013/07/09/team-development-series-introduction-Peter-hauge . aspx](http://blogs.msdn.com/b/lightswitch/archive/2013/07/09/team-development-series-introduction-peter-hauge.aspx)上可以找到关于同时与多个开发人员合作进行 light switch 项目的其他指南和最佳实践。
......@@ -152,4 +152,4 @@ WCF 放射免疫服务可以是任何继承自域服务基类的类。这允许
LightSwitch 使用语义版本控制。开发人员有责任保持主要和次要版本号的最新。每次单击发布按钮时,修补程序编号都会自动增加。
单击发布按钮将启动发布向导。这个过程将在后面详细介绍。目前,我将把我的案例放在 LightSwitch 上,它是 LOB 应用程序开发的绝佳工具;我将卷起袖子,深入到“常规属性”选项卡上我还没有提到的最后一个属性:SQL 数据库项目。**
\ No newline at end of file
单击发布按钮将启动发布向导。这个过程将在后面详细介绍。目前,我将把我的案例放在 LightSwitch 上,它是 LOB 应用开发的绝佳工具;我将卷起袖子,深入到“常规属性”选项卡上我还没有提到的最后一个属性:SQL 数据库项目。**
\ No newline at end of file
......@@ -26,7 +26,7 @@ SDET·克里斯·鲁梅尔在[上详细解释了这个特性。](http://blogs.ms
图 36:添加部署后脚本
该部署后脚本将在每次部署数据库时执行。这包括首次发布应用程序时、发布更新时以及每次更改实体布局时。我已经更新了克里斯的 SQL 脚本来匹配我们的模型。
该部署后脚本将在每次部署数据库时执行。这包括首次发布应用时、发布更新时以及每次更改实体布局时。我已经更新了克里斯的 SQL 脚本来匹配我们的模型。
![](img/image037.png)
......@@ -34,10 +34,10 @@ SDET·克里斯·鲁梅尔在[上详细解释了这个特性。](http://blogs.ms
该脚本的意图很简单:给定一组硬编码的客户,用相应的标识更新数据库中的行,插入缺失的行,并删除多余的数据。这个数据中的人物和任何人,无论是活着的还是死去的,之间的任何相似之处都是纯粹的巧合。
重新构建并再次启动应用程序,以验证我们的测试对象是否到位。
重新构建并再次启动应用,以验证我们的测试对象是否到位。
![](img/image038.jpg)
图 37:重建的应用程序
图 37:重建的应用
该应用程序如预期的那样显示客户。
\ No newline at end of file
该应用如预期的那样显示客户。
\ No newline at end of file
# 第 4 章定制应用外观
该应用程序开箱即用,功能齐全,并且有一些基本的样式。在本章中,我将向您展示一些技术来进一步优化外观。首先,您将使用屏幕设计器,最终深入一些基本的 CSS、JavaScript 和 JQuery,最后完全标记全局应用程序主题。
该应用开箱即用,功能齐全,并且有一些基本的样式。在本章中,我将向您展示一些技术来进一步优化外观。首先,您将使用屏幕设计器,最终深入一些基本的 CSS、JavaScript 和 JQuery,最后完全标记全局应用主题。
## 来自屏幕设计器:布局和控件
......@@ -18,7 +18,7 @@
默认情况下,客户实体中的每个字段都将显示为一列,包括自动生成和维护的审核列(但不包括用于服务器并发检查的行版本列)。
如果您想知道为什么第一条记录在审核字段中有日期,而其他记录没有,这是因为在我的例子中,第一行是使用应用程序创建的。同一记录的内容后来被数据库中的 SQL 脚本直接覆盖,因为该脚本在 ID 上匹配。审计列由中间层(OData 服务)维护。这就是为什么我们的 SQL 部署后脚本创建的行没有审计信息。
如果您想知道为什么第一条记录在审核字段中有日期,而其他记录没有,这是因为在我的例子中,第一行是使用应用创建的。同一记录的内容后来被数据库中的 SQL 脚本直接覆盖,因为该脚本在 ID 上匹配。审计列由中间层(OData 服务)维护。这就是为什么我们的 SQL 部署后脚本创建的行没有审计信息。
让我们稍微整理一下。回到屏幕设计器中,选择“表格行”节点的任何子节点,然后按键盘上的 delete 键或单击命令栏中的 delete 按钮。重复,直到您剩下大约五列。
......@@ -62,7 +62,7 @@
## 来自屏幕设计器:弹出窗口和过滤
通过选择集合控件和布局的正确组合,您可以确保应用程序显示尽可能多的有用信息,并且只显示有用的信息,最终用户会对此表示感谢。让我们探索过滤数据的一些可能性。
通过选择集合控件和布局的正确组合,您可以确保应用显示尽可能多的有用信息,并且只显示有用的信息,最终用户会对此表示感谢。让我们探索过滤数据的一些可能性。
为了过滤数据,我们需要更改用于检索数据的查询。从屏幕设计器(左侧)的视图模型中选择客户集合,并选择编辑查询链接。
......@@ -176,7 +176,7 @@
## 自定义控件:后期渲染
有许多不同的屏幕布局和操作不需要任何代码,但仍然允许您调整应用程序以满足最终用户的需求。
有许多不同的屏幕布局和操作不需要任何代码,但仍然允许您调整应用以满足最终用户的需求。
不过,有时稍微改变 LightSwitch 可视化特定元素的方式是有意义的。在任何时候都有可能增强甚至完全覆盖 LightSwitch 视图引擎的结果。前者是 LightSwitch 开发人员称为后期渲染的过程。
......@@ -254,11 +254,11 @@ jQuery 选择器就是一个例子([http://www.w3schools.com/jquery/jquery_ref_s
图 60:按性别着色的瓷砖
虽然可以直接从代码中修改 CSS,但是像这样的编程并不能产生易于维护的应用程序。相反,更好的方法是在代码中应用特定的样式(在 HTML 世界中称为类),然后从单独的 CSS 文件中调整这个类。
虽然可以直接从代码中修改 CSS,但是像这样的编程并不能产生易于维护的应用。相反,更好的方法是在代码中应用特定的样式(在 HTML 世界中称为类),然后从单独的 CSS 文件中调整这个类。
## 自定义控件:渲染
渲染与后期渲染完全相同,只是您没有通过向 DOM 添加元素来调整 LightSwitch 的结果,而是完全覆盖并自己控制了这一点。例如,我们将更改应用程序,使其不以文本形式而是以图标形式显示客户满意度得分。
渲染与后期渲染完全相同,只是您没有通过向 DOM 添加元素来调整 LightSwitch 的结果,而是完全覆盖并自己控制了这一点。例如,我们将更改应用,使其不以文本形式而是以图标形式显示客户满意度得分。
说到寻找或者创造好的图标,我强烈推荐从[http://www.syncfusion.com/downloads/metrostudio](http://www.syncfusion.com/downloads/metrostudio)下载 Syncfusion 的免费 Metro Studio。
......@@ -278,7 +278,7 @@ jQuery 选择器就是一个例子([http://www.w3schools.com/jquery/jquery_ref_s
除了图像,内容子文件夹是存储级联样式表(CSS)的指定位置。其中一个 CSS 文件被命名为用户定制。半铸钢ˌ钢性铸铁(Cast Semi-Steel)
该文件允许您覆盖 LightSwitch 创建的任何样式,而无需实际修改 LightSwitch 专有 CSS(因此您的定制变得更能适应版本控制)。对于较小的应用程序,我使用这种用户定制。CSS 文件不仅可以改变样式,还可以添加新的类。打开用户自定义文件并添加以下样式:
该文件允许您覆盖 LightSwitch 创建的任何样式,而无需实际修改 LightSwitch 专有 CSS(因此您的定制变得更能适应版本控制)。对于较小的应用,我使用这种用户定制。CSS 文件不仅可以改变样式,还可以添加新的类。打开用户自定义文件并添加以下样式:
![](img/image072.png)
......@@ -342,7 +342,7 @@ jQuery 选择器就是一个例子([http://www.w3schools.com/jquery/jquery_ref_s
代码清单 15
我这样做是因为客户满意度分数的实际值可能会在应用程序执行过程中发生变化。当这种情况发生时(即使是在另一个屏幕或代码中完成),我们的回调函数将再次执行。以这种方式清除自定义元素上的 CSS 类有助于避免重复或冲突的样式。
我这样做是因为客户满意度分数的实际值可能会在应用执行过程中发生变化。当这种情况发生时(即使是在另一个屏幕或代码中完成),我们的回调函数将再次执行。以这种方式清除自定义元素上的 CSS 类有助于避免重复或冲突的样式。
保存进度并刷新浏览器以测试新样式。
......
......@@ -74,7 +74,7 @@ beforeShown 回调函数主要用于执行特定于扫描程序的初始化代
图 70:实体的写代码按钮
假设平均来说,一个客户一开始是一个快乐的客户,结果假设满意度得分为 80%。您可以在实体设计器生成的 created()函数存根中的应用程序中对此进行建模:
假设平均来说,一个客户一开始是一个快乐的客户,结果假设满意度得分为 80%。您可以在实体设计器生成的 created()函数存根中的应用中对此进行建模:
![](img/image091.png)
......@@ -106,7 +106,7 @@ beforeShown 回调函数主要用于执行特定于扫描程序的初始化代
我们为添加-编辑客户屏幕编写的初始化代码非常简单:设置屏幕的显示名称并初始化客户实体的满意度得分。我们没有触及任何可能需要一段时间才能完成的属性或字段。当你这样做的时候,为了防止冗长的代码执行时接口冻结,LightSwitch 会强制你使用 WinJS“promise”对象编写异步 JavaScript 代码。作为练习,我们将尝试在添加-编辑客户屏幕上显示一条消息,显示客户是否有任何未结订单。
这当然意味着我们将通过引入一个名为 Order 的新实体来扩展应用程序,订单和客户之间是一对多的关系。
这当然意味着我们将通过引入一个名为 Order 的新实体来扩展应用,订单和客户之间是一对多的关系。
![](img/image095.jpg)
......@@ -140,7 +140,7 @@ beforeShown 回调函数主要用于执行特定于扫描程序的初始化代
将 orders 集合重命名为 OpenOrders。
现在,应用程序已经有了订单的概念,并且您已经在屏幕上添加了示例数据和未完成订单的集合,如果客户当前有任何未完成的订单,您已经准备好显示一条消息。
现在,应用已经有了订单的概念,并且您已经在屏幕上添加了示例数据和未完成订单的集合,如果客户当前有任何未完成的订单,您已经准备好显示一条消息。
为了能够显示这个消息,我们需要将它存储在视图模型的某个地方。通过单击屏幕设计器顶部的“添加数据项”按钮,并在“添加数据项”向导中创建 OpenOrderMessage 属性,向视图模型添加新的字符串属性。
......@@ -200,7 +200,7 @@ promise 对象只不过是对获取数据的引用。IntelliSense 揭示了它
图 81:正确初始化的详细屏幕
![](img/image109.png)注意:认为这是多线程应用是不正确的。即使这些技术被明确地称为异步,JavaScript 确实提供了多线程支持(根据规格:[http://www . ECMA-international . org/publications/files/ECMA-ST/Ecma-262 . pdf](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf))。promise 对象不像真正的多线程应用程序那样同时运行多个代码路径,而是简单地封装改变一个单线程顺序代码路径的逻辑。
![](img/image109.png)注意:认为这是多线程应用是不正确的。即使这些技术被明确地称为异步,JavaScript 确实提供了多线程支持(根据规格:[http://www . ECMA-international . org/publications/files/ECMA-ST/Ecma-262 . pdf](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf))。promise 对象不像真正的多线程应用那样同时运行多个代码路径,而是简单地封装改变一个单线程顺序代码路径的逻辑。
如果您有一个可能需要一段时间才能完成的自定义 JavaScript 函数,LightSwitch 有一个简单的 API 调用,允许您自己将任何函数包装在一个承诺中,就像 Michael Washington 在下面的自描述代码片段中演示的那样,该代码片段摘自“在 Visual Studio LightSwitch 中使用承诺”([http://light witchhelp 网站. com/Blog/tabid/61/EntryId/170/Using-Promises-In-Visual Studio-light switch . aspx](http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/170/Using-Promises-In-Visual-Studio-LightSwitch.aspx)):
......@@ -232,7 +232,7 @@ promise 对象只不过是对获取数据的引用。IntelliSense 揭示了它
在实现代码之前,您可以为此控制器配置路由,以便快速测试。右键单击服务器项目,并从上下文菜单中选择“添加新项”。
从“添加新项”对话框添加新的全局应用程序类,并用以下代码替换内容:
从“添加新项”对话框添加新的全局应用类,并用以下代码替换内容:
![](img/image113.png)
......@@ -246,7 +246,7 @@ promise 对象只不过是对获取数据的引用。IntelliSense 揭示了它
因为您可以从浏览器执行 HTTP GET,所以您可以通过在 CustomerOrderSummaryController 的 GET 方法中设置断点并按 F5 构建和开始调试来测试您的设置。将您的浏览器从 HTML 客户端的默认 URL(http://localhost:10355/HTML client/)导航到 http://localhost:10355/reports/customerrodersummary/5。您应该到达断点,注意 id 参数的值是 5。端口号 10355 可能在您的系统上有所不同。
下一步是实现控制器,与应用程序的服务器端 LightSwitch 模型进行交互。这是通过添加对微软。LightSwitch 命名空间,其中 LightSwitch 为类顶部的 using 语句生成了一个名为 ServerApplicationContext 的类。ServerApplicationContext 是 LightSwitch 中的一个新类,从 VS 2012 更新 3 开始。
下一步是实现控制器,与应用的服务器端 LightSwitch 模型进行交互。这是通过添加对微软。LightSwitch 命名空间,其中 LightSwitch 为类顶部的 using 语句生成了一个名为 ServerApplicationContext 的类。ServerApplicationContext 是 LightSwitch 中的一个新类,从 VS 2012 更新 3 开始。
ServerApplicationContext 类的实例实现了 IDisposable,因此它们应该被包装在一个 using 语句中,以便正确地处置资源,比如与数据库的连接。
......@@ -266,7 +266,7 @@ ServerApplicationContext 类的实例实现了 IDisposable,因此它们应该
从 GET 操作中,您将从代码中返回一个隐式类型化的 CRL 对象数组。事实上,ASP.NET 网络应用编程接口会自动将数据整理成 JavaScript 对象符号(JSON)格式,这是编程语言不可知的。
你可以从任何编程语言中调用它。事实上,要测试结果,请随意按 Ctrl+F5 来构建和启动应用程序(无需调试),然后导航到像 http://localhost:{ yoursportnumber }/reports/customerrodersummary/5 这样的硬编码 URL 来查看结果。根据您的浏览器,该 JSON 响应可能会直接显示或作为文件下载。
你可以从任何编程语言中调用它。事实上,要测试结果,请随意按 Ctrl+F5 来构建和启动应用(无需调试),然后导航到像 http://localhost:{ yoursportnumber }/reports/customerrodersummary/5 这样的硬编码 URL 来查看结果。根据您的浏览器,该 JSON 响应可能会直接显示或作为文件下载。
![](img/image117.jpg)
......@@ -276,9 +276,9 @@ ServerApplicationContext 类的实例实现了 IDisposable,因此它们应该
既然您有了在服务器上积累数据的有效方法,那么您就需要一种有效的方法来可视化结果。虽然您可以使用 render 方法自己编写自定义控件,但有趣的是,LightSwitch 绝不会阻止使用第三方库。这是一个测试 Syncfusions 新的 JavaScript 基本工作室的好机会。
本质 JS 是一个新的 JavaScript 框架设计器,用于业务线(LOB)应用程序。向您的 LightSwitch HTML 应用程序添加第三方组件总是一个三步走的过程。第一步是添加所需的代码(。js 文件)和样式(。css 文件)移动到 HTMLClient 项目中的适当文件夹。您需要确保通过从网页中引用它们来加载它们,然后您可以在需要的地方使用它们。
本质 JS 是一个新的 JavaScript 框架设计器,用于业务线(LOB)应用。向您的 LightSwitch HTML 应用添加第三方组件总是一个三步走的过程。第一步是添加所需的代码(。js 文件)和样式(。css 文件)移动到 HTMLClient 项目中的适当文件夹。您需要确保通过从网页中引用它们来加载它们,然后您可以在需要的地方使用它们。
下载基本 JS 套件后,复制名为 bootstrap 的样式表。CSS,默认。CSS 和默认响应。CSS 从安装目录移动到 HTMLClient 项目的 Content 子文件夹,并将 ej.widgets.all.min.js 和 properties.js 移动到 Scripts 子文件夹。向应用程序中添加第三方脚本时,请始终搜索缩小版本,您可以通过。文件名中的 min,以减小下载大小。
下载基本 JS 套件后,复制名为 bootstrap 的样式表。CSS,默认。CSS 和默认响应。CSS 从安装目录移动到 HTMLClient 项目的 Content 子文件夹,并将 ej.widgets.all.min.js 和 properties.js 移动到 Scripts 子文件夹。向应用中添加第三方脚本时,请始终搜索缩小版本,您可以通过。文件名中的 min,以减小下载大小。
接下来,您需要将这些 CSS 和 JavaScript 资源加载到名为 default.htm 的 HTML 页面中。
......@@ -292,7 +292,7 @@ ServerApplicationContext 类的实例实现了 IDisposable,因此它们应该
代码清单 34
此块将导致加载 Microsoft light switch(msls)Javascript 库并启动应用程序,用构成应用程序的元素替换加载动画中的 HTML DIV 元素。
此块将导致加载 Microsoft light switch(msls)Javascript 库并启动应用,用构成应用的元素替换加载动画中的 HTML DIV 元素。
在这个网页中,找到指向样式表的链接,并在底部添加指向您刚刚添加到项目中的基本 JS 样式表的链接:
......@@ -318,7 +318,7 @@ ServerApplicationContext 类的实例实现了 IDisposable,因此它们应该
代码清单 38
现在,所需的基本 JS 文件已经添加到项目中并加载到 HTML 页面中,您可以在应用程序中将它们用作自定义控件。
现在,所需的基本 JS 文件已经添加到项目中并加载到 HTML 页面中,您可以在应用中将它们用作自定义控件。
首先,在屏幕设计器中打开添加-编辑客户屏幕,并创建一个名为 OrderSummary 的新选项卡。在此选项卡上,将客户的 id 属性从视图模型拖到视图上,并使用自定义控件来呈现它。在“属性”窗口中,将标签位置设置为“无”。
......@@ -360,9 +360,9 @@ ServerApplicationContext 类的实例实现了 IDisposable,因此它们应该
![](img/image130.jpg)
图 LightSwitch 应用程序中运行的基本 JS
图 LightSwitch 应用中运行的基本 JS
运行应用程序时,您会看到一个美丽的动画在运行。
运行应用时,您会看到一个美丽的动画在运行。
## jQuery 用户界面小部件:自定义必应地图控件
......
......@@ -2,7 +2,7 @@
## 内置模式
LightSwitch HTML 应用程序带有两个全局颜色和样式模式:默认的 Light 主题和 Dark 主题。
LightSwitch HTML 应用带有两个全局颜色和样式模式:默认的 Light 主题和 Dark 主题。
主题之间的切换是通过再次打开 default.htm 页面并编辑到下面两个样式表的链接来完成的,如前面的 HTML 注释中所述。
......@@ -22,7 +22,7 @@ LightSwitch HTML 应用程序带有两个全局颜色和样式模式:默认的 L
代码清单 48
LightSwitch 使用了一个名为 jQuery Mobile 的开源 UI 框架。依赖开源框架意味着你可以获得免费的 bug 修复、升级和令人敬畏的工具,比如 jQuery Mobile ThemeRoller。主题滚轮是一个网站,您可以在其中创建与任何 jQuery Mobile 应用程序一起工作的自定义主题,从而允许您替换内置的 LightSwitch 主题。
LightSwitch 使用了一个名为 jQuery Mobile 的开源 UI 框架。依赖开源框架意味着你可以获得免费的 bug 修复、升级和令人敬畏的工具,比如 jQuery Mobile ThemeRoller。主题滚轮是一个网站,您可以在其中创建与任何 jQuery Mobile 应用一起工作的自定义主题,从而允许您替换内置的 LightSwitch 主题。
要创建自己的主题,只需将 HTML 项目的 contents 子文件夹中的 light-theme-2.0.0.CSS 的内容复制到剪贴板即可。接下来,打开[http://jquerymobile.com/themeroller](http://jquerymobile.com/themeroller),找到顶部的导入按钮。将 CSS 粘贴到出现的对话框中,LightSwitch 主题应该加载到主题滚轮中。
......@@ -42,11 +42,11 @@ LightSwitch 使用了一个名为 jQuery Mobile 的开源 UI 框架。依赖开
![](img/image144.jpg)
图 93:带有黑色和蓝色主题的应用程序
图 93:带有黑色和蓝色主题的应用
## 添加公司标志
LightSwitch HTML 应用程序使用两个徽标,这两个徽标都可以在 HTML 客户端项目的内容文件夹的 images 子文件夹中找到:user-splash-screen.png 和 user-logo.png。前者在应用程序加载时可见;后者显示在每个浏览屏幕的左上角。
LightSwitch HTML 应用使用两个徽标,这两个徽标都可以在 HTML 客户端项目的内容文件夹的 images 子文件夹中找到:user-splash-screen.png 和 user-logo.png。前者在应用加载时可见;后者显示在每个浏览屏幕的左上角。
通过简单地改变资源本身,这两个图片都可以并且应该被你真实的公司标志所取代。
......@@ -60,4 +60,4 @@ LightSwitch HTML 应用程序使用两个徽标,这两个徽标都可以在 HT
![](img/image146.jpg)
图 94:带有自定义 user-logo.png 和附加页脚样式的应用程序
\ No newline at end of file
图 94:带有自定义 user-logo.png 和附加页脚样式的应用
\ No newline at end of file
......@@ -6,9 +6,9 @@
LightSwitch 提供了各种现成的受支持的托管环境,无论是内部还是云中。除非您选择连接到现有数据库,否则您的内部数据库(基于您的实体自动创建的数据库)可以部署到 SQL 2008、2012、2013 或 SQL Azure 服务器,并且您的 HTML 项目和中间层可以托管在 IIS、Azure 云服务或 Azure 网站(如果您需要较少的配置)上。
或者,LightSwitch 也允许您创建云业务应用程序。这允许应用程序由 Sharepoint 2013 服务器自动托管,无论是在本地还是在外部提供商(如 Office 365)上。
或者,LightSwitch 也允许您创建云业务应用。这允许应用由 Sharepoint 2013 服务器自动托管,无论是在本地还是在外部提供商(如 Office 365)上。
目前,您将坚持使用最简单的解决方案:将应用程序部署为免费的 Azure 网站。
目前,您将坚持使用最简单的解决方案:将应用部署为免费的 Azure 网站。
## 创建蔚蓝网站
......@@ -30,17 +30,17 @@ LightSwitch 提供了各种现成的受支持的托管环境,无论是内部
## 发布申请
有了支持 Azure 的基础设施,您应该不到一分钟就能准备好展示您的第一个移动业务应用程序
有了支持 Azure 的基础设施,您应该不到一分钟就能准备好展示您的第一个移动业务应用。
将您的构建配置从调试更改为发布,然后在解决方案资源管理器中右键单击 LightSwitch 项目。从上下文菜单中选择发布。
![](img/image149.png)
图 97:发布 LightSwitch 应用程序
图 97:发布 LightSwitch 应用。
这将打开 LightSwitch 发布应用程序向导,指导您完成整个过程。
这将打开 LightSwitch 发布应用向导,指导您完成整个过程。
该向导允许您将应用程序作为一个整体发布,或者仅将中间层部署为 OData 服务。第二个选项卡,应用服务器配置,允许您选择本地安装到 IIS 或部署到 Azure,这当然是您想要选择的选项。如果您没有安装 Azure SDK,Visual Studio 现在将指导您完成所需的安装。
该向导允许您将应用作为一个整体发布,或者仅将中间层部署为 OData 服务。第二个选项卡,应用服务器配置,允许您选择本地安装到 IIS 或部署到 Azure,这当然是您想要选择的选项。如果您没有安装 Azure SDK,Visual Studio 现在将指导您完成所需的安装。
第三个标签,订阅,可能是最节省时间的。
......@@ -52,4 +52,4 @@ LightSwitch 提供了各种现成的受支持的托管环境,无论是内部
有了这些,向导的其余部分就很简单了。您为网站指定的名称可以从“服务配置”选项卡中选择,并且您创建的数据库的连接将已经填充在“数据连接”选项卡中。
查看摘要页面的潜在错误后,单击发布。Visual Studio 将构建、打包、上传和部署您的应用程序。数据库项目中的后期部署脚本也将被执行,为您提供相同的示例数据。
\ No newline at end of file
查看摘要页面的潜在错误后,单击发布。Visual Studio 将构建、打包、上传和部署您的应用。数据库项目中的后期部署脚本也将被执行,为您提供相同的示例数据。
\ No newline at end of file
# 准备,出发,出发
抓住最近的移动设备,浏览到 http://<yourazurewebsite>. azurewebsites . net/HTMLClient/default . htm(default.htm 可以省略,但不要忘记 html client 子文件夹),查看您的第一个面向移动、触摸友好、云端、业务线、单页应用程序的运行情况。</yourazurewebsite>
抓住最近的移动设备,浏览到 http://<yourazurewebsite>. azurewebsites . net/HTMLClient/default . htm(default.htm 可以省略,但不要忘记 html client 子文件夹),查看您的第一个面向移动、触摸友好、云端、业务线、单页应用的运行情况。</yourazurewebsite>
![](img/image151.jpg)
图 99:发布的应用程序
图 99:发布的应用
恭喜你!你在 LightSwitch 移动商务应用学院度过了第一天。
你将不得不从这里自己弄清楚剩下的过程,但是有很多资源可以帮助你。例如,您可以浏览官方 LightSwitch 开发者中心([http://msdn.microsoft.com/en-us/vstudio/htmlclient.aspx](http://msdn.microsoft.com/en-us/vstudio/htmlclient.aspx))获取大量优秀的学习资料,或者在最大的非官方 LightSwitch 社区([http://lightswitchhelpwebsite.com/](http://lightswitchhelpwebsite.com/))闲逛,LightSwitch 摇滚明星 Michael Washington 以惊人的速度用不可思议的内容对待我们。说到不可思议的内容,你还应该看看务实的保罗·范·布莱戴尔([http://blog.pragmaswitch.com/](http://blog.pragmaswitch.com/))、艺术家朱厄尔·兰伯特([http://jewellambert.com/](http://jewellambert.com/))或者 xpert 360([http://xpert360.com/](http://xpert360.com/)的奇才们的博客。
我肯定我遗漏了至少十几个伟大的博客,包括亚历山德罗·德尔·索勒的博客(http://community . visual-basic . it),他在技术上编辑了这本电子书,还有我自己的漫谈([http://janvanderhaegen.wordpress.com](http://janvanderhaegen.wordpress.com))。确保您不会错过任何东西的最佳方法是下载社区应用程序([http://apps . Microsoft . com/windows/en-us/app/visual-studio-lightswitch/d5d5d5f 80e-d8df-4fa 9-935 b-a 92ed 7 ad 03 a 7](http://apps.microsoft.com/windows/en-us/app/visual-studio-lightswitch/d5d5f80e-d8df-4fa9-935b-a92ed7ad03a7))并订阅 light switch 团队博客([http://blogs.msdn.com/b/lightswitch/](http://blogs.msdn.com/b/lightswitch/)),高级项目经理贝丝·马西将每月为您提供内容和社区的完整汇总。
我肯定我遗漏了至少十几个伟大的博客,包括亚历山德罗·德尔·索勒的博客(http://community . visual-basic . it),他在技术上编辑了这本电子书,还有我自己的漫谈([http://janvanderhaegen.wordpress.com](http://janvanderhaegen.wordpress.com))。确保您不会错过任何东西的最佳方法是下载社区应用([http://apps . Microsoft . com/windows/en-us/app/visual-studio-lightswitch/d5d5d5f 80e-d8df-4fa 9-935 b-a 92ed 7 ad 03 a 7](http://apps.microsoft.com/windows/en-us/app/visual-studio-lightswitch/d5d5f80e-d8df-4fa9-935b-a92ed7ad03a7))并订阅 light switch 团队博客([http://blogs.msdn.com/b/lightswitch/](http://blogs.msdn.com/b/lightswitch/)),高级项目经理贝丝·马西将每月为您提供内容和社区的完整汇总。
感谢每个人让 LightSwitch 社区了解情况并参与进来。继续摇 LS!
\ No newline at end of file
# 前言:为什么探索光开关值得我花这么多时间?
# 零、前言
我们中的少数人设计逼真的三维游戏,或者在谷歌的玻璃项目团队中。我们大多数 IT 行业的人都创建了非常具体的业务线软件,我们自己永远不会使用。尽管目的和细节可能会因行业而异,但我们为保持医疗预约、为企业记账、跟踪大学生或管理房地产而编写的软件,都属于被称为“信息系统”的同一类无聊软件。信息系统是以数据为中心的应用程序,它们有几个共同点:一个或多个数据库、定义如何修改数据的大量业务规则、一个或多个不同的图形用户界面以及大量不同的报告。
为什么探索LightSwitch值得我花这么多时间?
我们中的少数人设计逼真的三维游戏,或者在谷歌的玻璃项目团队中。我们大多数 IT 行业的人都创建了非常具体的业务线软件,我们自己永远不会使用。尽管目的和细节可能会因行业而异,但我们为保持医疗预约、为企业记账、跟踪大学生或管理房地产而编写的软件,都属于被称为“信息系统”的同一类无聊软件。信息系统是以数据为中心的应用,它们有几个共同点:一个或多个数据库、定义如何修改数据的大量业务规则、一个或多个不同的图形用户界面以及大量不同的报告。
无论这些信息系统多么不具挑战性,但创建它们的人却恰恰相反。我们花了几个月甚至几年的时间来全面了解编码语言、技术和模式,并且通常拥有计算机科学学位,我们是善于分析的艺术家,总是在寻找挑战。
......@@ -10,6 +12,6 @@
* **学习业务。**如果你不知道某个人是谁,他或她的问题是什么,那么相信你可以创造软件来解决某人的问题,或者让某人的生活变得更轻松,这是荒谬的。在开始开发之前,请最终用户带您度过他或她的一天。随着每一个动作,问“为什么?”“怎么会?”最重要的是,“这让你有什么感觉?”不要指望最终用户能够给你提供一份需求清单——正如中国谚语所说,鱼是最后发现海洋的。做一个企业的内部人,但要做一个足以识别实际需求的外部人。
* **只为生意服务。**一天有 24 小时,学习新的、具有挑战性的技术和架构设计或代码模式绰绰有余,但要在闲暇时间去做,而不是在工作中。把时间花在不能直接为企业增加价值的事情上被认为是浪费。昂贵的废物也是如此。如果用户需要软件来管理他们的约会,那么这就是他们应该得到的——而不是“基于通用插件的宏记录器”,或者任何你骗自己相信会给他们的工作带来真正启示的东西。
* **只码业务。**沉闷是无法逃避的;没有任何自动映射器或代码生成器可以否定必须定义屏幕、实体和验证的事实。但是,定义一次。如果绝大多数手工编写的代码不是领域特定的,或者如果您在整个应用程序的几个层中实现了更改,那么您就做错了。更具体地说,您使用了错误的工具。
* **只码业务。**沉闷是无法逃避的;没有任何自动映射器或代码生成器可以否定必须定义屏幕、实体和验证的事实。但是,定义一次。如果绝大多数手工编写的代码不是领域特定的,或者如果您在整个应用的几个层中实现了更改,那么您就做错了。更具体地说,您使用了错误的工具。
如果你读了这篇序言,并且你同意,或者可能一直在点头或微笑,那么 Visual Studio LightSwitch 是一个你在工具带上肯定想要的工具。专为市民开发者和专业软件工程师而设计,如果你面对的是一个信息系统,如果你了解自己的业务并准备好为业务服务,那么 Visual Studio LightSwitch 将允许你只对业务进行编码,成为你应得的编码摇滚明星。
\ No newline at end of file
# 第 1 章哪里有 Visual Studio LightSwitch 2012?
# 一、在哪里获取 Visual Studio LightSwitch 2012?
获得 LightSwitch 2012 (RC)是容易的部分。在撰写本书时,仅作为一级公民在 Visual Studio 2012 中提供,目前仍处于 Release 候选者阶段,可以[免费下载](http://www.microsoft.com/visualstudio/11/en-us/downloads#professional)。当 Visual Studio 的 RC 期结束时,RTM 版本也将集成 LightSwitch,因此如果您订阅了 MSDN,或者打算购买 Visual Studio Professional 或更高版本的许可证,那么您是安全的。
......
# 第二章你好世界
# 二、你好世界
如果你和我一样,你有一些你想做的事情,有很多你必须做的项目,还有很多你应该已经完成的任务。作为本教程的一部分,我们将编写一个简单的 LightSwitch 应用程序来帮助您组织人员、任务和项目。毕竟*时间就是金钱*
如果你和我一样,你有一些你想做的事情,有很多你必须做的项目,还有很多你应该已经完成的任务。作为本教程的一部分,我们将编写一个简单的 LightSwitch 应用来帮助您组织人员、任务和项目。毕竟*时间就是金钱*
## 创建新项目
安装好 Visual Studio 2012 RC 后,启动它,从其**文件**菜单中选择**新项目**。在已安装的模板中,选择创建新的**光开关应用程序(Visual C#)** 的选项。您也可以选择使用 VB.NET 作为编码语言来创建您的应用程序。给你的项目取一个合适的名字,点击**确定**
安装好 Visual Studio 2012 RC 后,启动它,从其**文件**菜单中选择**新项目**。在已安装的模板中,选择创建新的**LightSwitch应用(Visual C#)** 的选项。您也可以选择使用 VB.NET 作为编码语言来创建您的应用。给你的项目取一个合适的名字,点击**确定**
![](img/image002.jpg)
......@@ -12,13 +12,13 @@
## 永远从数据开始
显示了 LightSwitch 主页,它建议从数据开始——考虑到应用程序以数据为中心的特性,这是一个显而易见的建议,您会发现 LightSwitch 非常适合。单击**创建新表**链接,创建新实体。这将打开实体设计器。
显示了 LightSwitch 主页,它建议从数据开始——考虑到应用以数据为中心的特性,这是一个显而易见的建议,您会发现 LightSwitch 非常适合。单击**创建新表**链接,创建新实体。这将打开实体设计器。
![](img/image003.jpg)
图 2: LightSwitch 主屏幕
我们将在整本书中解释实体设计器中发生的一切。首先,让我们通过将实体重命名为**项目**并添加一个名为**名称**的字符串属性来创建一个工作的“hello world”应用程序
我们将在整本书中解释实体设计器中发生的一切。首先,让我们通过将实体重命名为**项目**并添加一个名为**名称**的字符串属性来创建一个工作的“hello world”应用。
要重命名实体,请在实体设计器中双击它或填写右侧的**属性**窗口。
......@@ -50,10 +50,10 @@
## 按 F5 键将它们混合在一起
按下 **F5** 或从菜单中选择**调试** > **开始调试**来构建和启动您的应用程序。构建一个 LightSwitch 应用程序可能需要相当长的时间,但是经过这一小段延迟后,您的应用程序将会启动并准备使用。
按下 **F5** 或从菜单中选择**调试** > **开始调试**来构建和启动您的应用。构建一个 LightSwitch 应用可能需要相当长的时间,但是经过这一小段延迟后,您的应用将会启动并准备使用。
![](img/image008.jpg)
图 7:你好世界应用程序
图 7:你好世界应用
此时,我们有了一个工作应用程序,可以在其中添加、编辑或删除项目。虽然我们还没有编写任何代码,因为没有域逻辑(这是您必须编写的唯一代码),但是该应用程序有大量的功能和非功能特性:可折叠菜单、数据分页、排序、搜索、将数据导出到 Excel、验证、并发管理等等。
\ No newline at end of file
此时,我们有了一个工作应用,可以在其中添加、编辑或删除项目。虽然我们还没有编写任何代码,因为没有域逻辑(这是您必须编写的唯一代码),但是该应用有大量的功能和非功能特性:可折叠菜单、数据分页、排序、搜索、将数据导出到 Excel、验证、并发管理等等。
\ No newline at end of file
# 第三章实体设计师
# 三、实体设计师
## 创建具有简单和计算属性的任务实体
......@@ -20,7 +20,7 @@
图 9:清除最大长度
在这里指定描述字段的最大长度是“不要重复你自己”(DRY)原则的一个很好的例子,我在前言中暗示了这一点。在整个应用程序中,只有一个控制**描述**属性可以有多长的真实来源。这些信息将用于正确创建实际的数据库字段,还将用于在服务器和客户端上实现验证。
在这里指定描述字段的最大长度是“不要重复你自己”(DRY)原则的一个很好的例子,我在前言中暗示了这一点。在整个应用中,只有一个控制**描述**属性可以有多长的真实来源。这些信息将用于正确创建实际的数据库字段,还将用于在服务器和客户端上实现验证。
![](img/image011.jpg)
......@@ -93,7 +93,7 @@ LightSwitch 支持计算属性。这些属性不存储在数据库中,而是
图 15:对于每个实体,您可以选择 Summary 属性
乍一看,实体设计器看起来像一个数据库设计器,但是您真的应该试着把它看作一个域对象设计器,因为这里所做的选择将影响整个应用程序,而不仅仅是数据库层。这在我们的第三个实体中变得更加明显:人。
乍一看,实体设计器看起来像一个数据库设计器,但是您真的应该试着把它看作一个域对象设计器,因为这里所做的选择将影响整个应用,而不仅仅是数据库层。这在我们的第三个实体中变得更加明显:人。
## 通过巧妙重用现有业务类型来创建人员实体
......@@ -111,9 +111,9 @@ LightSwitch 支持计算属性。这些属性不存储在数据库中,而是
## 完全控制
另外,请记住,通过使用**编写代码**按钮,您可以控制应用程序的任何部分。这个扩展点允许您快速添加逻辑来控制特定属性的计算方式,如前所示,允许您实现业务规则、自定义验证、屏幕级或应用程序级可视化等等。稍后我将把这个称为*一级扩展性*
另外,请记住,通过使用**编写代码**按钮,您可以控制应用的任何部分。这个扩展点允许您快速添加逻辑来控制特定属性的计算方式,如前所示,允许您实现业务规则、自定义验证、屏幕级或应用级可视化等等。稍后我将把这个称为*一级扩展性*
我们可以添加到应用程序中的这种可扩展性的一个例子是每次创建**项目**时添加一个新任务。通过点击**项目**实体的实体设计器中的**编写代码**按钮,并简单添加以下代码,即可添加该代码:
我们可以添加到应用中的这种可扩展性的一个例子是每次创建**项目**时添加一个新任务。通过点击**项目**实体的实体设计器中的**编写代码**按钮,并简单添加以下代码,即可添加该代码:
```cs
namespace LightSwitchApplication
......@@ -137,7 +137,7 @@ LightSwitch 支持计算属性。这些属性不存储在数据库中,而是
## 别忘了设计关系
在完成对实体设计器的简单介绍并探索我们刚刚构建的应用程序之前,我们需要定义**项目****任务****人员**之间的关系。这是通过点击实体设计器工具栏中的**添加关系**按钮来完成的。
在完成对实体设计器的简单介绍并探索我们刚刚构建的应用之前,我们需要定义**项目****任务****人员**之间的关系。这是通过点击实体设计器工具栏中的**添加关系**按钮来完成的。
![](img/image019.jpg)
......@@ -159,13 +159,13 @@ LightSwitch 支持计算属性。这些属性不存储在数据库中,而是
在定义关系时,您会注意到 LightSwitch 中不直接支持某些关系类型,如“零或一对零或一”、“一对一”和“多对多”,但它们通常可以通过使用链接表和利用一级可扩展性来实现。
为了玩转我们到目前为止设计的应用程序(我有意使用术语“设计”而不是“编码”),按照第 2 章[中关于创建屏幕的说明,为各个实体添加两个名为**所有人**和**所有任务**的**列表和详细信息**屏幕。](2.html#heading_id_8)
为了玩转我们到目前为止设计的应用(我有意使用术语“设计”而不是“编码”),按照第 2 章[中关于创建屏幕的说明,为各个实体添加两个名为**所有人**和**所有任务**的**列表和详细信息**屏幕。](2.html#heading_id_8)
![](img/image022.jpg)
图 21:具有三个实体和相应屏幕的应用程序
图 21:具有三个实体和相应屏幕的应用
恭喜你,你现在有了一个全面运行的应用程序来帮助你重新控制你的时间!如下图所示,我在应用程序中添加了两个任务:*创建一些实体**洗碗*。请随意创建您自己的测试数据和任务。
恭喜你,你现在有了一个全面运行的应用来帮助你重新控制你的时间!如下图所示,我在应用中添加了两个任务:*创建一些实体**洗碗*。请随意创建您自己的测试数据和任务。
![](img/image023.jpg)
......@@ -173,11 +173,11 @@ LightSwitch 支持计算属性。这些属性不存储在数据库中,而是
在继续之前,我想强调的是,实体设计器应该被视为业务实体(域模型)设计器,而不是数据库设计器。
在实体设计器中设计的业务实体、它们的属性、它们的属性的业务类型及其扩展属性(包括验证)由 LightSwitch 在数据层、服务器和客户端的整个应用程序中使用。
在实体设计器中设计的业务实体、它们的属性、它们的属性的业务类型及其扩展属性(包括验证)由 LightSwitch 在数据层、服务器和客户端的整个应用中使用。
## 数据输入
一个应用程序中的数据必须可以在另一个应用程序中访问,这是常见的情况。LightSwitch 应用程序远离孤立的数据孤岛,IDE 对数据输入和数据输出场景都有现成的支持。
一个应用中的数据必须可以在另一个应用中访问,这是常见的情况。LightSwitch 应用远离孤立的数据孤岛,IDE 对数据输入和数据输出场景都有现成的支持。
要探索前者,请记住我们方便地单击了 LightSwitch 主屏幕上的**创建新表**链接,并开始设计我们的第一个实体。
......@@ -198,7 +198,7 @@ LightSwitch 支持计算属性。这些属性不存储在数据库中,而是
图 24:数据源向导帮助您连接到外部数据源
**附加数据源向导**将向您的应用程序添加一个非内部数据源,并允许您在数据上设计业务实体,但有一些验证限制(选项,如“是否需要属性”、“最大长度”,以及属性的兼容业务类型取决于源数据类型)。
**附加数据源向导**将向您的应用添加一个非内部数据源,并允许您在数据上设计业务实体,但有一些验证限制(选项,如“是否需要属性”、“最大长度”,以及属性的兼容业务类型取决于源数据类型)。
## 去 OData 还是不去 OData
......@@ -242,11 +242,11 @@ OData 是开放数据协议的缩写,是一个行业标准,在过去几年
图 29:浏览到 OData 端点
如果生成的 Silverlight 应用程序不符合您的业务需求,您可以通过许多其他客户端技术来访问这些 OData 端点,包括(但不限于):
如果生成的 Silverlight 应用不符合您的业务需求,您可以通过许多其他客户端技术来访问这些 OData 端点,包括(但不限于):
* Excel PowerPivot: [创建和使用 LightSwitch OData 服务](http://blogs.msdn.com/b/bethmassi/archive/2012/03/09/creating-and-consuming-lightswitch-odata-services.aspx)
* Windows 8: [在 Windows 8 Metro 风格的应用程序中使用 LightSwitch OData 服务](http://blogs.msdn.com/b/lightswitch/archive/2012/03/13/using-lightswitch-odata-services-in-a-windows-8-metro-style-application-elizabeth-maher.aspx)
* Windows Phone: [从 Windows Phone 应用程序中使用 LightSwitch OData 服务](http://msdn.microsoft.com/en-us/magazine/hh875176.aspx)
* Windows 8: [在 Windows 8 Metro 风格的应用中使用 LightSwitch OData 服务](http://blogs.msdn.com/b/lightswitch/archive/2012/03/13/using-lightswitch-odata-services-in-a-windows-8-metro-style-application-elizabeth-maher.aspx)
* Windows Phone: [从 Windows Phone 应用中使用 LightSwitch OData 服务](http://msdn.microsoft.com/en-us/magazine/hh875176.aspx)
* 一个完整的 CRUD Data.js 和淘汰赛。仅使用 HTML 页面的 Js LightSwitch 示例
* jQuery Mobile: [一款全 CRUD LightSwitch jQuery 移动应用](http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/126/A-Full-CRUD-LightSwitch-JQuery-Mobile-Application.aspx)
* 安卓:[使用安卓 App Inventor 与 LightSwitch 通信](http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/125/Communicating-With-LightSwitch-Using-Android-App-Inventor.aspx)
......@@ -256,7 +256,7 @@ OData 是开放数据协议的缩写,是一个行业标准,在过去几年
## 混合数据输入和数据输出
使用 LightSwitch 的一个强大方法是将其与其他技术结合使用,将数据输入和数据输出场景结合起来。由于可以选择在 LightSwitch 中间层使用 OData,LightSwitch 不仅可以用来创建简单的 CRUD 应用程序,还可以用来完成复杂的数据生态系统。
使用 LightSwitch 的一个强大方法是将其与其他技术结合使用,将数据输入和数据输出场景结合起来。由于可以选择在 LightSwitch 中间层使用 OData,LightSwitch 不仅可以用来创建简单的 CRUD 应用,还可以用来完成复杂的数据生态系统。
![](img/image031.jpg)
......
# 第四章查询编辑器
# 四、查询编辑器
## 找到重要的任务
......@@ -62,7 +62,7 @@
## 查找每个用户的重要任务
然而,图 38 中的查询显示了所有紧急任务。这个屏幕对我来说很棒,作为我个人生活的管理者,也是目前为止这个应用程序的唯一用户。但是如果您要使用这个应用程序来同时管理几个人、任务和项目,您可能会对每个用户的紧急任务查询感兴趣,而不是图 38 中的屏幕。
然而,图 38 中的查询显示了所有紧急任务。这个屏幕对我来说很棒,作为我个人生活的管理者,也是目前为止这个应用的唯一用户。但是如果您要使用这个应用来同时管理几个人、任务和项目,您可能会对每个用户的紧急任务查询感兴趣,而不是图 38 中的屏幕。
**解决方案资源管理器**中右键单击您的**任务**,并选择**添加新查询**,创建第二个查询。
......
# 第五章屏幕编辑器
# 五、屏幕编辑器
## 为我们的查询创建搜索数据屏幕
......@@ -78,7 +78,7 @@
## 屏幕去哪里了?
如果您按 F5 调试您的应用程序,您会注意到导航菜单不包括我们的新屏幕。
如果您按 F5 调试您的应用,您会注意到导航菜单不包括我们的新屏幕。
![](img/image051.png)
......@@ -86,7 +86,7 @@
原因是我们的新屏幕有一个本地屏幕属性,**任务分配人员**,为此我们选择了**是必需的****是参数**扩展属性。这意味着打开此屏幕的代码必须传递一个整数参数( **TaskAssignedPerson** ),导航菜单不知道如何为其解析一个值。
我们将不得不手动添加我们的新屏幕,这将只是我们在本教程中第五次必须编码——这对我们已经在这个应用程序中构建了多少功能来说还不错。
我们将不得不手动添加我们的新屏幕,这将只是我们在本教程中第五次必须编码——这对我们已经在这个应用中构建了多少功能来说还不错。
## 向屏幕添加新命令
......@@ -102,7 +102,7 @@
图 52:在屏幕上创建新命令
将添加一个新的命令,并且像您的 LightSwitch 应用程序的几乎任何元素一样,您可以使用设计器来设置几个扩展属性。我们肯定要设置的一个属性是所使用的图像。就我个人而言,我真的成为了 Syncfusion 免费定制图标工具 Metro Studio([http://www.syncfusion.com/downloads/metrostudio](http://www.syncfusion.com/downloads/metrostudio))的粉丝。我几乎只为 LightSwitch 命令使用图标,因为它们非常适合 LightSwitch 的世界性主题(参见[第 6 章](6.html#heading_id_40))。
将添加一个新的命令,并且像您的 LightSwitch 应用的几乎任何元素一样,您可以使用设计器来设置几个扩展属性。我们肯定要设置的一个属性是所使用的图像。就我个人而言,我真的成为了 Syncfusion 免费定制图标工具 Metro Studio([http://www.syncfusion.com/downloads/metrostudio](http://www.syncfusion.com/downloads/metrostudio))的粉丝。我几乎只为 LightSwitch 命令使用图标,因为它们非常适合 LightSwitch 的世界性主题(参见[第 6 章](6.html#heading_id_40))。
![](img/image054.jpg)
......@@ -133,7 +133,7 @@ LightSwitch 会生成几个类,如果您选择这样做,您可以使用这
![](img/image056.jpg)
图 55:显示紧急任务命令现在在应用程序中可见
图 55:显示紧急任务命令现在在应用中可见
点击**显示紧急任务**命令,我们新的搜索屏幕**我的紧急任务**打开。
......@@ -143,15 +143,15 @@ LightSwitch 会生成几个类,如果您选择这样做,您可以使用这
## 运行时屏幕编辑器
虽然我们的新屏幕很有用,但你可能想对它进行一些图形修改,比如隐藏**任务分配人**标签和文本框。Visual Studio LightSwitch 最令人瞠目结舌的功能之一是,如果您不想或者不熟悉 Silverlight XAML,您不必编写自定义 XAML 来修改用户界面。更好的是,如果你想改变屏幕上的布局或控件,你甚至不必停止运行你的应用程序并重新编译它。
虽然我们的新屏幕很有用,但你可能想对它进行一些图形修改,比如隐藏**任务分配人**标签和文本框。Visual Studio LightSwitch 最令人瞠目结舌的功能之一是,如果您不想或者不熟悉 Silverlight XAML,您不必编写自定义 XAML 来修改用户界面。更好的是,如果你想改变屏幕上的布局或控件,你甚至不必停止运行你的应用并重新编译它。
如果您从 Visual Studio IDE 启动 LightSwitch 应用程序(即附带调试器),该应用程序将有一个名为**设计屏幕**的命令,该命令使您能够在运行时进行这些修改并将其保留回您的 Visual Studio 解决方案!老实说,这可能是个人缺乏经验,但我不知道有任何其他技术允许你这样做,我喜欢它。在运行时设计应用程序的图形部分,而不必构建来测试每个修改,并且能够用实际的测试数据而不是“*Neque porro quisquam est qui dolorem ipsum quia dolor sit amet,consectetur,adipissi velit*”进行设计—此功能绝对节省时间!
如果您从 Visual Studio IDE 启动 LightSwitch 应用(即附带调试器),该应用将有一个名为**设计屏幕**的命令,该命令使您能够在运行时进行这些修改并将其保留回您的 Visual Studio 解决方案!老实说,这可能是个人缺乏经验,但我不知道有任何其他技术允许你这样做,我喜欢它。在运行时设计应用的图形部分,而不必构建来测试每个修改,并且能够用实际的测试数据而不是“*Neque porro quisquam est qui dolorem ipsum quia dolor sit amet,consectetur,adipissi velit*”进行设计—此功能绝对节省时间!
![](img/image058.jpg)
图 57:设计屏幕命令
单击应用程序命令栏中的**设计屏幕**命令。这将打开运行时版本的**屏幕编辑器**
单击应用命令栏中的**设计屏幕**命令。这将打开运行时版本的**屏幕编辑器**
![](img/image059.jpg)
......@@ -211,6 +211,6 @@ LightSwitch 会生成几个类,如果您选择这样做,您可以使用这
图 65:在运行时设计后的所有人屏幕
正如您可以编写自定义代码来响应应用程序中的许多预定义事件一样,您也可以完全控制用户界面,并为**可视化树设计器**中的任何元素编写自定义 Silverlight XAML。
正如您可以编写自定义代码来响应应用中的许多预定义事件一样,您也可以完全控制用户界面,并为**可视化树设计器**中的任何元素编写自定义 Silverlight XAML。
然而,因为这需要重建来编译 XAML,所以它不能从运行时版本的**屏幕设计器**中完成。
\ No newline at end of file
# 第六章应用程序编辑器
# 六、应用编辑器
## 扩展光开关应用
## 扩展LightSwitch应用
编写自定义代码或自定义用户控件有时被称为**一级可扩展性**。LightSwitch 允许您将应用程序扩展到开箱即用之外,并且不需要您完全安装 Visual Studio。独立版本的 LightSwitch 也提供一级可扩展性。
编写自定义代码或自定义用户控件有时被称为**一级可扩展性**。LightSwitch 允许您将应用扩展到开箱即用之外,并且不需要您完全安装 Visual Studio。独立版本的 LightSwitch 也提供一级可扩展性。
这表明,还有更高级别的可扩展性。**二级可扩展性**为 LightSwitch 应用程序添加了可在不同应用程序中重用的功能。它们通过 Visual Studio 扩展(。vsix ),可以直接从供应商处购买,也可以从 Visual Studio Gallery([http://visualstudiogallery.msdn.microsoft.com/site/search?)下载 query=LightSwitch & f%5B0%5D。值=灯光开关& f%5B0%5D。Type=SearchText & ac=8](http://visualstudiogallery.msdn.microsoft.com/site/search?query=LightSwitch&f%5B0%5D.Value=LightSwitch&f%5B0%5D.Type=SearchText&ac=8)
这表明,还有更高级别的可扩展性。**二级可扩展性**为 LightSwitch 应用添加了可在不同应用中重用的功能。它们通过 Visual Studio 扩展(。vsix ),可以直接从供应商处购买,也可以从 Visual Studio Gallery([http://visualstudiogallery.msdn.microsoft.com/site/search?)下载 query=LightSwitch & f%5B0%5D。值=灯LightSwitch& f%5B0%5D。Type=SearchText & ac=8](http://visualstudiogallery.msdn.microsoft.com/site/search?query=LightSwitch&f%5B0%5D.Value=LightSwitch&f%5B0%5D.Type=SearchText&ac=8)
传统上,这些扩展将为您的 Visual Studio LightSwitch IDE 或应用程序添加以下一项或多项功能:
传统上,这些扩展将为您的 Visual Studio LightSwitch IDE 或应用添加以下一项或多项功能:
* 可重复使用的 WCF 服务
* 可重用的业务类型
......@@ -15,11 +15,11 @@
* 可重复使用的外壳
* 可重用主题
最后两个,主题和外壳,提供了一种简单的方法,只需点击几下鼠标就可以改变应用程序的整体外观。
最后两个,主题和外壳,提供了一种简单的方法,只需点击几下鼠标就可以改变应用的整体外观。
## 在 Visual Studio 中安装扩展
关闭您的 LightSwitch 应用程序,在 Visual Studio 的**工具**菜单中,选择**扩展管理器**
关闭您的 LightSwitch 应用,在 Visual Studio 的**工具**菜单中,选择**扩展管理器**
![](img/image067.jpg)
......@@ -27,15 +27,15 @@
**扩展管理器**中,搜索**在线扩展**以获得 LightSwitch 主题、外壳或两者。点击**安装**按钮,然后关闭**扩展管理器**
## 激活应用程序中的扩展
## 激活应用中的扩展
要激活您选择的外壳或主题,请在**解决方案资源管理器**中选择 LightSwitch 项目并按 Alt+Enter,或者右键单击该项目并从上下文菜单中选择**属性**
![](img/image068.jpg)
图 67:打开应用程序设计器
图 67:打开应用设计器
这开启了第四个也是最后一个特定于光开关的设计者,即**应用程序设计者**
这开启了第四个也是最后一个特定于LightSwitch的设计者,即**应用设计者**
导航至**扩展**选项卡。
......@@ -43,37 +43,37 @@
图 68:激活扩展
**应用程序设计器**的这个选项卡中,您可以看到机器上所有 LightSwitch 特定扩展的概述。选中您已下载的扩展旁边的复选框,以便在此应用程序中激活它。
**应用设计器**的这个选项卡中,您可以看到机器上所有 LightSwitch 特定扩展的概述。选中您已下载的扩展旁边的复选框,以便在此应用中激活它。
在上图中,可以看到我下载了**light switch Cosmopolitan Shell 和主题**,现在作为新的默认 Shell 和主题包含在 Visual Studio LightSwitch 2012 RC 中。
## 常规属性选项卡
一旦激活,二级可扩展性功能——外壳和主题——可以在这个 LightSwitch 应用程序中使用。从**常规属性**选项卡中选择使用哪个外壳或主题。
一旦激活,二级可扩展性功能——外壳和主题——可以在这个 LightSwitch 应用中使用。从**常规属性**选项卡中选择使用哪个外壳或主题。
![](img/image070.jpg)
图 69:应用程序设计器的常规属性选项卡
图 69:应用设计器的常规属性选项卡
将选定的 **Shell** 更改为现在可用的 Shell,和/或将选定的**主题**更改为您下载的主题。
![](img/image071.jpg)
图 70:选择要在 LightSwitch 客户端应用程序中使用的外壳或主题
图 70:选择要在 LightSwitch 客户端应用中使用的外壳或主题
**常规属性**选项卡上的其他属性也值得快速查看:
* **申请名称**:申请名称,我改成了*我的时间,我的钱*
* **标志**:如果外壳支持的话要使用的标志(LightSwitch Cosmopolitan Shell 就是这么做的)
* **图标**:应用程序的图标。
* **版本:**应用的主要和次要发布版本。第三个数字,即修订号,会在您每次发布具有相同主版本和次版本的应用程序时附加。
* **培养:**应用的培养。这用于整个应用程序的全球化和翻译。目前,LightSwitch 一次只支持一种文化。
* **图标**:应用的图标。
* **版本:**应用的主要和次要发布版本。第三个数字,即修订号,会在您每次发布具有相同主版本和次版本的应用时附加。
* **培养:**应用的培养。这用于整个应用的全球化和翻译。目前,LightSwitch 一次只支持一种文化。
**F5** 构建和调试应用程序,看看你的应用程序的整个外观和感觉是如何变化的。
**F5** 构建和调试应用,看看你的应用的整个外观和感觉是如何变化的。
## 屏幕导航
**屏幕导航**选项卡允许您控制应用程序的导航菜单。屏幕可以被分成不同的组,并且顺序和标签可以用这个编辑器改变。
**屏幕导航**选项卡允许您控制应用的导航菜单。屏幕可以被分成不同的组,并且顺序和标签可以用这个编辑器改变。
![](img/image072.jpg)
......@@ -83,27 +83,27 @@
![](img/image073.jpg)
图 LightSwitch 应用程序没有像导航选项卡建议的那样的管理组
图 LightSwitch 应用没有像导航选项卡建议的那样的管理组
原因有两个:我们还没有激活**用户认证模式**,我们还没有访问这些屏幕的正确权限。两者都可以从**访问控制**选项卡进行更改。
## 访问控制选项卡
第四个**应用程序编辑器**选项卡提供了对身份验证模式的控制,允许您定义权限,并允许您强制 OData 端点的安全连接(参见[第 3 章](3.html#heading_id_16))。
第四个**应用编辑器**选项卡提供了对身份验证模式的控制,允许您定义权限,并允许您强制 OData 端点的安全连接(参见[第 3 章](3.html#heading_id_16))。
支持的三种身份验证模式是:
* **Windows 身份验证**:使用您的 Windows 凭据自动登录。建议在公司内部运行的应用程序
* **表单认证**:启动应用程序时出现登录屏幕,用户必须提供用户名和密码。建议用户来自不同公司的应用。
* **无**:启动应用,不需要认证。除非您是唯一的用户并且正在本地计算机上运行应用程序,否则绝不建议使用此身份验证模式。
* **Windows 身份验证**:使用您的 Windows 凭据自动登录。建议在公司内部运行的应用。
* **表单认证**:启动应用时出现登录屏幕,用户必须提供用户名和密码。建议用户来自不同公司的应用。
* **无**:启动应用,不需要认证。除非您是唯一的用户并且正在本地计算机上运行应用,否则绝不建议使用此身份验证模式。
![](img/image074.jpg)
图 73:应用程序设计者的访问控制选项卡
图 73:应用设计者的访问控制选项卡
对于此应用程序,将**认证模式**更改为**使用表单认证**。当应用程序从 Visual Studio 运行时,即附加了调试器,LightSwitch 将自动跳过登录屏幕,使用名为**测试用户**的用户登录。
对于此应用,将**认证模式**更改为**使用表单认证**。当应用从 Visual Studio 运行时,即附加了调试器,LightSwitch 将自动跳过登录屏幕,使用名为**测试用户**的用户登录。
说到授权,LightSwitch 实现了一个基于权限的系统。这些权限是在**应用程序设计器**的这个选项卡中定义的,以后可以通过自定义代码在任何需要的地方进行检查。这可以在屏幕级、实体级甚至操作级完成。
说到授权,LightSwitch 实现了一个基于权限的系统。这些权限是在**应用设计器**的这个选项卡中定义的,以后可以通过自定义代码在任何需要的地方进行检查。这可以在屏幕级、实体级甚至操作级完成。
通过选中唯一预定义权限(称为**安全管理**)旁边的**授权调试**复选框(见图 73),您可以将此权限添加到调试时将使用的**测试用户**中。按 F5 构建并开始调试,注意差异。
......@@ -113,31 +113,31 @@
对于那些不喜欢“寻找 7 个不同点”游戏的人来说,请注意现在右上角的 **CurrentUserControl** 显示 LightSwitch 确实已经自动登录了一个**测试用户**,这又是一个很好的时间节省。
**测试用户**也有**安全管理**权限,需要查看导航菜单中的**管理**组。该组包含两个屏幕,安全管理员可以在其中管理用户及其权限。请注意,当您部署应用程序时,您的测试数据没有部署,包括这些用户及其权限,因此在开发期间通过这些屏幕所做的更改不会反映在您的部署中。这些屏幕只有在部署应用程序后才会真正有用。
**测试用户**也有**安全管理**权限,需要查看导航菜单中的**管理**组。该组包含两个屏幕,安全管理员可以在其中管理用户及其权限。请注意,当您部署应用时,您的测试数据没有部署,包括这些用户及其权限,因此在开发期间通过这些屏幕所做的更改不会反映在您的部署中。这些屏幕只有在部署应用后才会真正有用。
说到这里…
## 应用类型选项卡
最后一个令人瞠目结舌的时刻到了,抵抗之声,我们交响乐的高潮。我们在这本电子书的开头将 Visual Studio LightSwitch 称为“为桌面或云构建以数据为中心的应用程序的最简单方法”,然而,在整个教程中,除了在[第 3 章](3.html#heading_id_16)中提到了服务器的公共 OData 端点之外,我们并没有真正说明应用程序的架构或目标平台。我们造了什么?单层桌面应用程序、多层应用程序还是可以托管在云中的 web 应用程序
最后一个令人瞠目结舌的时刻到了,抵抗之声,我们交响乐的高潮。我们在这本电子书的开头将 Visual Studio LightSwitch 称为“为桌面或云构建以数据为中心的应用的最简单方法”,然而,在整个教程中,除了在[第 3 章](3.html#heading_id_16)中提到了服务器的公共 OData 端点之外,我们并没有真正说明应用的架构或目标平台。我们造了什么?单层桌面应用、多层应用还是可以托管在云中的 web 应用
由于 LightSwitch 的元数据驱动实现,**应用程序设计器**的最后一个选项卡,称为**应用程序类型**选项卡,允许您在开发的最新可能阶段做出这些决定。这提供了比传统开发周期更多的应用程序灵活性,在传统开发周期中,您必须在一开始就决定您的应用程序开发环境。LightSwitch 的灵活性还允许您更改应用程序类型,而不必重做应用程序的整个部分。
由于 LightSwitch 的元数据驱动实现,**应用设计器**的最后一个选项卡,称为**应用类型**选项卡,允许您在开发的最新可能阶段做出这些决定。这提供了比传统开发周期更多的应用灵活性,在传统开发周期中,您必须在一开始就决定您的应用开发环境。LightSwitch 的灵活性还允许您更改应用类型,而不必重做应用的整个部分。
![](img/image076.jpg)
图 75:应用程序设计者的**应用程序类型**选项卡
图 75:应用设计者的**应用类型**选项卡
想想您开发的最新大型数据中心应用程序。假设应用程序最初是作为直接访问数据库的桌面应用程序编写的(单层),过了一段时间后,决定将其重构为一个名为 web 服务的 web 应用程序(多层)。重构应用程序需要多长时间?
想想您开发的最新大型数据中心应用。假设应用最初是作为直接访问数据库的桌面应用编写的(单层),过了一段时间后,决定将其重构为一个名为 web 服务的 web 应用(多层)。重构应用需要多长时间?
这个故事的 LightSwitch 版本来了。
一键将**客户端**类型更改为**网页**。这将自动禁止选择在与客户端相同的层上运行**应用服务器**。按 F5 构建并开始调试。
在构建过程中,LightSwitch 将采用您在**实体设计器**中设计的元数据,以及您在**查询设计器****屏幕设计器**中设计的任何元数据,以及您在**应用程序设计器**中做出的所有选择,来生成多层 web 应用程序
在构建过程中,LightSwitch 将采用您在**实体设计器**中设计的元数据,以及您在**查询设计器****屏幕设计器**中设计的任何元数据,以及您在**应用设计器**中做出的所有选择,来生成多层 web 应用
![](img/image077.jpg)
图 76:只需单击一下,就可以将单层桌面应用程序更改为多层 web 应用程序
图 76:只需单击一下,就可以将单层桌面应用更改为多层 web 应用
## 发布时间…
......
# 第七章继续前进
# 七、继续前进
## Visual Studio light switch 是正确的工具吗?
在过去的一年里,我花了相当多的时间研究 LightSwitch 产品,我在元数据驱动的实现中的旅程是一次改变生活的经历。LightSwitch 2012 RC 在客户端层使用了较新版本的 Silverlight,在服务器层使用了与其前身完全不同的技术(这也打开了应用程序,以任何其他技术创建客户端),事实上,我的 LightSwitch 1.0 应用程序可以在没有任何修改的情况下进行转换,这是一场重构之战,通常需要数年才能完成,这向我证明了 LightSwitch 在应用程序开发中获得了比我想象中更“正确”的东西。
在过去的一年里,我花了相当多的时间研究 LightSwitch 产品,我在元数据驱动的实现中的旅程是一次改变生活的经历。LightSwitch 2012 RC 在客户端层使用了较新版本的 Silverlight,在服务器层使用了与其前身完全不同的技术(这也打开了应用,以任何其他技术创建客户端),事实上,我的 LightSwitch 1.0 应用可以在没有任何修改的情况下进行转换,这是一场重构之战,通常需要数年才能完成,这向我证明了 LightSwitch 在应用开发中获得了比我想象中更“正确”的东西。
在一个集成开发环境中,公民开发人员、专业开发人员和专家开发人员一起在最短的时间内创建最佳的以数据为中心的应用程序
在一个集成开发环境中,公民开发人员、专业开发人员和专家开发人员一起在最短的时间内创建最佳的以数据为中心的应用。
传统上,公民开发人员的技术知识或编码技能有限,但他们比其他人更了解业务问题,可以使用简单而强大的编辑器来设计应用程序,而不会遇到砖墙,这是大多数快速应用程序开发集成开发人员所面临的问题,这要归功于众多的一级可扩展性点。
传统上,公民开发人员的技术知识或编码技能有限,但他们比其他人更了解业务问题,可以使用简单而强大的编辑器来设计应用,而不会遇到砖墙,这是大多数快速应用开发集成开发人员所面临的问题,这要归功于众多的一级可扩展性点。
专业开发人员可以远离他们觉得无聊的任务,因为他们觉得这不会对他们构成挑战,并专注于他们最擅长的事情:以二级扩展的形式交付可重用的功能:可重用的控制套件、业务类型、外壳、主题等。
微软 LightSwitch 团队作为专业开发人员,确保公民和专业开发人员的特征融合在强大的业务线应用程序中,这些应用程序遵循最佳和行业公认的技术和架构趋势。
微软 LightSwitch 团队作为专业开发人员,确保公民和专业开发人员的特征融合在强大的业务线应用中,这些应用遵循最佳和行业公认的技术和架构趋势。
如果手头的软件挑战与数据有关,这是在考虑 LightSwitch 是否适合您的需求时最大的“如果”,我会一直渴望使用 LightSwitch 来解决它,不仅仅是因为您可以从产品中获得令人厌倦的快速结果,还因为令人愉快的开发体验。
......@@ -20,5 +20,5 @@
* 微软官方的 LightSwitch 开发者中心([http://msdn.microsoft.com/en-us/lightswitch/default](http://msdn.microsoft.com/en-us/lightswitch/default))是一个很好的开始的地方。Beth Massi([www.BethMassi.com](http://www.BethMassi.com))被社区戏称为“LightSwitch 女神”,是公众可见度最高的 LightSwitch 高级项目经理,创作了无数“入门”视频和教程。入门级别和专家级别主题的新内容至少每周添加一次。每月都会发布一个很棒的社区内容“汇总”,上面有 MSDN 论坛的链接,如果其他社区成员还没有解决问题,LightSwitch 团队成员会帮助你解决任何问题。
* 迈克尔·华盛顿,LightSwitch 社区最伟大的摇滚明星之一,主持着 LightSwitch 帮助网站([http://www.LightSwitchHelpWebsite.com](http://www.LightSwitchHelpWebsite.com))。这个非官方的社区门户提供了很多很好的链接,一个社区成员互相帮助的论坛,一个任何人都可以出售他或她的服务和扩展的市场。迈克尔经常用新的创新文章来款待来访者,这些文章更多的是为专家而不是新手准备的。
* 你会发现 LightSwitch 社区中其他摇滚明星的许多有趣的私人博客散布在互联网上。这些博客代表了作者的不同背景,通常关注 LightSwitch 非常不同的方面,或者从非常不同的角度来看待它。例如,我的个人博客([http://janvanderhaegen.wordpress.com](http://janvanderhaegen.wordpress.com))只关注框架的内部,而保罗·帕特森的博客([http://www.paulspatterson.com/](http://www.paulspatterson.com/))展示了一些惊人的工艺,即使是公民开发者也能做到。本书简介中的[图片](LightSwitch_Succinctly_0003.htm#heading_id_2)展示了一个名为“一点生产力”的 LightSwitch 应用程序,他在不到一周的时间内创建并部署到 Azure 上——他在博客中对此经历进行了深入探讨。
* 你会发现 LightSwitch 社区中其他摇滚明星的许多有趣的私人博客散布在互联网上。这些博客代表了作者的不同背景,通常关注 LightSwitch 非常不同的方面,或者从非常不同的角度来看待它。例如,我的个人博客([http://janvanderhaegen.wordpress.com](http://janvanderhaegen.wordpress.com))只关注框架的内部,而保罗·帕特森的博客([http://www.paulspatterson.com/](http://www.paulspatterson.com/))展示了一些惊人的工艺,即使是公民开发者也能做到。本书简介中的[图片](LightSwitch_Succinctly_0003.htm#heading_id_2)展示了一个名为“一点生产力”的 LightSwitch 应用,他在不到一周的时间内创建并部署到 Azure 上——他在博客中对此经历进行了深入探讨。
* 我还创建了一个机器人,可以监控不同的官方和非官方来源,包括一些最有经验的社区成员的博客,如扬·杜兰、扬·德·洪特、《SD 时报》、丹·比尔、保罗·范·布莱德尔、基思·克雷戈、科斯塔斯·赫里斯托多洛、斯图(stuxstu)、雷根·阿什沃斯、阿莱桑德罗·德尔·索尔、迈克尔·华盛顿、巴拉(Tek Freak)、蒂姆·梁、保罗·帕特森、朱厄尔·兰伯特和拉什米·朗扬·帕尼格拉希。每当网上出现任何有趣的 LightSwitch 素材,机器人都会在 [@LightSwitchNews](https://twitter.com/lightswitchnews) 账号下推文。如果你觉得这个名单上少了一个人,我必须道歉,因为这是我无知的表现。请随时告诉我,我会很高兴让机器人更新。
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册