单页面应用:
1.检验是不是:
打开终端
curl url
页面都是html 且在不同路由内返回的内容是一样的
2、锚点(定位
<h1><a name="foo"/>abc</h1>
or
<h1 id="foo">abc</h1>
设置后我们可以通过在地址后#foo找到它
3、后来出现html5 history API (跟锚点一样
window.history.go(-1);后退
window.history.go(1);前进
存变化地址
var stateObj ={ foo:"bar"};
history.pushState(stateObj,"page 2","bar.html");
4、hash搜索引擎难抓取(不带#)
步骤:
1、定义路由
2.编写UI component
3.定义model
4.connect
index.js
import dva from 'dva';
//1 定义
const app =dva();
//2 插件
//app.use({});
//3 Model
//app.model(require('./models/example').default);
//4.Router 配路由
app.router(require('./router').default);
//require相当于import
//该语句相当于
app.router(RouterConfig);
//这个RouterConfig是router.js中export default RouterConfig
//5.start
app.start('#root');
网址地址中的#/是什么意思呢 如何去掉
BrowserRouter 不带#
HashRouter 带#
解决方案:切换router为BrowserRouter
$ npm install --save history
修改入口文件
import { createBrowserHistory as createHistory } from 'history';
const app = dva({
history: createHistory()
});
src中actions文件存放逻辑文件
如登陆.js中
import axios from 'axios';
非异步的请求:
export const setCurrentUser =(user) =>{
return {
type:SET_CURRENT_USER,
user
}
};
异步请求:
export const login =(data) =>{
return dispatch =>{
return axios.post('/api/auth',data).then(
res => { const token =res.data.token;
localStorage.setItem ('jwtToken',token);
setAuthorizationToken(token);
dispatch(setCurrentUser(jwDecode(token)))
});
}
};
reducers中auth.js
const initialState ={
isAuthenticated: false,
user:{}
}
const auth =(state = initialState,action ={})=>{
switch(action.type){
case SET_CURRENT_USER:
return {
isAuthenticated: !isEmpth(action.user),
user:action.user
}
default:return state;
}
}
export default auth;
src下有个models
新建一个js文档
如何要使用这个counter.js,在utils中index.js中(可以使用很多个
app.model(require('./models/counter').default);
app.model(require('./models/example').default);
*若有十个百个如何优化呢?
在models中新建index.js
将一群model内容搬到这个文件中 我们需要循环遍历它
知识点Webpack中的require.context
filter
filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。const context =require.context ( './' , false, /\.js$/ );//当前目录 不循环遍历 查找js文件 export default context .keys()//找到之后取出key值 .filter(item => item !== './index.js')//过滤它 .map (key => context (key));//遍历它变成一个数组
最后在入口文件使用它
app.model(require('./models').default.forEach(key => app.model(key.default)));
可以输出它看一下内容
在入口文件中 console.log(require(’./models’。default));
counter.js
export default {
namespace:'counter',//定义一个不同的名便于区分state 防止重复冲突
state:{//此时是一个JSON
count:0
},//定义了namespace后state中的counter与另外models里的js文件中的state时重名不会冲突
//默认数据 优先级低于dva()的opts.initialState
补充
const app=dva({ initialState:{count:1}, }); app.model({ namespace:'count', state:0, });
则app.start()后state.count为1
把component和model连接在一起
connect方法
import { connect } from 'dva';
在组件js里最后
export default connect (null, {login})(LoginForm);
{login}就可以在本文件其他地方以
this.props.login(this.state)引用
对于函数mapStateToProps可以放到components下的flash里
FlashMessagesList.js
const mapStateToProps = ( state ) => {
return {
messages : state . flashMessages };
};
继续实现连接
components/Counter.js中
import React from 'react';
import { connect } from 'dva';
import PropTypes from 'prop-types';
const Counter =({Counter} 或props) => {
return (
console.log(Counter或props.Counter);
<div>
<h1>{counter.count}</h1>
<button>+</button>
</div>
)
}
Counter.propTypes ={//类型检查
counter:propTypes.object //对象 //别忘了导入propTypes
//object =array数组
}
const mapStateToProps =(state) =>{
return {
Counter(提出model里的namespace):state.counter
export default connect (mapStateToProps)(Counter);
在routes里也可以connect
routes/CounterPage.js
import React from 'react';
import Counter from '../components/Counter';
import { connect } from 'dva';
const CouterPage = ( {counter }//props) => {
return (
<div>
<p>Counter </p>
<Counter counter ={ counter}// 或{ ...props }传入全部 />
</div>
)
}
const mapStateToProps = ({ counter}) =>{
return {
counter:state.counter //两个counter都是命名空间
};
};
export default connect(mapStateToProps)(CounterPage);