文档服务地址:http://47.92.0.57:3000/ 周报索引地址:http://47.92.0.57:3000/s/NruNXRYmV

Commit 9fcdb500 by 安博

update readme.md

parent 079391c5
...@@ -865,3 +865,49 @@ let proxyOption ={target:proxyPath,changeOrigoin:true}; ...@@ -865,3 +865,49 @@ let proxyOption ={target:proxyPath,changeOrigoin:true};
app.use("/api",proxyMiddleWare(proxyOption)) //对api请求使用代理 app.use("/api",proxyMiddleWare(proxyOption)) //对api请求使用代理
``` ```
前端服务器代理的好处是对于用户而言只能看到前端服务器的地址,后端服务器的安全性得到提高;同时代理发生在内网环境,速度快。 前端服务器代理的好处是对于用户而言只能看到前端服务器的地址,后端服务器的安全性得到提高;同时代理发生在内网环境,速度快。
第6章          跨页面数据存储与session
==========
6.1          跨页面数据存储
---------
所谓跨页面数据存储,即同一域名下的各个标签能够访问某个共享的数据。这样在设计某些功能的时候会带来不少方便。
通常的跨页面存储方式有:`localStorage` `sessionStorage` `cookie`
localStorage和sessionStorage比较类似,提供一组简单的API:
`getItem(key)`
`setItem(key,value)`
`clear()`
这三个API的意思都非常明显,需要注意的是item的value只支持字符串,如果需要存储JSON可以使用`JSON.stringfy()`。存储于其中的数据在同一个域名的标签之间共享。
如果需要实时监听数据改变,可以使用
```
addEventListener('storage', e=>{
console.log(e.oldValue);
console.log(e.newValue);
console.log(e.url);
console.log(e.storageArea);
console.log(e.key);
})
```
字段意义也都非常清楚。注意事件只会在未直接修改数据的页面触发。
localStorage的保存时间是永久,而sessionStorage的保存时间是浏览器关闭之前。
6.2          session
--------
首先请自行了解cookie和session之间的关系。
浏览器端可以使用`document.cookie`访问cookie。而cookie中有一个`httpOnly`的字段,用于限制浏览器脚本对cookie内容的访问,不过这并不影响浏览器向服务器发送cookie。好的做法是服务器设置该字段为`true`,然后向其中写入sessionID或者token之类的字段。服务器可以自己选择session数据的存放方式,比如内存或者持久化到数据库中,而不是将这些数据放到前端处理。
前端如果需要保留一个域名下的某些可公开数据,应当使用localStorage之类的方式,不可公开的数据全部交由服务器端session处理。即,完全不信任前端。
cookie可以设置过期方式与过期时间字段。
6.3          ant框架中的权限控制
------
...@@ -175,7 +175,7 @@ export const getRouterData = app => { ...@@ -175,7 +175,7 @@ export const getRouterData = app => {
component: dynamicWrapper(app, [], () => import('../routes/play/play')), component: dynamicWrapper(app, [], () => import('../routes/play/play')),
}, },
'/play/p1/p2': { '/play/p1/p2': {
component: dynamicWrapper(app, ['play'], () => import('../routes/play/play')), component: dynamicWrapper(app, ['play','token'], () => import('../routes/play/play')),
}, },
// '/user/:id': { // '/user/:id': {
// component: dynamicWrapper(app, [], () => import('../routes/User/SomeComponent')), // component: dynamicWrapper(app, [], () => import('../routes/User/SomeComponent')),
......
...@@ -2,7 +2,7 @@ import { play, testAPI } from '../services/api'; ...@@ -2,7 +2,7 @@ import { play, testAPI } from '../services/api';
export default { export default {
namespace: 'play', namespace: 'play',
state: {}, state: {data:{time:666}},
effects: { effects: {
*getTime(_, { call, put }) { *getTime(_, { call, put }) {
const response = yield call(play); const response = yield call(play);
......
// import { xxx } from '../services/xxx';
export default {
namespace: "token",
state: {token:0},
effects: {
* fetch({payload}, {call, put})
{
yield put({type: 'save', newToken: payload});
},
},
reducers: {
save(state, {newToken})
{
return {
...state,
token:newToken
};
},
},
};
import React, { Component, Fragment } from 'react'; import React, {Component, Fragment} from 'react';
import { connect } from 'dva'; import {connect} from 'dva';
@connect(({ play, loading }) => ({ @connect(({play, token, loading}) => ({
play, play, token,
loading: loading.effects['play/getTime'], loading: loading.effects['play/getTime'],
})) }))
export default class play extends Component { export default class play extends Component {
componentDidMount() { componentDidMount()
const { dispatch } = this.props; {
dispatch({ type: 'play/getTime' }); const {dispatch} = this.props;
dispatch({type: 'play/getTime'});
typeof +localStorage.getItem('token') === "number" ? null : localStorage.setItem('token', 0);
dispatch({type: 'token/fetch', payload: localStorage.getItem('token')});
addEventListener('storage', e => {
const {dispatch} = this.props;
dispatch({type: 'token/fetch', payload: e.newValue});
});
} }
render() { refresh = e => {
const { play } = this.props; e.preventDefault();
const {dispatch} = this.props;
dispatch({type: 'play/getTime', payload: {name: '12', email: '189.cn', cellPhone: '123'}});
let newToken = typeof +localStorage.getItem('token') === "number" ? +localStorage.getItem('token') + 1 : 0;
localStorage.setItem('token', newToken);
dispatch({type: 'token/fetch', payload: newToken});
};
render()
{
const {play} = this.props;
console.log(play); console.log(play);
const data = play.data || { time: 'error' }; const data = play.data || {time: 'error'};
console.log(data); console.log(data);
const time = data.time || 'error'; const time = data.time || 'error';
const testRep = JSON.stringify(play.testRep); const testRep = JSON.stringify(play.testRep);
//let test = localStorage.getItem('token');
let test = this.props.token;
console.log(test);
return ( return (
<div> <div>
{testRep} {time}
<button style={{ marginLeft: 10 }} onClick={this.refresh}> <button style={{marginLeft: 10}} onClick={this.refresh}>
刷新时间 刷新时间
</button> </button>
{test.token}
</div> </div>
); );
} }
refresh = e => {
e.preventDefault();
const { dispatch } = this.props;
dispatch({ type: 'play/testAPI', payload: { name: '12', email: '189.cn', cellPhone: '123' } });
};
} }
import fetch from 'dva/fetch'; import fetch from 'dva/fetch';
import { notification } from 'antd'; import {notification} from 'antd';
import { routerRedux } from 'dva/router'; import {routerRedux} from 'dva/router';
import store from '../index'; import store from '../index';
const codeMessage = { const codeMessage = {
...@@ -23,11 +23,14 @@ const codeMessage = { ...@@ -23,11 +23,14 @@ const codeMessage = {
601: '自定义错误码601', 601: '自定义错误码601',
}; };
function checkStatus(response) { function checkStatus(response)
if (response.status >= 200 && response.status < 300) { {
if (response.status >= 200 && response.status < 300)
{
return response; return response;
} }
if (response.status >= 600) { if (response.status >= 600)
{
return response; return response;
} }
const errortext = codeMessage[response.status] || response.statusText; const errortext = codeMessage[response.status] || response.statusText;
...@@ -42,6 +45,20 @@ function checkStatus(response) { ...@@ -42,6 +45,20 @@ function checkStatus(response) {
} }
/** /**
* 设置代理,用于支持跨域
* @param path
* @param proxyUrl
* @param port
* @returns {*}
*/
function setProxy(path, {proxyUrl, port})
{
if (proxyUrl && port)
return proxyUrl + ':' + port + path;
else return path;
}
/**
* Requests a URL, returning a promise. * Requests a URL, returning a promise.
* *
* @param {string} url The URL we want to request * @param {string} url The URL we want to request
...@@ -50,18 +67,24 @@ function checkStatus(response) { ...@@ -50,18 +67,24 @@ function checkStatus(response) {
*/ */
export default function request(url, options) { export default function request(url, options) {
const defaultOptions = { const defaultOptions = {
credentials: 'include', mode: 'cors',//手动开启跨域
credentials: 'include',//允许跨域cookie
//credentials: 'same-origin',//只允许同域cookie
}; };
const newOptions = { ...defaultOptions, ...options }; const newOptions = {...defaultOptions, ...options};
if (newOptions.method === 'POST' || newOptions.method === 'PUT') { if (newOptions.method === 'POST' || newOptions.method === 'PUT')
if (!(newOptions.body instanceof FormData)) { {
if (!(newOptions.body instanceof FormData))
{
newOptions.headers = { newOptions.headers = {
Accept: 'application/json', Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8', 'Content-Type': 'application/json; charset=utf-8',
...newOptions.headers, ...newOptions.headers,
}; };
newOptions.body = JSON.stringify(newOptions.body); newOptions.body = JSON.stringify(newOptions.body);
} else { }
else
{
// newOptions.body is FormData // newOptions.body is FormData
newOptions.headers = { newOptions.headers = {
Accept: 'application/json;*/*', Accept: 'application/json;*/*',
...@@ -70,33 +93,41 @@ export default function request(url, options) { ...@@ -70,33 +93,41 @@ export default function request(url, options) {
} }
} }
//在这里对url做一次代理
url = setProxy(url, {proxyUrl: null, port: null});
return fetch(url, newOptions) return fetch(url, newOptions)
.then(checkStatus) .then(checkStatus)
.then(response => { .then(response => {
if (newOptions.method === 'DELETE' || response.status === 204) { if (newOptions.method === 'DELETE' || response.status === 204)
{
return response.text(); return response.text();
} }
return response.json(); return response.json();
}) })
.catch(e => { .catch(e => {
const { dispatch } = store; const {dispatch} = store;
const status = e.name; const status = e.name;
if (status === 401) { if (status === 401)
{
dispatch({ dispatch({
type: 'login/logout', type: 'login/logout',
}); });
return; return;
} }
if (status === 403) { if (status === 403)
{
dispatch(routerRedux.push('/exception/403')); dispatch(routerRedux.push('/exception/403'));
return; return;
} }
if (status <= 504 && status >= 500) { if (status <= 504 && status >= 500)
{
dispatch(routerRedux.push('/exception/500')); dispatch(routerRedux.push('/exception/500'));
return; return;
} }
if (status >= 404 && status < 422) { if (status >= 404 && status < 422)
{
dispatch(routerRedux.push('/exception/404')); dispatch(routerRedux.push('/exception/404'));
} }
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment