博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redux 学习
阅读量:6173 次
发布时间:2019-06-21

本文共 8947 字,大约阅读时间需要 29 分钟。

hot3.png

参考资料

 包含文档,redux项目,以及一些脚手架工具

慕课网

example

中间件middleware

参考资料:

example

观看example的时候,要把整个脉络action--》reducer---》store---》搞清楚,比如reducer要书写,参考(action--》reducer这条线)所以需要action这个参数入侵。比如store要书写,需要reducer--》store,所以需要reducer入侵。

代码的编写参考例子。

故障分析

有时候cnpm不起作用013808_vF1X_1267791.png,可能是被360拦截了。013737_PZi2_1267791.png

013836_0sXz_1267791.png

013852_QsBm_1267791.png添加信任就可以了。

 

官网

Counter Vanilla

一个入门demo,描述了redux如何运作的过程,从action--》reducer---》store---》更新应用state的过程。

  • store:
    •  store.dispatch({ type: 'xxx' }),这里store分发dispatch(触发)这些action,回调subscribe由store订阅  store.subscribe(render)好了
  • reducer:
    • fn:counter(state,action)是reducer,根据action.type,得到不同的状态。
    • var store = Redux.createStore(counter),这里store就和reducer绑定在一起了。
  • action
    • { type: 'xxx' }描述一种行为。行为具体怎么发生在reducer(这里是counter函数)里面定义了。

注意点:redux采用的是消费订阅者模式。

Counter

commonjs方式的demo。简易版的demo,方便了解整个rudux过程。

Redux 结合 React 使用的最基本示例。出于简化,当 store 发生变化,React 组件会手动重新渲染。在实际的项目中,可以使用 React 和 Redux 已绑定、且更高效的 。

要点

  • reactjs组件不需要知道redux,只是在外层导入props的时候 onIncrement={() => store.dispatch({type:'INCREMENT'})}关联store,让store去dispatch相应的动作,根据subscribe到store的reducer去判断类型,进行操作。这也是redux的底层的操作。
  • 组件和redux相关的组件书写的时候不会相互影响,可以分开编写,测试。
  • couter组件不包含状态,可以使用另一种写法,不使用class的方式
    import React,{Component} from 'react' /*class Counter extends Component {}*/const incrementIfOdd = (value,onIncrement) => {    if (value % 2 !== 0) {      onIncrement()    }  } const incrementAsync = (onIncrement) => {    setTimeout(onIncrement, 1000)  }export default ({value,onIncrement,onDecrement})=>{	return (		

    Clicked: {value} times

    )}

    注意 onClick里面不能直接{incrementifOdd(value,onIncrement)}

问题:

  • package.json文件"react-scripts": "^0.6.0",这个文件的作用(好像是简化测试,以及发布的模块),配合这个库使用的要加入react-addons-test-utils,enzyme这两个模块。

Todos

深入理解在 Redux 中 state 的更新与组件是如何共同运作的例子。展示了 reducer 如何委派 action 给其它 reducer,也展示了如何使用  从展示组件中生成容器组件。

要点

  • container的都是要跟redux关联的组件,也就是的作用,从redux的state树中取得自己要的数据mapStateToProps和动作mapDispatchToProps(要响应的dispath),关联react展示组件。然后react组件从这些容器中取得相应的数据和动作进行处理。
  • 组件触发动作action(带有数据)的时候,redux会去遍历所有的reduce,然后找到匹配的reduce,然后redux会自动更新state,react会更新视图。
  • 容器组件可以用动词来表达,比如addTodo,VisibleTodoList,而展示组件可以是一个名词比如footer等。
  • 注意容器组件AddTodo的写法。没有写mapStateToProps,这些东西。参考用法
    import React from 'react'import { connect } from 'react-redux'import { addTodo } from '../actions'let AddTodo = ({ dispatch }) => {  let input  return (    
    { e.preventDefault() if (!input.value.trim()) { return } dispatch(addTodo(input.value)) input.value = '' }}>
    { input = node }} />
    )}AddTodo = connect()(AddTodo)export default AddTodo

    比较这两个写法:具体看使用:FilterLink.js里的定义是一个函数,VisibleTodoList里的定义是一个对象。

    比较FilterLink.js和VisibileTodoList.js的mapDispatchToProps写法,注意两者的区别FilterLink是属性在标签里定义了。所以:

  • const mapDispatchToProps = (dispatch,ownProps) => ({	onClick:()=>{		dispatch(setVisibilityFilter(ownProps.filter))	}})

    而VisibleTodoList的是从内部去跑这个方法的。

    const mapDispatchToProps  =  {  onTodoClick: toggleTodo}

    另外,参考里面有一个写法:这也是传入id来处理的。

    const mapDispatchToProps = (dispatch) => {  return {    onTodoClick: (id) => {      dispatch(toggleTodo(id))    }  }}

    参数传递在Todo里面

    const todoList = ({todos,onTodoClick})=>{	return (
      {todos.map(todo =>
      onTodoClick(todo.id)} /> )}
    )}

     

todomvc

要点:

  • 改写官网TodoTextInput.js源文件如下:组件继承方式
    import React, { Component, PropTypes } from 'react'import classnames from 'classnames'export default class TodoTextInput extends Component {  static propTypes = {    onSave: PropTypes.func.isRequired,    text: PropTypes.string,    placeholder: PropTypes.string,    editing: PropTypes.bool,    newTodo: PropTypes.bool  }  state = {    text: this.props.text || ''  }  handleSubmit = e => {    const text = e.target.value.trim()    if (e.which === 13) {      this.props.onSave(text)      if (this.props.newTodo) {        this.setState({ text: '' })      }    }  }  handleChange = e => {    this.setState({ text: e.target.value })  }  handleBlur = e => {    if (!this.props.newTodo) {      this.props.onSave(e.target.value)    }  }  render() {    return (          )  }}

    这种写法,内部保持一个state,需要state一般是需要和用户进行交互,改写onKeyDown源文件如下函数组件:

    import React from 'react'import classnames from 'classnames'/*const handleSubmit =(e)=>{		const text = e.target.value.trim()	if(e.which === 13) {	}}const handleBlur = (e)=>{	console.log(this.props)}*/const TodoTextInput =({...props})=> 						 {									const text = e.target.value.trim()									if(e.which === 13&&text!=='') {										props.onSave(text)										e.target.value=""									}							}}						    placeholder={props.placeholder}/>export default TodoTextInput

    注意这里onKeyDown里面要引用外部的props,所以不能抽取到外面handleSubmit方法。会报props找不到。换个思路,如果使用链接工厂的方式:

    onBlur={handleBlur(props)}-----------------------------------------------------const handleBlur = (props)=>(e)=>{ //链接工厂的方式	console.log(props,e,e.target.value)}

    这样也是可以的。或者换个思路

    onBlur={e=>{handleBlur(props,e)}}-----------------------------------------const handleBlur = (props,e)=>{	console.log(props,e,e.target.value)}

     

  • 函数调用。一般下面的方法,如果只写一个textxxx那么textxxx都可以调用的到,如果这样写了,根据就近原则,内部函数先调用了。

  • import React from 'react'import TodoTextInput from './TodoTextInput'const textsss = ()=>{		console.log("xx")	}const Header = ({addTodo}) => {	const textsss = ()=>{		console.log("xxwww")	}	//这里如何定义内部方法。	return (

    todos

    { textsss() addTodo(text) }} placeholder="what need to be done?" />
    )}export default Header

     

  • 注意看下面的定义对象的方式 mainsection里面: 
    const TODO_FILTERS = {  [SHOW_ALL]: () => true,  [SHOW_ACTIVE]: todo => !todo.completed,  [SHOW_COMPLETED]: todo => todo.completed}

    这里[]:xxx,[]里面的是一个变量。

  • reduces/todos.js 里面的complete里面的一个写法:对象扩展运算符,...todo,就是把对象扩展了。然后后面的属性覆盖前面的。

    case types.COMPLETE_TODO:			return state.map(todo=>{						return todo.id === action.id?						{...todo,completed:!todo.completed}:						todo					})

     

async

可以参考这篇。

  • 注意代码段,
    export const fetchPostsIfNeeded = reddit => (dispatch, getState) => {  debugger  if (shouldFetchPosts(getState(), reddit)) {    return dispatch(fetchPosts(reddit))  }}

    这里getState是从哪里注入进来的?注意这里调用方是

    componentDidMount() {    const { dispatch, selectedReddit } = this.props    dispatch(fetchPostsIfNeeded(selectedReddit))  }

    dispatch(fetchPostsIfNeeded(selectedReddit))就是说只有注入dispatch,触发dispatch,才有getState()这个变量。让我们可以做下一步的操作。可以换成下面的代码块。

    export const fetchPostsIfNeeded = reddit =>{  return (dispatch, getState) => {    if (shouldFetchPosts(getState(), reddit)) {      return dispatch(fetchPosts(reddit))    }  } }

    dispatch(fetchPostsIfNeeded(selectedReddit))调用的时候,最后返回的是一个函数。可以有这两个变量。我们修改todomvc 例子里面的action/index.js,加入dispatch,getState(),如下,注意,如果想改成这样的话,

    export const addTodo = text =>(dispatch,getState)=> {debugger;return ({ type: types.ADD_TODO, text })}

    必须加入中间件。发现这是系统调用的时候调用的时候自动加入的。这也可以理解,actioncreator本来是要返回一个plain的obj,不过现在需要做其他的操作(网络请求),就需要中间件。按照正常的逻辑,走网络请求得到数据应该要走网络请求,所以函数的参数,就是状态(getState)和动作(dispatch)。继续做下一步的处理

  • 使用thunk中间件是因为actionCreator不仅仅要返回一个plain对象,还要在函数里面做一些操作。比如异步请求,然后最后返回的是一个函数。

当 action creator 返回函数时,这个函数会被 Redux Thunk middleware 执行。这个函数并不需要保持纯净;它还可以带有副作用,包括执行异步 API 请求。这个函数还可以 dispatch action,就像 dispatch 前面定义的同步 action 一样。

shopping

比较这两种写法:

productContainer

{products.map(product =>
addToCart(product.id)} /> )}

productItem里面:

这种写法把点击事件的具体操作放到外层容器处理。

另一种写法是:

productContainer

{products.map(product=>
)}

productItem里面做处理:

export default ({product,addToCart}) => (		
)

在productItem里面onClick另外处理,处理的场景不一样而已。主要是看业务需要分割到什么样的程度。

 

注意以下这两种写法:

 

actions.js

export const testConsoleProductUnderirect = ()=>dispatch=>{	dispatch({		type:types.TEST_CONSOLE_PRODUCTS	})}export const testConsoleProductInderirect = ()=>({	type:types.TEST_CONSOLE_PRODUCTS})

调用方式为

store.dispatch(testConsoleProductUnderirect())

store.dispatch(testConsoleProductInderirect())

第二种是常规的写法,就是返回一个普通的action对象。第一种写法是要由thunk中间件来触发的写法。注意 

const xx=()=>dispatch=>({XX:XX})

每一层 箭头都是有()包裹,是直接返回的。第一个xx=()=>dispatch说明是返回一个参数为dispatch的函数,一般actionCreator是要返回action对象的,这里返回了一个函数,需要用到thunk支持,第二层箭头>dispatch=>{ dispatch({ type:types.TEST_CONSOLE_PRODUCTS }) } 里面就可以dispatch其他操作。根据中间件文档的解释,中间件处理过程如下。传入action,然后返回next----》dispatch这个action,然后再store

这个next

store => next => action

层层嵌套。

注意使用了中间件之后,第二种actionCreator可以返回任意东西。只要有dispatch参数进去就可以了。

export const testConsoleProductUnderirect = ()=>dispatch=>{	console.log("hello kitty")	/*dispatch({		type:types.TEST_CONSOLE_PRODUCTS	})*/}

第一种同步actionCreator不行

export const testConsoleProductInderirect = ()=>{	console.log("hello kitty")}

这样写是会报错的。

转载于:https://my.oschina.net/u/1267791/blog/751978

你可能感兴趣的文章
Android Fragment 真正的完全解析(上) (转载)
查看>>
多线程依次打印abcabc
查看>>
一:学习Linux前准备工作
查看>>
how to install wireless driver for Dell 630 in Ubuntu
查看>>
Kafka 配置参数汇总及相关说明
查看>>
弄清 CSS3 的 transition 和 animation
查看>>
服务器指定网卡进行备份数据避免影响业务口
查看>>
在Sublime Text 2下面开发Sass
查看>>
四则运算个人项目3
查看>>
eclipse 构建maven web工程
查看>>
237. Delete Node in a Linked List
查看>>
[转] webpack之plugin内部运行机制
查看>>
宽字节与多字节之间的转换
查看>>
SEO的重要性
查看>>
ASP.NET 运行时详解 揭开请求过程神秘面纱
查看>>
Oracle 索引的失效检查
查看>>
C语言第五次作业--数据类型
查看>>
系统架构师-基础到企业应用架构-业务逻辑层
查看>>
高手详解SQL性能优化十条建议
查看>>
修改 IntelliJ IDEA 默认配置路径
查看>>