이 글에서는 주로 모두와 함께 쿠키에 대해 이야기하고 있습니다. 중국어로 쿠키를 이해해야 한다면 넷스케이프 창립자 중 한 명인 루 몬트레이가 1993년에 발명한 작은 텍스트 파일이어야 합니다. 이 기사가 모든 사람에게 도움이 되기를 바랍니다.
웹사이트를 열고 웹사이트를 탐색하는 가장 일반적인 두 가지 작업은 등록과 로그인이므로 이 두 기능이 어떻게 구현되는지 살펴볼 필요가 있습니다.
로컬 시뮬레이션, localhost:8080/sign_up
을 입력하면 브라우저가 get
요청을 시작하고 서버가 sign_up.html
에 응답합니다. localhost:8080/sign_up
的时候,浏览器发起get
请求,服务器给你响应sign_up.html
//服务器端代码 if (path === '/sign_up' && method === 'GET') { let string = fs.readFileSync('./sign_up.html', 'utf8') response.statusCode = 200 response.setHeader('Content-Type', 'text/html;charset=utf-8') response.write(string) response.end() }
在写sign_up.html
的时候,注意几点css知识:
如果想让你的登录页面的body占满整个屏幕,随着窗口的大小变化而变化的话,可以写
body, html{height: 100%} //或者 body{min-height: 100%} html{height: 100%} //不能这么写 body, html{min-height: 100%}
当然了,实际上这么写就可以了
body{min-height: 100vh}
label
标签是display: inline
,不能设置宽度,行内元素则会根据行内内容自适应宽度,所以行内元素设置width是没有效果的。改成inline-block就可以了
既然是注册的需求,那么我们首要关注的点就是--用户的注册信息我们如何获得呢
选择合理的数据结构存储数据是很重要的。
每个input
的name
可以使用数组存储
input
的value
应该使用hash
,也就是对象来存储。
上述的套路会一直用下去,hash+[]
的组合。
//使用jq来写 let hash = {} let $form = $('#signUpForm') $form.on('submit', (e) => { e.preventDefault() //不用form表单的默认提交,而是使用我们的的ajax提交 let need = ['email', 'password', 'password_confirmation'] need.forEach((name) => { let value = $form.find(`[name=${name}]`).val() hash[name] = value })
最终hash
里面存储的就是
{ 'email': '...', 'password': '...', 'password_confirmation': '...' }
到目前为止我们把用户的数据封装到了一个对象里面了。
不过在把hash用ajax发出去之前要先进行一些必要的非空验证
主要是检测邮箱是否为空、密码是否为空、两次输入的密码是否一致。
//发起请求之前验证是否为空 if (hash['email'] === '') { $form.find('[name="email"]').siblings('.errors').text('请您输入邮箱') return false //精髓啊,不然没用了 } if (hash['password'] === '') { $form.find('[name="password"]').siblings('.errors').text('请您输入密码') return false //精髓啊,不然没用了 } if (hash['password_confirmation'] === '') { $form.find('[name="password_confirmation"]').siblings('.errors').text('请您再次输入确认密码') return false //精髓啊,不然没用了 } if (hash['password'] !== hash['password_confirmation']) { $form.find('[name="password_confirmation"]').siblings('.errors').text('两次输入密码不匹配') return false //精髓啊,不然没用了 }
如果忘记写return的话,即使你为空了还是会直接越过这一步检测,去发起ajax请求的,所以一定不要忘了写上return false.
如果仅仅这么写的话会有一个bug。当出现错误提示后,你把信息填对了,错误信息依然显示,这显然是不合理的。应该填入信息后,错误信息就消失的。
$form.find('.errors').each((index, span) => { $(span).text('') })
使用上述的jq代码来解决这个bug即可。
非空验证完了之后,意味着浏览器收集用户数据的工作完成了,可以把hash发到服务器端了,接下来就是ajax请求了。
$.post('/sign_up', hash) .then((response) => { //成功了就打印这个 console.log(response) }, () => { //错误了打印这个 })
因为formData是一段一段上传的(具体原因略复杂,可以取极限法,如果formdata很多,不可能一下子上传过来),自己不会写,就去搜索代码片段解析formdata
google: node get post data
把获得的代码封装成了一个函数
function readBody(request) { return new Promise((resolve, reject) => { let body = [] request.on('data', (chunk) => { body.push(chunk) }).on('end', () => { body = Buffer.concat(body).toString(); resolve(body) }) } ) }
如何使用上述代码片段呢
... if (path === '/sign_up' && method === 'POST') { readBody(request).then((body) => { let strings = body.split('&') //['email=1', 'password=2', 'password_confirmmation=3'] let hash = {} strings.forEach(string => { //想得到类似这种的 string == 'email=1' let parts = string.split('=') //再用=分割,得到['email', '1'] let key = parts[0] let value = parts[1] hash[key] = decodeURIComponent(value)//hash['email'] = '1' }) let {email, password, password_confirmation} = hash //ES6的解构赋值 } ...
当服务器端接收到了所有的formdata数据后,其实是一串形如email=1&password=2&password_confirmation=3
的字符串,所以我们考虑使用&
字符分割成数组。
得到一个形如['email=1', 'password=2', 'confirmation=3']
的数组之后,我们为了得到string = 'email=1'
这种形式的,开始遍历数组,把数组的每个元素按照=
分割,得到 [email, 1]
用第二小节提供的hash+[]
方法,处理成hash
既然服务器端已经获得了formdata
let email = hash['emai'] let password = hash['password'] let password_confirmation = hash['password_confirmation']
sign_up.html
을 작성할 때 몇 가지 CSS 지식에 주의하세요.let {email, password, password_confirmation} = hash
if (email.indexOf('@') === -1) { response.statusCode = 400 response.write('email is bad') //单引号只是为了标记这是一个字符串 }
label
레이블은 display: inline
이며 너비는 인라인 요소로 설정할 수 없습니다. 인라인 콘텐츠에 따라 자동으로 조정됩니다. 너비에 맞게 조정되므로 인라인 요소의 너비 설정은 효과가 없습니다. inline-block
입력
의 이름
은 배열을 사용하여 저장할 수 있습니다🎜값
은 객체인 해시
를 사용해 저장해야 합니다. 🎜hash+[]
조합으로 계속 사용됩니다. 🎜console.log(email.indexOf('@')) console.log(email)
hash
에 저장된 것은 🎜hash[key] = decodeURIComponent(value)
if (email.indexOf('@') === -1) { response.statusCode = 400 response.setHeader('Content-Type', 'application/json;charset=utf-8') //直接告诉浏览器我是json response.write(` { "errors": { "email": "invalid" } } `) }
$.post('/sign_up', hash) .then((response) => { //成功了就打印这个 console.log(response) }, (request, b, c) => { console.log(request) console.log(b) console.log(c) })
(request) => { let {errors} = request.responseJSON if (errors.email && errors.email === 'invalid') { $form.find('[name="email"]').siblings('.errors').text('您输入的邮箱错啦') } }
google: node get post data
🎜🎜얻은 코드를 함수로 캡슐화합니다🎜var users = fs.readFileSync('./db/users', 'utf8') try { users = JSON.parse(users) //[] JSON也支持数组 } catch (exception) { users = [] } let inUse = false for (let i = 0; i < users.length; i++) { let user = users[i] if (user.email === email) { inUse = true break } } if (inUse) { response.statusCode = 400 response.setHeader('Content-Type', 'application/json;charset=utf-8') response.write(` { "errors": { "email": "inUse" } } `) }
if (errors.email && errors.email === 'inUse') { $form.find('[name="email"]').siblings('.errors').text('这个邮箱已被注册啦') }
email=1&password=2&password_confirmation=3
🎜🎜 형태의 문자열이 있기 때문에 &
문자를 사용하여 배열로 분할하는 것을 고려합니다. 🎜['email=1', 'password=2', 'confirmation=3']</code 형태의 배열을 얻은 후 >, <code>string = 'email=1'
형식을 얻기 위해 배열 순회를 시작하고 =
에 따라 배열의 각 요소를 분할하고 <를 얻습니다. code>[email , 1]🎜hash+[]
메소드를 사용하여 해시로 처리하세요🎜formdata
를 얻었으니 메일함 형식 등의 간단한 검증을 수행해야 합니다. 문제가 없다면 데이터는 다음과 같습니다. 데이터베이스에 저장됩니다. (현재 검증 수준은 매우 기본적이며 완전한 등록 검증 기능을 포함하지 않습니다)🎜🎜검증 전 준비 작업🎜🎜이전 섹션에서는 양식 데이터를 해시에 완벽하게 캡슐화했습니다. 해시를 하나씩 열어서 살펴보세요🎜🎜아마도 이것이 가장 직접적인 방법일 것입니다🎜users.push({email: email, password: password})//是个对象啊 var usersString = JSON.stringify(users) fs.writeFileSync(&amp;#39;./db/users&amp;#39;, usersString) response.statusCode = 200
我是菜鸟级校验邮箱,看到了邮箱的独特标志---@
,最起码有这个标志才叫邮箱吧,也就是说没有这个标志,我就可以认为邮箱格式不对啊,翻译成代码就是
if (email.indexOf(&amp;#39;@&amp;#39;) === -1) { response.statusCode = 400 response.write(&amp;#39;email is bad&amp;#39;) //单引号只是为了标记这是一个字符串 }
很好,目前来说,事情的发展都很正常,直到一个bug的到来。
一个合法的邮箱,却进入了非法邮箱处理的代码片段里面……
毫无疑问,邮箱是合法的,代码也是合理的,那么出问题的必然是我,某个地方的理解有问题。
找bug,把可能出错的代码片段分成几个区间,打log.
console.log(email.indexOf(&amp;#39;@&amp;#39;)) console.log(email)
没错,email
这个字符串的@
索引真的是-1,可是我的邮箱写的明明有@
啊。
为啥呢,接着又打印出了email
的内容,终于真相大白了,email
字符串里面真的没有@
,
却发现了一串你没想到的%40
,(⊙v⊙)嗯,没错了,这就是我认为的那个@
的另一个形态。
我在浏览器看到的只是浏览器想让我看到的东西而已,既然已经被浏览器处理了,那到了服务器端自然无法处理。
那这个%40
哪来的呢
Google走起,在w3schools的HTML URL Encoding Reference找到了解释(不是国内的w3school……)
URL encoding converts characters into a format that can be transmitted over the Internet.
URL编码把字符转化成了一种可以在互联网上传播的格式,也就是说,我在网页上看到的字符是被URL编码处理的结果。
那接下来就去搞定什么是URL编码
搞定这个之前,文档先要让你明白啥是URL
Web browsers request pages from web servers by using a URL.The URL is the address of a web page, like: https://www.w3schools.com.
Web浏览器通过使用URL从Web服务器请求页面。 该网址是网页的地址,例如:https://www.w3schools.com。
复习一下URL的组成6部分:
https://www.baidu.com/s?wd=he... 通过这个你就可以访问到一个 "唯一的" 网址
名字 | 作用 |
---|---|
https: | 协议 |
www.baidu.com | 域名 |
/s | 路径 |
wd=hello&rsv_spt=1 | 查询参数 |
#5 | 锚点 |
端口 | 默认80 |
复习完了URL
,继续搞URL编码
URLs can only be sent over the Internet using the ASCII character-set.Since URLs often contain characters outside the ASCII set, the URL has to be converted into a valid ASCII format.
URL encoding replaces unsafe ASCII characters with a "%" followed by two hexadecimal digits.
URLs cannot contain spaces. URL encoding normally replaces a space with a plus (+) sign or with %20.
URL只能用ASCII编码在互联网之间发送。
既然URL通常包括ASCII字符编码集之外的字符(很明显嘛,ASCII码表太少),所以URL必须转化成有效的ASCII格式。
这是重点,URL编码使用%
后面紧跟着两个16进制数字的编码格式来代替不安全的ASCII码表
URL不能包括空格。所以URL编码通常使用+号或者20%
来代替空格。
继续往下翻,找到了%40
。
所以要把value
的值解码回去
hash[key] = decodeURIComponent(value)
decodeURIComponent()
方法用于解码由 encodeURIComponent
方法或者其它类似方法编码的部分统一资源标识符(URI)。毕竟URL
属于URI
。
如果有了错,需要提示用户错了,后端写的代码,用户不一定看的懂,需要前端润色一下使用户看懂,或者前端和后端沟通一下,maybe后端脾气不好,前端也是暴脾气,所以应该选择一个前后端都要用的东西做桥梁,很明显JSON
是完美的候选人。
if (email.indexOf(&amp;#39;@&amp;#39;) === -1) { response.statusCode = 400 response.setHeader(&amp;#39;Content-Type&amp;#39;, &amp;#39;application/json;charset=utf-8&amp;#39;) //直接告诉浏览器我是json response.write(` { &quot;errors&quot;: { &quot;email&quot;: &quot;invalid&quot; } } `) }
这就合理多了,后台只管写个json给前台看,其他不管了,前台翻译一下给用户看喽~
那么前台如何获得这个json
呢
$.post(&amp;#39;/sign_up&amp;#39;, hash) .then((response) =&gt; { //成功了就打印这个 console.log(response) }, (request, b, c) =&gt; { console.log(request) console.log(b) console.log(c) })
忘记了错误函数里面的参数是啥了,那就都打印出来看看。
可以看到,如果没用JSON的话,request对象里面有一个后端写的responseText属性可以利用。
设置了Content-Type:application/json;charset=utf-8
之后,可以利用多出来的responseJSON
属性,获得json的内容啊。
最终失败函数里面写
(request) =&gt; { let {errors} = request.responseJSON if (errors.email &amp;&amp; errors.email === &amp;#39;invalid&amp;#39;) { $form.find(&amp;#39;[name=&quot;email&quot;]&amp;#39;).siblings(&amp;#39;.errors&amp;#39;).text(&amp;#39;您输入的邮箱错啦&amp;#39;) } }
var users = fs.readFileSync(&amp;#39;./db/users&amp;#39;, &amp;#39;utf8&amp;#39;) try { users = JSON.parse(users) //[] JSON也支持数组 } catch (exception) { users = [] } let inUse = false for (let i = 0; i &lt; users.length; i++) { let user = users[i] if (user.email === email) { inUse = true break } } if (inUse) { response.statusCode = 400 response.setHeader(&amp;#39;Content-Type&amp;#39;, &amp;#39;application/json;charset=utf-8&amp;#39;) response.write(` { &quot;errors&quot;: { &quot;email&quot;: &quot;inUse&quot; } } `) }
本文并没有使用真正意义上的数据库,只是使用了简单的db文件做数据库,其实就是存的数组,也就是users其实就是数组[]
。
之所以使用了try{}catch(){}
,是因为一旦除了错,可以将其初始化为空数组,后续代码可以继续执行,可能并不严谨,不过本文是侧重了解注册的思路的。
同样的,如果邮箱已经存在了,就提示用户
if (errors.email &amp;&amp; errors.email === &amp;#39;inUse&amp;#39;) { $form.find(&amp;#39;[name=&quot;email&quot;]&amp;#39;).siblings(&amp;#39;.errors&amp;#39;).text(&amp;#39;这个邮箱已被注册啦&amp;#39;) }
后端校验必须很严格,因为可以通过curl
越过前端的校验。
没有错误之后,就可以把信息写到数据库里面啦
users.push({email: email, password: password})//是个对象啊 var usersString = JSON.stringify(users) fs.writeFileSync(&amp;#39;./db/users&amp;#39;, usersString) response.statusCode = 200
users实现是个对象,而对象是内存里面的东西,数据库里面应该存储的是字符串,所以用了JSON.stringify(users)
相关推荐:
위 내용은 쿠키를 함께 배워볼까요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!