用户登录 之 准备

写在前面

与之前静态页面相关的内容不同,要实现 用户登录,必然涉及到 数据的交互
在所有开始之前,我们需要了解下,一般前端与后端之间是如何实现数据的交互的。在 HTML 层面上,如果不引入 Javascript,要实现前后端的关联,会使用 FORM 这个 DOM 元素,然后在 FORM 内填充数据的字段元素。
FORM 以中文的术语是 表单,关于表单设计,还可以引出几本砖头大的书,但于我们没有什么必要,它可以是非常专业的(保持敬畏),也可以不专业(别被吓到),只要 表达 到位即可。

注: 前端 主要指基于用户使用的浏览器端的技术,而后端主要指由程序员控制、实现的服务(器)端的相关技术。

FORM 与 INPUT 元素

FORM 其实跟 HTML 常用的 DOM 元素 DIV 差不多,只是类型不同,浏览器赋予它的默认表现、交互行为不同而已,在涉及到表单 (需要用户填表、提交数据用的),一般是元素 FORM (相当于一个大容器)包含多个 INPUT 字段,从而构建整个表单。

比如下面这个表单:

其对应的 Jade 源码:

form#form_one(action="", method="POST")
    div.form_field.username
        label Username
        input(type="text", name="username", placeholder="hepo")
    div.form_field.password
        label Password
        input(type="password", name="password", placeholder="123456")
    div.form_field.submit
        input(type="submit", value="登录")

简单说下代码中的一些含义:
form#form_one(action="", method="POST"),一般会给 FORM 以一个 id,比如这里的 form_one,因为多数时候需要对 FORM 进行操作,有 id 则方便识别、调用、控制。action 表示数据往哪个 URL 提交,如果没有指定或为空,表示往当前页面的 URL 提交;method 是提交数据的方式,一般是 POST

div.form_field.username
    label Username
    input(type="text", name="username", placeholder="hepo")

这段代码,使用了之前介绍的常见布局方法,先外部包裹有一个 DIV,form_field 是一个通用的 class,username 是当前这个 field 特殊指定的。label 一般在 FORM 内配合 INPUT 使用,label 有一个特殊的属性 for,你可以在源代码中尝试修改为 label(for="username") Username, 然后给后面 username 一个 id=username 的属性;这时,界面上点击 label 中的文本,光标会自动 focus 到 INPUT 这个元素之中。
重点需要说明的是 INPUT,它有多个 type,比如 text、password、radio、checkbox、submit、hidden(隐藏的元素,但可以有 value 以便在提交时一并传给服务器),不同 type 在视觉、交互表现上也不一样。

INPUT 除了 type 之外,其它一些非常重要的属性:

  • name: 如果没有 name,则服务端上获得对应的数据会超级不方便;一般情况下,当前 FORM 内 name 最好是唯一的,不要重复。
  • id: 就是普通的 DOM id,一般情况不用指定,如需操作当前字段的 DOM 元素,则建议设定。
  • placeholder: 输入型的 type 中有效,可以通过这个属性,给用户以提醒。

Jade 的温故知新

我们在最开始的时候,介绍如何使用 Jade 代替 HTML,包括之前处理静态页面的时候,也基本上使用了 Jade 的代码来写。
接下来,因为动态页面,会很自然地引入 变量 这个概念,需要此时对 Jade 的基本语法重新捋一遍,建议可以翻回到前面再看一看。
本段落,主要针对 Demo 中源码片段,做逐行的解释,以增加大家的理解。

if request.method == 'POST'  --> 逻辑判断
    h2 来自浏览器的数据交互: --> 
    p --> P 标签
        span Method: --> SPAN 标签 + 普通文本
        b= request.method --> B 标签(加粗效果) + 变量(=后面多个空格)
    p --> P 标签
        span Data: --> SPAN 标签 + 普通文本
        pre= request.values.to_dict().json  --> PRE 标签 + 变量(=后面多个空格)

request.methodrequest.values.to_dict().json,这些变量都不是天然形成的,而是 FirstWeb 的基本 Web 引擎 farbox_lite 带来的,所以我们并不需要特别记住这些变量以及属性,因为它们的适用性仅限于 FirstWeb 中。以 request 为例,它是当前浏览器 请求 所包含的各种信息,我们将其统一归纳到一个变量对象,名为 request;而 request.form 表示是 POST 这个 method时浏览器传入的各种值request.args 则针对 GETrequest.valuesPOST+GET 的合集。
request.values.to_dict().json 它翻译成人类的语言,大抵是: 先取 request 上的一个叫 values 的属性(得到了一个变量),调用其另外一个属性 to_dict,这个属性是一个函数(用()结尾表示无参数时的函数运行),获得变量之后,再获取其 json 这个属性(作用是转为 JSON 格式的字符串)。

A 与 INPUT 元素

在介绍 INPUT 的时候,说它是有不同 type 的,比如 submit 这个类型,表现行为相当于是一个按钮,点击『按钮』的时候,就会提交表单内的数据了;没有 submit,默认就没有办法提交数据了。
多数时候,有 FORM 的地方,就有 Javascript,与此同时,因为 Javascript 的介入, 我们可以将 submit 的行为,移到其它 DOM 元素上。此时, A 元素(超链接) 是非常天然的替代元素。

在 Demo 的页面中,我们也做了这个演示:

document.getElementById('form_two').submit(); // 原生 Javascript 提交
$('#form_two').submit(); //由 jQuery 提交

h.load 是什么

FirstWeb 的框架源自于 Bitcron,有些 API 的调用方式 (如 Jade 模板的特定的语法、默认的变量) 也尽可能保持兼容,主要是 d (data)html (h) 这两个变量空间 (此处空间其实就是一个大的变量集合,可供内部调用子属性子函数)。具体参考 https://api.bitcron.com/read/d 以及 https://api.bitcron.com/read/h

在后续的 Demo 的源码中,我们会看到如下 h.load 的函数调用,它可以同时载入 .js.css,但也仅是 FirstWeb 中动态框架 ( template 目录下的文件)中生效。其本质而言,不过是 技术在不断弥合人类的懒惰,因为,就不用特别去记忆了 js、css 分别如何载入的 HTML 语法了。

示例源码:

+h.load('/template/script.js')
+h.load('/template/style.css')

最终实际会解析为:

<script type="text/javascript" src="/template/frontend/script.js"></script>
<link href="/template/frontend/style.css" type="text/css" rel="stylesheet"/>

继续

好了,我们继续去实现『如何实现账户的登录』……