06/redux-01

<pre>
    当有如下需要可以考虑使用redux:
      当组件的状态,需要共享
      某个状态需要在任何地方都可以拿到
      一个组件需要改变全局状态
      一个组件需要改变另一个组件的状态

      vue中是   
                   store(state,mutation,action)
          |----------------------- |     
          |  action --->mutation   |
          |-- ↑-------        ↑    |    
           dispatch  |        |    |
              |      |        |    |
              |      |        ↓    |
      component<-----|-----state   |                                           
                     |--------------            | 



             state可以由组件直接获取得到 
             组件diapatch  action 或commit mutation    来实现数据state的修改       
  

react没有vuex那么清晰,在store里定义state(状态),action等  主要定义reducer和action
react中reduce相当于mutation,store不需要定义声明,有reducer自动完成
组件通过store.getState()获得状态
组件怎么改状态?通过容器dispatch去改-->也就是store.dispatch(Action)   这个Action相当于重新触发掉了reducer  重新产生State,State一变化就触发组件变化。流向和vuex是一样的
component--->Action--->reducer--->state--->component     但是不把store,reducer,action全部叫store   这每一个东西都是普通的

  </pre>

02

 <div id='root'></div>
    <script src="./react.js"></script>
    <script src="./react-dom.js"></script>
    <script src="./react-router-dom.js"></script>
    <script src="./redux.js"></script>
    <script src="./babel.min.js"></script>
    <script type="text/babel">
    //count数据  用redux存
    //VUEX的使用:1)创建容器 定义state,action,mutation 2)容器挂载到Vue实例上  3)组件获取状态或修改状态
    //Redux:
    //reducer:用于产生state的函数  定义reducer才能知道count是什么数据
   //                        reducer根据对应的action产生state
    //action 是个普通对象,用于记录用户的行为  里面属性其实可以随便定,但规范上一般是给{type:''}
    // store  根据reducer函数创建

//六步骤
    //1.定义Reducer:是个函数  怎么定义随意 名字随便取,但是里面参数的含义是固定的
    //第一个参数,上一次的状态  state是由reducer创建的,所以一次都没调用的时候可能没有定义,可以给个初始化  
    //第二个参数是用户提交的action对象
    //返回值为新状态
    function myCount(state=0,action){
      debugger
      //这个state其实就代表count
      //reducer就是根据action产生state
      //传递给我的action到底是个什么行为,所有要根据action.type判断
      //reducer最终返回的是一个新状态
      switch(action.type){
        case 'ADD':
          return state+action.payload
        case 'SUB':
          return state-action.payload
          //一定要定义默认情况
        default:return state   //返回旧状态
      }
    }


    //2.reduce做好后创建容器
    //  创建store:用Redux.createStore     这个方法接受一个参数,就收Reducer作参数  根据这个Reducer就能产生容器(store)
    const store=Redux.createStore(myCount)

    //3.有时候可写可不写,简单的话可以不写  创建Action函数,Action Creator  是个函数,作用是创建action(一个对象)  return一个对象
      //可以由参数也可以没有
    function setCount(type,payload){
      //返回Action
      return{
        type,
        payload
      }
    }

    //4 创建组件   获取状态   修改状态
    class App extends React.Component{
      add=()=>{
        //让状态+1   reducer已将帮你做了  只要去执行一遍就行
        //只要去调用reducer  这时候用store.dispatch  store是全局变量
        //dispatch参数为action
        //addCount就是帮我们生成action对象的   所以这里得dispatch的参数就位action函数  否则简单的话可以不用这个addCount函数  直接store.dispatch({type:"ADD"})
        store.dispatch(setCount('ADD',2))
        //一dispatch  马上就会去调用reducer函数(也就是myCount),action传给myCount的第二个参数  这时候state就变了  state+1了
        //但这时候是不会更新视图的
      }
      sub=()=>{
        //让状态-1
        store.dispatch(setCount('SUB'))
      }

      render(){
        return(
          <div>
            {/*获取状态 store.getState()   拿到了state(就是count数字)*/}
            <p>{store.getState()}</p>
            <button onClick={this.add}>+</button>  
            <button onClick={this.sub}>-</button>  
          </div>
        )
      }
    }
    //5.渲染组件
    ReactDOM.render(<App/>,document.getElementById('root'))

    //6.监听状态变化,重新渲染页面  store.subscribe会自动监听state的更新
    store.subscribe(function(){
      ReactDOM.render(<App/>,document.getElementById('root'))
    })

    
    </script>

03

 <div id='root'></div>
    <script src="./react.js"></script>
    <script src="./react-dom.js"></script>
    <script src="./react-router-dom.js"></script>
    <script src="./redux.js"></script>
    <script src="./babel.min.js"></script>
    <script type="text/babel">
   
      //需求:共享数据count,行为有:加某个值,减某个值
      //1.定义Reducer:Reducer是函数,用于根据就状态和Action产生新状态

      //myCount这个函数由你去定义但不是不是由你直接去调用  而是由你去dispatch的时候由内部的Redux通过store自动的去调用
      //所以里面的形参不能换顺序,调用者根据规则去调用的,所以要按规则去定义,第一个就要定义state,第二个是action
      //redux的action个vuex不同  vuex的action是方法(函数),  redux的是对象  且有不成文的规则,要有一个type属性 不叫type也可以  不过都用type {type}
      //state=0这个初始值可以在创建recuder的时候在形参里设置,也可以在第二步创建容器的时候指定
      //action:{type:表示行为名称,payload:行为所携带的数据(推荐用payload)}
      function myCount(state=0,action){
      switch(action.type){
        case 'ADD':
          return state+action.payload
        case 'SUB':
          return state-action.payload
          //一定要定义默认情况
        default:return state   //返回旧状态
      }
    }

      //2.创建容器 第一个参数就是recuder,第二个参数就是状态初始值(可选,但这里不写那么reducer(myCount)就要写,否则state就是undefined)
      const store = Redux.createStore(myCount)

      //3.定义创建Action的方法,Action Creator
      function setCount(type,payload=1) {
        
        return {
          type,
          payload
        }
      }

      //4.设计组件
      class App extends React.Component{
        add = ()=>{
          store.dispatch(setCount('ADD',+this.input.value||1))
        }
        sub= ()=>{
          store.dispatch(setCount('SUB',+this.input.value||1))
        }
        render(){
          return(
            <div>
              <p>{store.getState()}</p>
              <input ref={(el)=>{this.input=el}}/>
              <button onClick={this.add}>+</button>   
              <button onClick={this.sub}>-</button>   
            </div>
          )
        }
      }
      function myRender(){
        ReactDOM.render(<App/>,document.getElementById('root'))
      }
      myRender()

      //这里只是讲的redux  redux本身是不能自动更新组件的(state变化的话)   后面有一个react-redux  这个做的是自动监听state变化  会直接引起视图变化  只用redux才有第五步

      //5.监听状态改变 store.subscribe(myCount)是有返回值的  执行这个返回值就会解除监听
      var unSubScribe=store.subscribe(myRender)

      // setTimeout(()=>unSubScribe(),20000)//解除监听



   
    </script>
  

04

 <style>
  
  .del{
    text-decoration: line-through
  }
  
  </style>
</head>
<body>
    <div id='root'></div>
    <script src="./react.js"></script>
    <script src="./react-dom.js"></script>
    <script src="./react-router-dom.js"></script>
    <script src="./redux.js"></script>
    <script src="./babel.min.js"></script>
    <script type="text/babel">

    //1需求:todoList
    //共享的state:[{count:'',isComplete:false}]
    //修改的action:添加,删除

      //1.定义Reducer:纯函数,不依赖除参数以外的数据,并且不改变函数以外的数据
      //  state虽然是函数内的,但是是外面传进来的,push就把外面的数据改了
      //                     相同的条件下重复调用还能得到相同的结果
      const todoList = function(state=[],action){
        switch (action.type) {
          case 'ADD_LIST':
            //  state.push(action.payload)  这是改了旧的状态  不能这么做   我们要保证reduce是纯函数,已有的状态是不能够改变的
            //  return state
            return[
              ...state,
              action.payload
            ]
          case 'DELETE_ITEM':
            return [
              ...state.slice(0,action.index),
              ...state.slice(action.index+1)
            ]
          case 'CLEAR_LIST':
            return []
          case 'TOGO_TODO':
            return [
            ...state.slice(0,action.index),
            Object.assign({},state[action.index],{isComplete:!state[action.index].isComplete}),
              ...state.slice(action.index+1)
            ]
            return state
          default: return state
        }
      }
    
    //2.创建容器 第一个参数就是reducer,第二个参数就是状态初始值(可选)
      const store = Redux.createStore(todoList)

    //3.定义Action Creator
    function addList(payload) {
      return {
        type:'ADD_LIST',
        payload
      }
    }
    function deleteList(index) {
      return {
        type:'DELETE_ITEM',
        index
      }
    }
    function clearList(payload) {
      return {
        type: 'CLEAR_LIST',
        payload
      }
    }
    function toggleTodo(index) {
      return {
        type:'TOGO_TODO',
        index
      }
    }
    
    //4.设计组件
    class App extends React.Component{
      render(){
    
        return (<div>
          <h1>用户标签</h1>
          <TodoList />
          <AddTodoItem />
        </div>)
      }
    }
    
    class TodoList extends React.Component{

      del=(index)=>{
        store.dispatch(deleteList(index))
      }

      cancel=(index)=>{
        store.dispatch(toggleTodo(index))
      }
      num = ()=>{
        var idx=0
        store.getState().map((val,index)=>{
         for(var i in val){
          
           if(val[i]===true){ ;idx++}
         }
        })
      
        return idx
      }

      render(){
        console.log(store.getState())
        // console.log()
        return(<div>
          <ul>
          {store.getState().map((val,index)=>{
            return (<li key={index}>
              <input  type="checkbox"  checked={val.isComplete} onChange={(e)=>{this.cancel(index)}} />
              <span className={val.isComplete?'del':''}>{val.content}</span>
              <button onClick={(e)=>this.del(index)}>删除</button>
            </li>)
          })}
        
        </ul>
        <p>完成数:{this.num()}/{store.getState().length}</p>
        
        
       </div> )
      }
    }

    class AddTodoItem extends React.Component{
      add = ()=>{
        store.dispatch(addList({content:this.newText.value,isComplete:false}))
   
      }
      render(){
        return(<div>
          <strong>任务</strong>
          <input ref={(el)=>{this.newText=el}}/>
          <button onClick={this.add}>保存</button>
        
        </div>)

      }
    }

    function render(){
      ReactDOM.render(<App/>,document.getElementById('root'))
    }
    render()

    store.subscribe(render)
    


    </script>
  

05

<style>
  
  .del{
    text-decoration: line-through
  }
  
  </style>
</head>
<body>
    <div id='root'></div>
    <script src="./react.js"></script>
    <script src="./react-dom.js"></script>
    <script src="./react-router-dom.js"></script>
    <script src="./redux.js"></script>
    <script src="./babel.min.js"></script>
    <script type="text/babel">

    //1需求:todoList
    //共享的state:[{count:'',isComplete:false}]
    //修改的action:添加,删除

      //1.定义Reducer:纯函数,不依赖除参数以外的数据,并且不改变函数以外的数据
      //  state虽然是函数内的,但是是外面传进来的,push就把外面的数据改了
      //                     相同的条件下重复调用还能得到相同的结果
      const todoList = function(state=[],action){
        switch (action.type) {
          case 'ADD_LIST':
            //  state.push(action.payload)  这是改了旧的状态  不能这么做   我们要保证reduce是纯函数,已有的状态是不能够改变的
            //  return state
            return[
              ...state,
              action.payload
            ]
          case 'DELETE_ITEM':
            return [
              ...state.slice(0,action.index),
              ...state.slice(action.index+1)
            ]
          case 'CLEAR_LIST':
            return []
          case 'TOGO_TODO':
            return [
            ...state.slice(0,action.index),
            Object.assign({},state[action.index],{isComplete:!state[action.index].isComplete}),
              ...state.slice(action.index+1)
            ]
            return state
          default: return state
        }
      }


      const totalNum=function (state=0,action) {
        switch(action.type){
          case 'ADD_TOTAL':
            return state+1
          case 'SUB_TOTAL':
            return state-1
          
        }
      }
    

    const rootRedcer=store.combineReducers({
      todoList,
      totalNum
    })
    //2.创建容器 第一个参数就是reducer,第二个参数就是状态初始值(可选)
      const store = Redux.createStore(rootRedcer)

    //3.定义Action Creator
    function addList(payload) {
      return {
        type:'ADD_LIST',
        payload
      }
    }
    function deleteList(index) {
      return {
        type:'DELETE_ITEM',
        index
      }
    }
    function clearList(payload) {
      return {
        type: 'CLEAR_LIST',
        payload
      }
    }
    function toggleTodo(index) {
      return {
        type:'TOGO_TODO',
        index
      }
    }

    function addNum() {
      return {
        type:'ADD_TOTAL'
      }
    }
    
    //4.设计组件
    class App extends React.Component{
      render(){
    
        return (<div>
          <h1>用户标签</h1>
          <TodoList />
          <AddTodoItem />
        </div>)
      }
    }
    
    class TodoList extends React.Component{

      del=(index)=>{
        store.dispatch(deleteList(index))
      }

      cancel=(index)=>{
        store.dispatch(toggleTodo(index))
      }
      num = ()=>{
        var idx=0
        store.getState().map((val,index)=>{
         for(var i in val){
          
           if(val[i]===true){ ;idx++}
         }
        })
      
        return idx
      }

      render(){
        console.log(store.getState())
        // console.log()
        return(<div>
          <ul>
          {store.getState().map((val,index)=>{
            return (<li key={index}>
              <input  type="checkbox"  checked={val.isComplete} onChange={(e)=>{this.cancel(index)}} />
              <span className={val.isComplete?'del':''}>{val.content}</span>
              <button onClick={(e)=>this.del(index)}>删除</button>
            </li>)
          })}
        
        </ul>
        <p>完成数:{this.num()}/{store.getState().length}</p>
        
        
       </div> )
      }
    }

    class AddTodoItem extends React.Component{
      add = ()=>{
        store.dispatch(addList({content:this.newText.value,isComplete:false}))
   
      }
      render(){
        return(<div>
          <strong>任务</strong>
          <input ref={(el)=>{this.newText=el}}/>
          <button onClick={this.add}>保存</button>
        
        </div>)

      }
    }

    function render(){
      ReactDOM.render(<App/>,document.getElementById('root'))
    }
    render()

    store.subscribe(render)
    


    </script>

06

<style>
  
  .del{
    text-decoration: line-through
  }
  
  </style>
</head>
<body>
    <div id='root'></div>
    <script src="./react.js"></script>
    <script src="./react-dom.js"></script>
    <script src="./react-router-dom.js"></script>
    <script src="./redux.js"></script>
    <script src="./react-redux.js"></script>
    <script src="./babel.min.js"></script>
    <script type="text/babel">


   //1建立reducer
    function reducer1(state=0,action){
      switch (action.type) {
        case "ADD":
            return state+action.payload
        case 'SUB':
          return state-action.payload
        default: return state
      }
    }

    function reducer2(state=0,action){
      switch(action.type) {
        case "ADD2":
            return state+action.payload
        case 'SUB2':
            return state-action.payload
        default: return state
      }
    }


  //2,创建store

  const rootReducer=Redux.combineReducers({
    reducer1,
    reducer2
  })
  const store=Redux.createStore(rootReducer)

  //3.创建action
  function add1(payload){
    return {
      type:'ADD',
      payload
    }
  }

  function add2(payload){
    return {
      type:'ADD2',
      payload
    }
  }

  function sub1(payload){
    return{
      type:'SUB',
      payload
    }
  }

  function sub2(payload){
    return{
      type:'SUB2',
      payload
    }
  }
  //4  创建组件
  class App extends React.Component{

    add1=()=>{
      store.dispatch(add1(1))
    }
    add2=()=>{
      store.dispatch(add2(2))
    }
    sub1=()=>{
      store.dispatch(sub1(2))
    }

    sub2=()=>{
      store.dispatch(sub2(2))
    }
    render(){
      return(<div>
      <p>{store.getState().reducer1}</p>
      <button onClick={this.add1}>+1</button>
      <button onClick={this.sub1}>-1</button>
      <p>{store.getState().reducer2}</p>
      <button onClick={this.add2}>+2</button>
      <button onClick={this.sub2}>-2</button>
      </div>)
    }
  }


    function render(){
      ReactDOM.render(<App/>,document.getElementById('root'))
    }
    render()
    store.subscribe(render)
    </script>

07

<style>
  
  .del{
    text-decoration: line-through
  }
  
  </style>
</head>
<body>
    <div id='root'></div>
    <script src="./react.js"></script>
    <script src="./react-dom.js"></script>
    <script src="./react-router-dom.js"></script>
    <script src="./redux.js"></script>
    <script src="./react-redux.js"></script>
    <script src="./babel.min.js"></script>
    <script type="text/babel">


   //1建立reducer
    function reducer1(state=0,action){
      switch (action.type) {
        case "ADD":
            return state+action.payload
        case 'SUB':
          return state-action.payload
        default: return state
      }
    }

    function reducer2(state=0,action){
      switch(action.type) {
        case "ADD2":
            return state+action.payload
        case 'SUB2':
            return state-action.payload
        default: return state
      }
    }


  //2,创建store

  const rootReducer=Redux.combineReducers({
    reducer1,
    reducer2
  })
  const store=Redux.createStore(rootReducer)

  //3.创建action
  function add1(payload){
    return {
      type:'ADD',
      payload
    }
  }

  function add2(payload){
    return {
      type:'ADD2',
      payload
    }
  }

  function sub1(payload){
    return{
      type:'SUB',
      payload
    }
  }

  function sub2(payload){
    return{
      type:'SUB2',
      payload
    }
  }
  //4  创建组件
  class App extends React.Component{
    //React-Redux的提供的根组件,让所有包含的组件能够获取state
    //React-Redux将组件划分为:容器组件和UI组件
    render(){
      return(<ReactRedux.Provider store={store}>
      
      <ContainerComponent></ContainerComponent>
      
      </ReactRedux.Provider>)
    }
  }


  //UI组件,只有界面和props
  class UIComponent extends React.Component{



    render(){
      return(<div>
        <p>{this.props.count}</p>
        <button onClick={this.add}>+</button>
        <button onCilck={this.sun}>-</button>
      </div>)
    }
  }

  //容器组件,通过ReactRedux.connect方法获取  这个方法本身有两个参数   再加一个UI组件
  //mapStateToProps,mapDispatchToProps 这两个变量要定义出来,用常量变量都可以,他们都是一个函数
  //mapStateToProps的参数是state,mapDispatchToProps的参数是dispatch
  //将store的state映射为UI组件的props
  function mapStateToProps(state){
    return {
      count:state
    }
  }
  //将store的dispatch映射为UI组件的props
  function mapDispatchToProps(dispatch){
    return{
      add:()=>{dispatch(add1(1))}
    }
}
  
  const ContainerComponent=ReactRedux.connect(mapStateToProps,mapDispatchToProps)(UIComponent)

 
      ReactDOM.render(<App/>,document.getElementById('root'))

    </script>

猜你喜欢

转载自www.cnblogs.com/lucy-xyy/p/11653246.html