dva视频课2

触发action 使用dispatch
让State改变需要reducer变化从而有新的store

dva好处在于不用想 redux一样还要维护一个常量

定义和用法
slice() 方法可从已有的数组中返回选定的元素。

语法
arrayObject.slice(start,end)
参数 描述
start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

routes/CounterPage.js
import React from 'react';
import Counter from '../components/Counter';
import { connect } from 'dva';

const CounterPage =({ counter ,dispatch }) => {
return ( 
<div>
	<p>Counter</p>
	<Counter counter ={ counter } dispatch= { dispatch } />//在组件内用只用传一次 在外层用要像这样多传一次
</div>
)
}

const mapStateToProps =(state)  =>{
return 
{ counter: state.counter };
};
export default connect (mapStateToProps)(CounterPage);

console.log()会在浏览器控制台打印出信息

console.dir()可以显示一个对象的所有属性和方法

同时还要修改components/Counter.js

import React from 'react';
const Counter =({ counter, dispatch}) => {
return ( 
<div>
	<h1>{ counter.count } </h1>
	<button onClick ={ ()=> {dispatch ({ type :'counter/add' }) } >
	+
	</button>
	)
	}
	export default Counter;

models/counter.js

export default {
namespace:'counter',
state{
count:2
},
reducers:{
	add(state,action){//由于type是add
		return {
		count:state.count + 1
		};
		},
		}
}

处理异步动作
例:隔了几秒钟数值才发生变化
向服务器请求数据

yield put /calldva视频课2_第1张图片
https://www.cnblogs.com/handsomehan/p/7102346.html

component /counter.js

import React from 'react';
const Counter =({ counter, dispatch}) => {
return ( 
<div>
	<h1>{ counter.count } </h1>
	<button onClick ={ ()=> {dispatch ({ type :'counter/add' }) } >//必须要有命名空间
	+
	</button>
	<button onClick ={ ()=> {dispatch ({ type :'counter/asyncAdd' }) } >
	async +
	</button>//异步动作
	)
	}
	export default Counter;

在models/counter.js中

import { delay } from 'dva/saga';
export default {
namespace:'counter',
state{
count:2
},
reducers:{
	add(state,action){//由于type是add
		return {
		count:state.count + 1
		};
		},
		},
effects: {
//function* 省略成了*
	*asyncAdd({ payload }, { call  , put ,select }) {//select.namespace 取出这里的值
	//select可以在saga中取到state的值
		const counter = yield select (state => state.counter)
		//或const counter = yeild select (({ counter }) => counter )
		//或const counter = yeild select ( _ => _.counter )
		//或const {counter} =yield select (_ => _);
		yield call (delay,1000);//调用
		yield put ({type: 'add' });//相当于dispatch
		},
	},
}
export default connect(({ products }) => ({
products,
}))(Products);
```相当于

(state.products) => ({
products:products
})


若reducers和effects中出现同名的情况呢?
不停的循环
尽量避免重名


yield 回调 一步一步的执行


在src/index.js中
有很多model需要引用怎么办?
我们可以把它们放入一个文件然后在这里循环遍历出来
新建src/models/index.js
放入许多 app.model(require(’./models/namespace’).default);
再放入

涉及到的是require.context的知识点

const context = require.context('./',false,/\.js$/);
export default context
.keys()
.filter(item => item!== './index.js')
.map(key => context(key));

将src/index.js model那改为
require(’./models’).default.forEach(key=> app.model(key.default));


可选使用的redux-actions库
便于方便管理component里调用的dispatch
(github)


实现路由跳转的几种方式
1、常规
2、在组件里

components/counter.js
子组件:
const Counter =({history,...等其他要传的值}) => {
return (
<div>
	<h1> {counter.count } </h1>
	<button onClick={ () => history.push('/') }>返回首页</button>
</div>
)
}

在父组件 routes/CounterPage.js中

const CounterPage =( { history} ) =>{
return(
) } }

3、把组件包裹起来的方式’
引用

import { withRouter } from 'dva/router';

const Counter =....

export default withRouter(Counter);

4、link式

import { withRouter ,Link } from 'dva/router';

const Counter =....
{
<Link to='/'>home</Link>//链接式
}
export default withRouter(Counter);

5、上下文跳转context

component/Counter.js中
import ...
const Counter =( props, context)=>{
return (
<div>
	<button onClick={ () => context.router.history.push('/') }>context go back</button>
</div>
)
}
static contextTypes ={
	router:PropTypes.object
}

6、effects中进行跳转(使用了react-router-redux)

import {routerRedux }from 'dva/router'
const Counter =....
{
return (
<div>
	<button onClick ={ () => dispatch (routerRedux.push('/'))}>routerRedux back</button>
</div>
)
}

7、在effects中进行跳转
components/counter.js

 //将跳转加入到这里

models/counter.js

import { routerRedux } from 'dva/router';
import queryString from 'query-string';
effects: {
*....{
yield put (routerRedux.push('/'));//或
yield put (routerRedux.push ({
pathname: '/'
hash:'hello'//在地址后面加入#hello
search: queryString.stringify({
from:'rails'  //地址后加?from=rail
})
})
}
}

订阅事件(监听变化 进行处理)

地址匹配另一种方式:利用正则表达式匹配
path-to-regexp(github

models/counter.js

export default {
namespace:...
subscriptions:{
	setup( { dispatch,history}) { //setup 一个函数名字
	window.onresize =() => {//窗口改变时
	dispatch ( {type :'add'});
	};
	onClick({ dispatch }) {
	document.addEventListener('click', () => {
		dispatch ({type: 'add'});
		})
	}
	},
	setupHistory({dispatch ,history}) {
	  history.listen((location)=> {//location 得到地址路径名 如/counter
	  	dispatch({type:'add'});//一进入就会执行add
	  })
	  }
	  },
	...
	}

const {dispatch} = props; //把props里的dispatch提取出来

onClick ={ () =>{...}} //里面是箭头函数

axios:
effects:{
 *fetch(_,{ put ,call }) {//传入put call方法
 	yield put({ type:'fetch/start' });
 	try{//success
 	const user = yield call(axios.get,"url");
 	yield put({ type:"fetch/success",user:user});}
 	catch(e){//fail error
 	yield put({ tyoe:"FETCH_USER_SUCCEEDED",error:e.message});
    }
 	},
 	},
 
 reducers:{
 'fetch/success'(state,action){
 return {
 	isFetching:false,//是否正在加载
 	error:null,//是否有错
 	user:action.user//返回用户名
 },
'fetch/error'(state,action){
 return {
 	isFetching:false,
 	error:action.error,
 	user:null
 	}
  }
  },
 
 

你可能感兴趣的:(前端)