1. 程式人生 > >部落格專案之前端開發—註冊功能實現

部落格專案之前端開發—註冊功能實現

1、前端註冊功能實現

  在service/user.js中增加reg註冊函式     

 1 import axios from "axios"
 2 import { observable } from "mobx";
 3 import store from 'store'
 4 
 5 // 過期外掛
 6 store.addPlugin(require('store/plugins/expire'))
 7 
 8 class UserService {
 9     // 定義被觀察物件
10     @observable loggedin = false
11 
12     //
登入 13 login (email, password) { 14 //TODO 15 console.log('----------------') 16 console.log(email) 17 console.log(password) 18 console.log('----------------') 19 20 axios.post('/api/user/login', { 21 email:email, 22 password:password
23 })// 成功執行 24 // 普通函式,用箭頭處理this問題 25 .then((response) => { 26 console.log(1,response); 27 console.log(2,response.data) 28 const {token, user} = response.data 29 console.log(3,token) 30 store.set('token',token, (new
Date()).getTime() + (8 * 3600 * 1000)) 31 console.log(4,user) 32 //成功後,狀態改變 33 this.loggedin = true 34 35 })//錯誤就不執行 36 .catch( (error) => { 37 console.log(7,error); 38 this.loggedin = false; 39 }); 40 } 41 42 // 註冊 43 reg (name, email, password) { 44 //TODO 45 console.log('-------***---------') 46 console.log(email) 47 console.log(password) 48 console.log('-------***---------') 49 50 axios.post('/api/user/reg', { 51 email:email, 52 password:password, 53 name:name 54 })// dev server 會代理 55 // 普通函式,用箭頭處理this問題 56 .then( response => { 57 console.log(1,response); 58 console.log(2,response.data) 59 console.log(3,response.status) 60 const {token, user} = response.data 61 console.log(4,token) 62 // 儲存token 63 store.set('token',token, (new Date()).getTime() + (8 * 3600 * 1000)) 64 console.log(5,user) 65 //成功後,狀態改變 66 console.log('==================') 67 this.loggedin = true 68 console.log('==================') 69 70 })//錯誤就不執行 71 .catch(error => { 72 console.log(6,error); 73 this.loggedin = false; 74 }); 75 } 76 } 77 78 79 80 //全域性變數 81 const userService = new UserService() 82 83 export {userService}

         《===等價===》

     測試:

     

     component/reg.js 元件:

 1 import React from 'react'
 2 import{Link, Redirect} from 'react-router-dom'
 3 import '../css/login.css'
 4 import {userService as service} from '../service/user';
 5 import { observer } from 'mobx-react';
 6 
 7 
 8 
 9 export default class Reg extends React.Component{
10     render(){
11         return <_Reg service={service} />;
12     }
13 }
14 // 觀察者
15 @observer
16 class _Reg extends React.Component{
17     validatePwd(pwd1, pwd2) {
18         return pwd1.value == pwd2.value  //確保兩次輸入的密碼一致,下面沒有程式碼,可以自己新增
19     }        
20 
21     handleClick(event) {
22         event.preventDefault()
23         console.log(typeof(event.target.form),'=========')
24         const [name, email, password, confirm] = event.target.form;
25         console.log(this.validatePwd(password, confirm),'===========')
26         this.props.service.reg(name.value, email.value, password.value);
27 
28     }
29     
30     render(){
31         if (this.props.service.loggedin) {
32             return <Redirect to="/" />
33         }
34         return(
35             <div className="login-page">
36             <div className="form">
37             <form className="register-form">
38                 <input type="text" placeholder="姓名"/>
39                 <input type="text" placeholder="郵箱"/>
40                 <input type="password" placeholder="密碼"/>
41                 <input type="password" placeholder="確認密碼"/>
42                 <button onClick={this.handleClick.bind(this)}>註冊</button>
43                 <p className="message">已經註冊? <Link to="/login">登入</Link></p>
44             </form>
45             </div>
46       </div>
47         )
48     }
49 }
 1 # 註冊(業務) insert
 2 def reg(request:HttpRequest):
 3     try:
 4         play = simplejson.loads(request.body)
 5         # print(play, type(play),'========================')
 6         email = play["email"]
 7         a = User.objects.filter(email=email)
 8         # print(a.query) # 檢視查詢語句
 9         if a.first():# 懶惰,只要用,就會查
10             return HttpResponseBadRequest('使用者名稱存在')
11         print('--------------------------------------')
12         name = play["name"]
13         # 這兩步可以合起來,減少計算
14         password = play["password"]
15         print(password)
16         password = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
17         # ORM 操作
18         user = User()
19         user.email = email
20         user.name = name
21         user.password = password
22 
23         try: # 這個try可以去掉,不要把e法到瀏覽器端,
24             # 這個try裡可以做些特殊處理;
25             user.save() # commit提交
26             # 如果正常,返回json資料
27             token = gen_token(user.id)
28             res = JsonResponse({
29                 'user': {
30                     "user_id": user.id,
31                     "name": user.name,
32                     "email": user.email
33                 },
34                 'token': token
35             })
36             res.set_cookie('Jwt', token)  # set cookie
37             return res
38         except jwt.ExpiredSignatureError as e:
39             print(e)
40             return HttpResponseBadRequest("jwt 過期了")
41         except Exception as e:
42             print(e)
43             # return HttpResponseBadRequest("引數錯誤")
44             raise # 直接往外拋,外面的接住。
45     except Exception as e: # 有任何異常返回。
46         print(e,'==')
47         return HttpResponseBadRequest("引數錯誤") # 這裡返回例項,這不是異常類,繼承自httpresponse
後臺user/reg.py

 

  注意:

    所有的業務操作都是對一個service例項的操作,不能說,註冊使用一個service例項,登入使用一個service例項,這樣兩者沒有任何關係

    所以直接從service/user.js 中匯出,為每個業務使用

    

    本專案是:只要註冊成功,就不需要登入了,直接登入成功,所以後臺直接返回token  

 

2、Ant Design

  Ant Design 螞蟻金服開源的 React UI 庫

  官網:https://ant.design/index-cn

  官方文件:https://ant.design/docs/react/introduce-cn

  安裝: $npm  install antd    $ yarn add antd

  使用:

    

3、網頁中資訊顯示  

   網頁開發中,不管操作成功與否,有很多資訊提示, 目前資訊都是控制檯輸出的,使用者看不到,使用Antd的message元件顯示友好資訊提示

  在service/user.js 中增加一個被觀察物件

  

 1 import axios from "axios"
 2 import { observable } from "mobx";
 3 import store from 'store'
 4 
 5 
 6 // 過期外掛
 7 store.addPlugin(require('store/plugins/expire'))
 8 
 9 class UserService {
10     // 定義被觀察物件
11     @observable loggedin = false
12     @observable errMsg = '' // 登入錯誤資訊
13 
14     //登入
15     login (email, password) {
16         //TODO
17         console.log('----------------')
18         console.log(email)
19         console.log(password)
20         console.log('----------------')
21 
22         axios.post('/api/user/login', {
23             email:email,
24             password:password
25             })// 成功執行
26             // 普通函式,用箭頭處理this問題
27             .then((response) => {
28                 console.log(1,response);
29                 console.log(2,response.data)
30                 const {token, user} = response.data
31                 console.log(3,token)
32                 store.set('token',token, (new Date()).getTime() + (8 * 3600 * 1000))
33                 console.log(4,user)
34                 //成功後,狀態改變
35                 this.loggedin = true
36                 this.errMsg = ''
37 
38             })//錯誤就不執行
39             .catch( (error) => {
40                 console.log(7,error);
41                 this.loggedin = false;
42                 this.errMsg = '登入名或密碼錯誤'
43             });
44     }
45 
46     // 註冊
47     reg (name, email, password) {
48         //TODO
49         console.log('-------***---------')
50         console.log(email)
51         console.log(password)
52         console.log('-------***---------')
53 
54         axios.post('/api/user/reg', {
55             email,
56             password,
57             name
58             })// dev server 會代理
59             // 普通函式,用箭頭處理this問題
60             .then( response => {
61                 console.log(1,response);
62                 console.log(2,response.data)
63                 console.log(3,response.status)
64                 const {token, user} = response.data
65                 console.log(4,token)
66                 // 儲存token
67                 store.set('token',token, (new Date()).getTime() + (8 * 3600 * 1000))
68                 console.log(5,user)
69                 //成功後,狀態改變
70                 console.log('==================')
71                 this.loggedin = true
72                 this.errMsg = '  '
73                 console.log('==================')
74 
75             })//錯誤就不執行
76             .catch(error => {
77                 console.log(6,error);
78                 this.loggedin = false;
79                 this.errMsg = '註冊失敗'
80 
81             });
82     }
83 }
84 
85 
86 
87 //全域性變數
88 const userService = new UserService()
89 
90 export {userService}

 

    component/login.js元件,增加Antd的message元件

 1 import React from 'react';
 2 import {Link,Redirect} from 'react-router-dom';
 3 import '../css/login.css';
 4 import {userService as service} from '../service/user';
 5 import { observer } from 'mobx-react';
 6 import { message } from  'antd'
 7 import 'antd/lib/message/style'
 8 
 9 
10 
11 
12 export default class Login extends React.Component{
13     render(){
14         return <_Login service={service} />;
15     }
16 }
17 // 觀察者
18 @observer
19 class _Login extends React.Component {
20     handleClick(event) {
21         event.preventDefault();
22         const [email, password] = event.target.form
23         this.props.service.login(email.value, password.value)// 獲取表單的值
24     }
25 
26 
27     render(){
28         console.log('======================')
29         // 觀察者發現改變了,在這裡只要用一次,即便是列印,就會通知render
30         // 沒有改變,則不會被呼叫loggedin
31         console.log(this.props.service.loggedin)
32         // 登入成功之後,就不會往下走了,直接return,並跳轉
33         if (this.props.service.loggedin) return <Redirect to="/" />
34         //import { message } from  'antd'
35         // 官網提供的函式:顯示3秒資訊,之後,置空
36         if (this.props.service.errMsg) {// 如果註冊失敗,才會進來
37             //js中 [] {} 等效true
38             message.info(this.props.service.errMsg, 3, 
39             () => this.props.service.errMsg = '')
40         }
41         
42         return(
43             <div className="login-page">
44                 <div className="form">
45                 <form className="login-form">
46                 <input type="text" placeholder="郵箱"/>
47                 <input type="password" placeholder="密碼"/>
48                 <button onClick={this.handleClick.bind(this)}>登入</button>
49                 <p className="message">未註冊? <a href="#">立即註冊</a></p>
50                 {/* <span>{this.props.service.errMsg}</span> */}
51                 </form>
52                 </div>
53             </div>
54         )
55     }
56 }

     結果:

      

 

    上面的程式碼執行到使用者登入失敗的時候,瀏覽器控制檯會丟擲 一個警告:

    

    

    解決辦法:

      將訊息的清除程式碼移動到 componentDidUpdat中(render結束後執行 訊息提示)

 1 import React from 'react';
 2 import {Link,Redirect} from 'react-router-dom';
 3 import '../css/login.css';
 4 import {userService as service} from '../service/user';
 5 import { observer } from 'mobx-react';
 6 import { message } from  'antd'
 7 import 'antd/lib/message/style'
 8 
 9 
10 
11 
12 export default class Login extends React.Component{
13     render(){
14         return <_Login service={service} />;
15     }
16 }
17 // 觀察者
18 @observer
19 class _Login extends React.Component {
20     handleClick(event) {
21         event.preventDefault();
22         const [email, password] = event.target.form
23         this.props.service.login(email.value, password.value)// 獲取表單的值
24     }
25 
26 
27     render(){
28         console.log('======================')
29         // 觀察者發現改變了,在這裡只要用一次,即便是列印,就會通知render
30         // 沒有改變,則不會被呼叫loggedin
31         console.log(this.props.service.loggedin)
32         // 登入成功之後,就不會往下走了,直接return,並跳轉
33         if (this.props.service.loggedin) return <Redirect to="/" />
34 
35         let em =  this.props.service.errMsg; // 引用這個值,留作觀察,否則不知道時候改了沒
36         
37         return(
38             <div className="login-page">
39                 <div className="form">
40                 <form className="login-form">
41                 <input type="text" placeholder="郵箱"/>
42                 <input type="password" placeholder="密碼"/>
43                 <button onClick={this.handleClick.bind(this)}>登入</button>
44                 <p className="message">未註冊? <a href="#">立即註冊</a></p>
45                 {/* <span>{this.props.service.errMsg}</span> */}
46                 </form>
47                 </div>
48             </div>
49         )
50     }
51     componentDidUpdate(prevProps, prevState) { //渲染後,顯示訊息元件
52         //這裡的prevProps和下面的this.props是同一個值,因為service這個屬性沒有改變
53         //一直是user。js中匯出的service
54         //import { message } from  'antd'
55         // 官網提供的函式:顯示3秒資訊,之後,置空
56         if (prevProps.service.errMsg) {// 如果註冊失敗,才會進來
57             //js中 [] {} 等效true
58             message.info(prevProps.service.errMsg, 3, 
59             () => prevProps.service.errMsg = '')
60         }
61     }
62 }

 

  component/reg.js元件同樣增加message元件

 1 import React from 'react'
 2 import{Link, Redirect} from 'react-router-dom'
 3 import '../css/login.css'
 4 import {userService as service} from '../service/user';
 5 import { observer } from 'mobx-react';
 6 import { message } from  'antd'
 7 import 'antd/lib/message/style'
 8 import {inject} from '../utils'
 9 
10 
11 
12 // 觀察者
13 @inject({service})
14 @observer
15 class _Reg extends React.Component{
16     validatePwd(pwd1, pwd2) {
17         return pwd1.value == pwd2.value
18     }
19     validateEma(email) {
20         // email校驗
21     }        
22 
23     handleClick(event) {
24         event.preventDefault()
25         console.log(typeof(event.target.form),'=========')
26         const [name, email, password, confirm] = event.target.form;
27         if (this.validatePwd(password, confirm) ){
28             this.props.service.reg(name.value, email.value, password.value);  
29                     
30         }
31         else {
32             console.log('兩次密碼不同')
33             this.props.service.reg(name.value, email.value, password.value,false);   
34         }
35 
36 
37     }
38     
39     render(){
40         if (this.props.service.loggedin) {
41             return <Redirect to="/" />
42         }
43         let em =  this.props.service.errMsg; // 引用這個值,留作觀察,否則不知道時候改了沒
44 
45         return(
46             <div className="login-page">
47             <div className="form">
48             <form className="register-form">
49                 <input type="text" placeholder="姓名"/>
50                 <input type="text" placeholder="郵箱"/>
51                 <input type="password" placeholder="密碼"/>
52                 <input type="password" placeholder="確認密碼"/>
53                 <button onClick={this.handleClick.bind(this)}>註冊</button>
54                 <p className="message">已經註冊? <Link to="/login">登入</Link></p>
55             </form>
56             </div>
57       </div>
58         )
59     }
60     componentDidUpdate(prevProps, prevState) { //渲染後,顯示訊息元件
61         //這裡的prevProps和下面的this.props是同一個值,因為service這個屬性沒有改變
62         //一直是user。js中匯出的service
63         //import { message } from  'antd'
64         // 官網提供的函式:顯示3秒資訊,之後,置空
65         if (prevProps.service.errMsg) {// 如果註冊失敗,才會進來
66             //js中 [] {} 等效true
67             message.info(prevProps.service.errMsg, 3, 
68             () => prevProps.service.errMsg = '')
69         }
70     }
71 }

 

 

4、高階元件裝飾器

  裝飾器函式的整個過程演變如下:

 1 export default class Login extends React.Component{
 2     render(){
 3         return <_Login service={service} />;
 4     }
 5 }
 6 
 7 class Login extends React.Component{
 8     render(){
 9         return <_Login service={service} />;
10     }
11 }
12 // 匿名 元件
13 const Login = class extends React.Component {
14     render(){
15         return <_Login service={service} />;
16     }
17 }
18 // 提引數
19 function inject (){
20     return Login
21 }
22 
23 function inject() {
24     return class extends React.Component {
25         render(){
26             return <_Login service={service} />;
27         }
28     }
29 }
30 
31 function inject(x,Comp) {
32     return class extends React.Component {
33         render(){
34             return <Comp service={x} />;
35         }
36     }
37 }
38 
39 //柯里化
40 function inject(x) {
41     function wrapper (Comp) {
42         return class extends React.Component {
43             render(){
44                 return <Comp service={x} />;
45             }
46         }
47     }
48     return wrapper
49 }
50 
51 
52 
53 function inject(obj) {
54     function wrapper (Comp) {
55         return class extends React.Component {
56             render(){
57                 return <Comp {...obj} />
58             }
59         }
60     }
61     return wrapper
62 }
63 
64 function inject(obj) {
65     return  wrapper (Comp) {
66         return class extends React.Component {
67             render(){
68                 return <Comp {...obj} />
69             }
70         }
71     }
72 }
73 
74 const inject = obj =>  Comp => {
75         return class extends React.Component {
76             render(){
77                 return <Comp {...obj} />
78             }
79         }
80     }
81 //等價為一個無狀態元件
82 const inject = obj =>  Comp => {
83     return function (props) {
84             return <Comp {...obj} />    
85     }
86 }
87 
88 
89 const inject = obj =>  Comp => {
90     props => <Comp {...obj} />;
91 }
92 
93 const inject = obj =>  Comp => props => <Comp {...obj} />;
94 const inject = obj =>  Comp => props => <Comp {...obj} {...props} />;

 

    新建一個工具檔案 src/utils.js  放入以下內容:

1 import React from 'react'
2 
3 const inject = obj =>  Comp => props => <Comp {...obj} {...props} />;
4 
5 
6 export {inject}

    將登入,註冊元件裝飾一下:

    具體程式碼:Mobx的observer 裝飾器要求,所以注意裝飾的順序

 1 import React from 'react';
 2 import {Link,Redirect} from 'react-router-dom';
 3 import '../css/login.css';
 4 import {userService as service} from '../service/user';
 5 import { observer } from 'mobx-react';
 6 import { message } from  'antd'
 7 import 'antd/lib/message/style'
 8 import {inject} from '../utils'
 9 
10 
11 @inject({service})
12 @observer//官方推薦,貼近類
13 export default class Login extends React.Component {
14     handleClick(event) {
15         event.preventDefault();
16         const [email, password] = event.target.form
17         this.props.service.login(email.value, password.value)// 獲取表單的值
18     }
19 
20 
21     render(){
22         console.log('======================')
23         // 觀察者發現改變了,在這裡只要用一次,即便是列印,就會通知render
24         // 沒有改變,則不會被呼叫loggedin
25         console.log(this.props.service.loggedin)
26         // 登入成功之後,就不會往下走了,直接return,並跳轉
27         if (this.props.service.loggedin) return <Redirect to="/" />
28 
29         let em =  this.props.service.errMsg; // 引用這個值,留作觀察,否則不知道時候改了沒
30         
31         return(
32             <div className="login-page">
33                 <div className="form">
34                 <form className="login-form">
35                 <input type="text" placeholder="郵箱"/>
36                 <input type="password" placeholder="密碼"/>
37                 <button onClick={this.handleClick.bind(this)}>登入</button>
38                 <p className="message">未註冊? <a href="#">立即註冊</a></p>
39                 {/* <span>{this.props.service.errMsg}</span> */}
40                 </form>
41                 </div>
42             </div>
43         )
44     }
45     componentDidUpdate(prevProps, prevState) { //渲染後,顯示訊息元件
46         //這裡的prevProps和下面的this.props是同一個值,因為service這個屬性沒有改變
47         //一直是user。js中匯出的service
48         //import { message } from  'antd'
49         // 官網提供的函式:顯示3秒資訊,之後,置空
50         if (prevProps.service.errMsg) {// 如果註冊失敗,才會進來
51             //js中 [] {} 等效true
52             message.info(prevProps.service.errMsg, 3, 
53             () => prevProps.service.errMsg = '')
54         }
55     }
56 }
login.js
 1 import React from 'react'
 2 import{Link, Redirect} from 'react-router-dom'
 3 import '../css/login.css'
 4 import {userService as service} from '../service/user';
 5 import { observer } from 'mobx-react';
 6 import { message } from  'antd'
 7 import 'antd/lib/message/style'
 8 import {inject} from '../utils'
 9 
10 
11 
12 // 觀察者
13 @inject({service})
14 @observer
15 class _Reg extends React.Component{
16     validatePwd(pwd1, pwd2) {
17         return pwd1.value == pwd2.value
18     }
19     validateEma(email) {
20         // email校驗
21     }        
22 
23     handleClick(event) {
24         event.preventDefault()
25         console.log(typeof(event.target.form),'=========')
26         const [name, email, password, confirm] = event.target.form;
27         if (this.validatePwd(password, confirm) ){
28             this.props.service.reg(name.value, email.value, password.value);  
29                     
30         }
31         else {
32             console.log('兩次密碼不同')
33             this.props.service.reg(name.value, email.value, password.value,false);   
34         }
35 
36 
37     }
38     
39     render(){
40         if (this.props.service.loggedin) {
41             return <Redirect to="/" />
42         }
43         let em =  this.props.service.errMsg; // 引用這個值,留作觀察,否則不知道時候改了沒
44 
45         return(
46             <div className="login-page">
47             <div className="form">
48             <form className="register-form">
49                 <input type="text" placeholder="姓名"/>
50                 <input type="text" placeholder="郵箱"/>
51                 <input type="password" placeholder="密碼"/>
52                 <input type="password" placeholder="確認密碼"/>
53                 <button onClick={this.handleClick.bind(this)}>註冊</button>
54                 <p className="message">已經註冊? <Link to="/login">登入</Link></p>
55             </form>
56             </div>
57       </div>
58         )
59     }
60     componentDidUpdate(prevProps, prevState) { //渲染後,顯示訊息元件
61         //這裡的prevProps和下面的this.props是同一個值,因為service這個屬性沒有改變
62         //一直是user。js中匯出的service
63         //import { message } from  'antd'
64         // 官網提供的函式:顯示3秒資訊,之後,置空
65         if (prevProps.service.errMsg) {// 如果註冊失敗,才會進來
66             //js中 [] {} 等效true
67             message.info(prevProps.service.errMsg, 3, 
68             () => prevProps.service.errMsg = '')
69         }
70     }
71 }
reg.js

     

@inject({service}) // Reg=inject({service})(Reg)  props是Login元件自己的 屬性props