你的位置:首页 > Java教程

[Java教程]网页前端状态管理库Redux学习笔记(一)


最近在博客园上看到关于redux的博文,于是去了解了一下。

这个Js库的思路还是很好的,禁止随意修改状态,只能通过触发事件来修改。中文文档在这里。

 

前面都很顺利,但是看到异步章节,感觉关于异步说得很乱,而且必须配合插件才能实现异步。我是不喜欢用插件的人,能不用则不用。因此自己写了一个异步解决方案。大致的思路如下:

  1. 只在一个函数doSometing中处理异步方法和处理返回值,使用action传递执行类型参数
  2. 需要执行异步方法时,使用action传递参数,指示函数执行异步,然后返回特定状态,例如字符串"fetching"
  3. 在异步方法的回调中再次触发此状态修改(执行store.dispatch)
  4. 需要执行处理返回的数据时,使用action传递参数,指示函数执行数据处理,然后返回正确的状态值
  5. 最后,指定在哪里处理正确的状态值,可以在状态对象中订阅事件,也可以在第3步中直接处理

最后,贴上我写的例子,欢迎指教:)

<!doctype html><html>  <head>    <meta charset="utf-8" />    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />    <title>Redux Demo</title>    <style>      html,body{        height: 100%;        overflow: hidden;        margin: 0;      }      #box{        max-height: 85%;        overflow-x: hidden;        overflow-y: auto;        padding: 0;        margin: 0;        list-style-type: none;      }      #box>li:first-child{        margin-top: 0;;      }      #box>li:last-child{        margin-bottom: 0;      }      li{        background: #f23;        padding: 5px 10px;        margin: 5px;      }      #btn{        width: 120px;        height: 10%;        margin: 2.5% calc(50% - 60px);      }      dialog::backdrop {        background: rgba(0,0,0,0.9);      }     </style>  </head>  <body>    <button id="btn">click btn</button>    <ul id="box"></ul>    <dialog id="dial"></dialog>        <script type="text/javascript" src="http://cdn.bootcss.com/redux/3.5.2/redux.min.js" ></script>    <script type="text/javascript">      var store;      Type1();      btn.addEventListener("click",function() {        store.dispatch({type:"act",doAddItem:true});      });            function renderListItem(index, callback) {        box.innerHTML+="<li><p>user "+index+"</p><p>your words here.</p></li>";        !!callback && callback();      }      function showLoading (msg, isCanClose) {        dial.innerHTML=msg;        !dial.open && dial.showModal();        isCanClose && (dial.onclick=function(){this.close();dial.onclick=null;});      }      function hideLoading () {        dial.close();      }      function Type1(){        var FLAGS={          INCREMENT:"i",          DECREMENT:"d",          SAYHI:"s"        };        function counter(state, action) {          !state && (state=1);          return (action===FLAGS.INCREMENT)?(++state):(--state);        }        function sayHello(state, action) {          state=!!action.name?action.name:"robin";          return (action.word||"hello")+", "+state;        }        function asyncCall (callback) {          window.setTimeout(function () {            callback && callback();          },3000);        }        function addListItem (state, param) {          if(typeof param.asyncCall!=="number"){            showLoading("waiting for fetching......");            (typeof state!=="number") && (state=-1);            asyncCall((function (state) {              return function () {               store.dispatch({type:"act",doAddItem:{asyncCall:state}});              };            })(state));            return "fetching";          }else{            var msg;            state=param.asyncCall;            (~~(10*Math.random()))%2===0 && (msg="internal error");            if(!msg){              renderListItem(++state, hideLoading);            }else{              showLoading("error : "+msg, true);            }            return state;          }        }        function Reducers (state, action) {          !state && (state={});          !!action.doSayHi && (state.sayHello=sayHello(state.sayHello, action.doSayHi));          !!action.doCounter && (state.counter=counter(state.counter, action.doCounter));          !!action.doAddItem && (state.itemCount=addListItem(state.itemCount, action.doAddItem));          return state;        }                store=Redux.createStore(Reducers);        store.subscribe(()=>{          var state=store.getState();          console.log("state changed to : ", state);        });        console.log("init state is : ",store.getState());                function action(conf){          var res={type:"action"};          if(!!conf){            !!conf.doSayHi && (res.doSayHi={name:conf.doSayHi.name, word:conf.doSayHi.word});            !!conf.doCounter && (res.doCounter=conf.doCounter);            !!conf.doAddItem && (res.doAddItem=conf.doAddItem);          }          return res;        }                var act=action({          doSayHi:{            name:"Gant",            word:"Good noon"          }        });        store.dispatch(act);                act=action({          doCounter:FLAGS.INCREMENT        });        store.dispatch(act);                act=action({          doSayHi:{            name:"Rassual",            word:"Good morning"          }        });        store.dispatch(act);                act=action({          doSayHi:{            name:"dear dd",            word:"Good evening"          },          doCounter:FLAGS.DECREMENT        });        store.dispatch(act);      }    </script>  </body></html>