> 웹 프론트엔드 > JS 튜토리얼 > 쿠키를 함께 배워볼까요?

쿠키를 함께 배워볼까요?

小云云
풀어 주다: 2018-02-09 14:35:46
원래의
1814명이 탐색했습니다.

이 글에서는 주로 모두와 함께 쿠키에 대해 이야기하고 있습니다. 중국어로 쿠키를 이해해야 한다면 넷스케이프 창립자 중 한 명인 루 몬트레이가 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()
 }
로그인 후 복사

CSS布局的几个小坑

在写sign_up.html的时候,注意几点css知识:

  1. 如果想让你的登录页面的body占满整个屏幕,随着窗口的大小变化而变化的话,可以写

body, html{height: 100%}
//或者
body{min-height: 100%}
html{height: 100%}
//不能这么写
body, html{min-height: 100%}
로그인 후 복사

当然了,实际上这么写就可以了

body{min-height: 100vh}
로그인 후 복사
  1. label标签是display: inline,不能设置宽度,行内元素则会根据行内内容自适应宽度,所以行内元素设置width是没有效果的。改成inline-block就可以了

쿠키를 함께 배워볼까요?

获得用户的数据

既然是注册的需求,那么我们首要关注的点就是--用户的注册信息我们如何获得呢

选择合理的数据结构存储数据是很重要的。

  1. 每个inputname可以使用数组存储

  2. inputvalue应该使用hash,也就是对象来存储。

  3. 上述的套路会一直用下去,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请求了。

使用ajax提交数据

$.post('/sign_up', hash)
.then((response) => {
  //成功了就打印这个  
  console.log(response)
},
() => {
  //错误了打印这个
})
로그인 후 복사

服务器端解析formData

因为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']
로그인 후 복사

CSS 레이아웃의 여러 함정

sign_up.html을 작성할 때 몇 가지 CSS 지식에 주의하세요.

  1. 만약 로그인 페이지의 본문이 전체 화면을 채우고 창 크기가 변경됨에 따라 변경되도록 하려면

let {email, password, password_confirmation} = hash
로그인 후 복사

라고 쓰면 됩니다. 물론 실제로는 이렇게 쓸 수 있습니다

if (email.indexOf('@') === -1) {
  response.statusCode = 400
  response.write('email is bad') //单引号只是为了标记这是一个字符串
}
로그인 후 복사
로그인 후 복사
< ol class=" list-paddingleft-2">
  • label레이블은 display: inline이며 너비는 인라인 요소로 설정할 수 없습니다. 인라인 콘텐츠에 따라 자동으로 조정됩니다. 너비에 맞게 조정되므로 인라인 요소의 너비 설정은 효과가 없습니다. inline-block

  • 쿠키를 함께 배워볼까요?

    사용자 데이터 가져오기🎜🎜등록 요구 사항이므로 첫 번째 초점은 사용자의 등록 정보입니다. get it🎜🎜데이터를 저장하기 위해서는 합리적인 데이터 구조를 선택하는 것이 매우 중요합니다. 🎜
    1. 🎜각 입력이름은 배열을 사용하여 저장할 수 있습니다🎜
    2. 🎜< 코드>입력의 은 객체인 해시를 사용해 저장해야 합니다. 🎜
    3. 🎜위 루틴은 hash+[] 조합으로 계속 사용됩니다. 🎜
    console.log(email.indexOf(&amp;amp;#39;@&amp;amp;#39;))
    console.log(email)
    로그인 후 복사
    로그인 후 복사
    🎜결국 hash에 저장된 것은 🎜
    hash[key] = decodeURIComponent(value)
    로그인 후 복사
    로그인 후 복사
    🎜입니다. 지금까지 우리는 사용자의 데이터를 객체로 캡슐화했습니다. 🎜🎜하지만 Ajax를 사용하여 해시를 보내기 전에 비어 있지 않은 확인을 수행해야 합니다.🎜🎜비어 있지 않은 확인🎜🎜주로 이메일이 비어 있는지, 비밀번호가 비어 있는지, 두 번 입력한 비밀번호가 올바른지 여부를 감지합니다. 일관된. 🎜
    if (email.indexOf(&amp;amp;#39;@&amp;amp;#39;) === -1) {
      response.statusCode = 400
      response.setHeader(&amp;amp;#39;Content-Type&amp;amp;#39;, &amp;amp;#39;application/json;charset=utf-8&amp;amp;#39;) //直接告诉浏览器我是json
      response.write(`
        {
          &amp;quot;errors&amp;quot;: {
          &amp;quot;email&amp;quot;: &amp;quot;invalid&amp;quot;
          }
        }
      `)
    }
    로그인 후 복사
    로그인 후 복사
    • 🎜 return 작성을 잊어버리면 비어 있더라도 이 감지 단계를 바로 건너뛰고 ajax 요청을 시작하게 되므로 잊지 마세요. false를 반환합니다.🎜
    • 🎜이렇게만 쓰면 버그가 발생합니다. 오류 메시지가 나타나고 정보를 올바르게 입력해도 여전히 오류 메시지가 표시됩니다. 이는 분명히 불합리한 일입니다. 정보를 입력한 후에는 오류 메시지가 사라져야 합니다. 🎜
    🎜쿠키를 함께 배워볼까요?🎜
    $.post(&amp;amp;#39;/sign_up&amp;amp;#39;, hash)
    .then((response) =&amp;gt; {
      //成功了就打印这个  
      console.log(response)
    },
    (request, b, c) =&amp;gt; {
       console.log(request)
       console.log(b)
       console.log(c)
    })
    로그인 후 복사
    로그인 후 복사
    🎜이 버그를 해결하려면 위의 jq 코드를 사용하세요. 🎜🎜비어있지 않은 확인이 완료되면 브라우저가 사용자 데이터 수집 작업을 완료했으며 해시를 서버로 보낼 수 있다는 의미입니다. 다음 단계는 Ajax 요청입니다. 🎜🎜ajax를 사용하여 데이터 제출🎜
    (request) =&amp;gt; {
      let {errors} = request.responseJSON    
      if (errors.email &amp;amp;&amp;amp; errors.email === &amp;amp;#39;invalid&amp;amp;#39;) {
        $form.find(&amp;amp;#39;[name=&amp;quot;email&amp;quot;]&amp;amp;#39;).siblings(&amp;amp;#39;.errors&amp;amp;#39;).text(&amp;amp;#39;您输入的邮箱错啦&amp;amp;#39;)
      }
    }
    로그인 후 복사
    로그인 후 복사
    🎜서버 측 파싱 formData🎜🎜formData는 하나씩 업로드되기 때문에 (구체적인 이유는 조금 복잡해서 극단적인 방법을 써도 되지만, formdata가 많으면 불가능합니다) 한꺼번에 업로드하려면), 제가 직접 작성할 수는 없고, 코드 조각을 검색하여 formdata를 구문 분석하기만 하면 됩니다🎜🎜google: node get post data🎜🎜얻은 코드를 함수로 캡슐화합니다🎜
    var users = fs.readFileSync(&amp;amp;#39;./db/users&amp;amp;#39;, &amp;amp;#39;utf8&amp;amp;#39;)
    try {
      users = JSON.parse(users) //[] JSON也支持数组
    } catch (exception) {
      users = []
    }
    let inUse = false
    for (let i = 0; i &amp;lt; users.length; i++) {
      let user = users[i]
      if (user.email === email) {
        inUse = true
        break
      }
    }
    if (inUse) {
      response.statusCode = 400
      response.setHeader(&amp;amp;#39;Content-Type&amp;amp;#39;, &amp;amp;#39;application/json;charset=utf-8&amp;amp;#39;)
      response.write(`
        {
          &amp;quot;errors&amp;quot;: {
          &amp;quot;email&amp;quot;: &amp;quot;inUse&amp;quot;
          }
        }
      `)
    }
    로그인 후 복사
    로그인 후 복사
    🎜위 코드 스니펫 사용법🎜
    if (errors.email &amp;amp;&amp;amp; errors.email === &amp;amp;#39;inUse&amp;amp;#39;) {
        $form.find(&amp;amp;#39;[name=&amp;quot;email&amp;quot;]&amp;amp;#39;).siblings(&amp;amp;#39;.errors&amp;amp;#39;).text(&amp;amp;#39;这个邮箱已被注册啦&amp;amp;#39;)
    }
    로그인 후 복사
    로그인 후 복사
    🎜서버가 모든 formdata 데이터를 수신할 때 실제로는 email=1&amp;amp;password=2&amp;amp;password_confirmation=3🎜🎜 형태의 문자열이 있기 때문에 &amp; 문자를 사용하여 배열로 분할하는 것을 고려합니다. 🎜
    • 🎜 ['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;amp;#39;./db/users&amp;amp;#39;, usersString)
       response.statusCode = 200
      로그인 후 복사
      로그인 후 복사
      🎜하지만 ES6에서는 구조 분해 할당을 위한 일종의 구문 설탕을 제공하는데 이는 매우 달콤하고 사려 깊습니다...🎜rrreee🎜버그 @coding🎜🎜알겠습니다. 이 단계에서는 먼저 이메일 형식이 올바른지 확인합니다. 🎜

      我是菜鸟级校验邮箱,看到了邮箱的独特标志---@,最起码有这个标志才叫邮箱吧,也就是说没有这个标志,我就可以认为邮箱格式不对啊,翻译成代码就是

      if (email.indexOf(&amp;amp;#39;@&amp;amp;#39;) === -1) {
        response.statusCode = 400
        response.write(&amp;amp;#39;email is bad&amp;amp;#39;) //单引号只是为了标记这是一个字符串
      }
      로그인 후 복사
      로그인 후 복사

      很好,目前来说,事情的发展都很正常,直到一个bug的到来。

      쿠키를 함께 배워볼까요?

      一个合法的邮箱,却进入了非法邮箱处理的代码片段里面……

      쿠키를 함께 배워볼까요?

      毫无疑问,邮箱是合法的,代码也是合理的,那么出问题的必然是我,某个地方的理解有问题。

      • 找bug,把可能出错的代码片段分成几个区间,打log.

      console.log(email.indexOf(&amp;amp;#39;@&amp;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&amp;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;amp;#39;@&amp;amp;#39;) === -1) {
        response.statusCode = 400
        response.setHeader(&amp;amp;#39;Content-Type&amp;amp;#39;, &amp;amp;#39;application/json;charset=utf-8&amp;amp;#39;) //直接告诉浏览器我是json
        response.write(`
          {
            &amp;quot;errors&amp;quot;: {
            &amp;quot;email&amp;quot;: &amp;quot;invalid&amp;quot;
            }
          }
        `)
      }
      로그인 후 복사
      로그인 후 복사

      这就合理多了,后台只管写个json给前台看,其他不管了,前台翻译一下给用户看喽~

      那么前台如何获得这个json

      $.post(&amp;amp;#39;/sign_up&amp;amp;#39;, hash)
      .then((response) =&amp;gt; {
        //成功了就打印这个  
        console.log(response)
      },
      (request, b, c) =&amp;gt; {
         console.log(request)
         console.log(b)
         console.log(c)
      })
      로그인 후 복사
      로그인 후 복사

      忘记了错误函数里面的参数是啥了,那就都打印出来看看。

      쿠키를 함께 배워볼까요?

      可以看到,如果没用JSON的话,request对象里面有一个后端写的responseText属性可以利用。

      쿠키를 함께 배워볼까요?

      设置了Content-Type:application/json;charset=utf-8之后,可以利用多出来的responseJSON属性,获得json的内容啊。

      最终失败函数里面写

      (request) =&amp;gt; {
        let {errors} = request.responseJSON    
        if (errors.email &amp;amp;&amp;amp; errors.email === &amp;amp;#39;invalid&amp;amp;#39;) {
          $form.find(&amp;amp;#39;[name=&amp;quot;email&amp;quot;]&amp;amp;#39;).siblings(&amp;amp;#39;.errors&amp;amp;#39;).text(&amp;amp;#39;您输入的邮箱错啦&amp;amp;#39;)
        }
      }
      로그인 후 복사
      로그인 후 복사

      校验邮箱是否已经存在了

      var users = fs.readFileSync(&amp;amp;#39;./db/users&amp;amp;#39;, &amp;amp;#39;utf8&amp;amp;#39;)
      try {
        users = JSON.parse(users) //[] JSON也支持数组
      } catch (exception) {
        users = []
      }
      let inUse = false
      for (let i = 0; i &amp;lt; users.length; i++) {
        let user = users[i]
        if (user.email === email) {
          inUse = true
          break
        }
      }
      if (inUse) {
        response.statusCode = 400
        response.setHeader(&amp;amp;#39;Content-Type&amp;amp;#39;, &amp;amp;#39;application/json;charset=utf-8&amp;amp;#39;)
        response.write(`
          {
            &amp;quot;errors&amp;quot;: {
            &amp;quot;email&amp;quot;: &amp;quot;inUse&amp;quot;
            }
          }
        `)
      }
      로그인 후 복사
      로그인 후 복사

      本文并没有使用真正意义上的数据库,只是使用了简单的db文件做数据库,其实就是存的数组,也就是users其实就是数组[]

      • 之所以使用了try{}catch(){},是因为一旦除了错,可以将其初始化为空数组,后续代码可以继续执行,可能并不严谨,不过本文是侧重了解注册的思路的。

      同样的,如果邮箱已经存在了,就提示用户

      if (errors.email &amp;amp;&amp;amp; errors.email === &amp;amp;#39;inUse&amp;amp;#39;) {
          $form.find(&amp;amp;#39;[name=&amp;quot;email&amp;quot;]&amp;amp;#39;).siblings(&amp;amp;#39;.errors&amp;amp;#39;).text(&amp;amp;#39;这个邮箱已被注册啦&amp;amp;#39;)
      }
      로그인 후 복사
      로그인 후 복사

      后端校验必须很严格,因为可以通过curl越过前端的校验。

      쿠키를 함께 배워볼까요?

      쿠키를 함께 배워볼까요?


      把信息写入数据库

      没有错误之后,就可以把信息写到数据库里面啦

       users.push({email: email, password: password})//是个对象啊
       var usersString = JSON.stringify(users)
       fs.writeFileSync(&amp;amp;#39;./db/users&amp;amp;#39;, usersString)
       response.statusCode = 200
      로그인 후 복사
      로그인 후 복사

      users实现是个对象,而对象是内存里面的东西,数据库里面应该存储的是字符串,所以用了JSON.stringify(users)

      相关推荐:

      JS前端缓存的实现方法及 Cookie的特点介绍

      全面掌握Express cookie-parser中间件

      JavaScript读取和写入cookie实例教程

      위 내용은 쿠키를 함께 배워볼까요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    관련 라벨:
    원천:php.cn
    본 웹사이트의 성명
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
    인기 튜토리얼
    더>
    최신 다운로드
    더>
    웹 효과
    웹사이트 소스 코드
    웹사이트 자료
    프론트엔드 템플릿