摘抄自https://juejin.im/post/5b067f6ff265da0de02f3887

wepy 框架本身是支持 Redux 的,我们在构建项目的时候,将 是否安装 Redux 选择 y 就好了,会自动安装依赖,运行项目后看官方给的demo确实是可以做到的,但是官方文档里却对这一块只字不提,经过我自己尝试了一波,这才稍微摸清了它的使用方式,赶紧拿来与你们分享~

注意了,接下来划重点了~

具体实现

运行我们的项目,发现官网已经给了我们一些 Redux 的使用方法,实际上主要是放在 store 文件夹下面了,我们现在来一探究竟~

step1

入口文件 index.js ,里面主要是 初始化 Redux , 其中 promiseMiddleware 是一个中间件,方便后面 action 做异步处理~ reducers 是一个纯函数,用于接受 Action 和当前 State 作为参数,返回一个新的 State~

import { createStore , applyMiddleware } from 'redux'
import promiseMiddleware from 'redux-promise'
import reducer from './reducers' const Store = createStore(
reducer ,
applyMiddleware(promiseMiddleware)
) export default configStore => Store 复制代码

step2

剩下三个文件夹分别是 types reducersactions ,其中 types 用于定义我们要触发的 action 的名称,也就是表示 action的名称,这里我定义了 counterlist 两个 types ,内容分别如下:

counter.js

export const INCREMENT = 'INCREMENT'

export const DECREMENT = 'DECREMENT'

export const ASYNC_INCREMENT = 'ASYNC_INCREMENT'
复制代码

list.js

export const ADD = 'ADD'

export const REMOVE = 'REMOVE'
复制代码

最后通过 types 文件夹的入口文件 index.js 将他们暴露出去~

export * from './counter'
export * from './list'
复制代码

step3

reducers文件件存放我们的纯函数,用来更改我们的状态 , 他也有一个入口文件 index.js,定义如下:

    import { combineReducers } from 'redux'
import counter from './counter'
import list from './list' export default combineReducers({
counter ,
list
}) 复制代码

首先将 counterlist 的分别引入进来,通过 redux 定义的 combineReducers 函数,将所有的 reducers 合并成一个整体,方便我们后面对其进行管理!

那么 counterlist 对应的 reducer 分别是 什么样的?我们直接看代码:

counter.js

    import { handleActions } from 'redux-actions'
import { INCREMENT , DECREMENT , ASYNC_INCREMENT } from '../types/counter' const defaultState = {
num: 0 ,
asyncNum: 0
} export default handleActions({
[INCREMENT](state){
return{
...state,
num : state.num + 1
}
},
[DECREMENT](state){
return{
...state,
num : state.num - 1
}
},
[ASYNC_INCREMENT](state, action){
return {
...state ,
asyncNum : state.asyncNum + action.payload
}
}
},defaultState)
复制代码

我们介绍一下 counter.js 里面的 reducer , 首先引入了 handleActions 方法用来创建 actions , 它将多个相关的 reducer 写在一起也是 ,方面后期维护,也方便后期通过 dispatch 来调用他们更改 state 里面的状态,它主要接收两个参数,第一个参数时候个大对象,里面存放多个 reducer , 第二个参数是初始化的时候 state 的状态值,因此,我们一开始就定义了 defaultState ;

接着,我们看看里面的 reducer , 分别定义了 INCREMENTDECREMENTASYNC_INCREMENT 三个 reducer ,前两个比较简单,分别是对 state 里面的 num 值进行 加减操作 , 最后一个是通过 action.payload 的值来对 asyncNum 的值进行异步操作的,具体怎么做到的,我们一会再看~

list.js 里定义的 reducer 跟上面类似,我就不一一介绍了,直接贴代码即可~

list.js

    import { handleActions } from 'redux-actions'
import { ADD , REMOVE } from '../types/list' const defaultState = [
{
title : '吃饭' ,
text : '今天我要吃火锅'
},
{
title : '工作' ,
text : '今天我要学习Redux'
}
] export default handleActions({
[ADD]( state , action ){
state.push(action.payload)
return [...state]
},
[REMOVE]( state , action ){
state.splice( action.payload , 1 );
return [ ...state ] }
},defaultState) 复制代码

step4

我们终于走到这一步了,到这里,你已经离预期不远啦,就剩一个 actions 文件件了,毫不例外,入口文件 index.js 如下:

index.js

    export * from './counter'
复制代码

很简单,只需要将所需的 action 导出即可~

这个里面我只定义了 counteraction , 也就是为了刚才异步数据 asyncNum 准备的~

counter.js

    import { ASYNC_INCREMENT } from '../types/counter'
import { createAction } from 'redux-actions' export const asyncInc = createAction(ASYNC_INCREMENT,()=>{
return new Promise(resolve=>{
setTimeout(()=>{
resolve(1)
},1000)
})
})
复制代码

这里跟 reducer 里面的要区分,这里是可以对数据进行一系列处理的,我们通过 createAction 创建一个 action , 该方法主要有两个参数,第一个参数 type 表示 action 的类型,第二个参数 payloadCreator 是一个 function,处理并返回需要的 payload ;如果空缺,会使用默认方法。这里我们是延迟 1s 后返回一个 1

ok,到此为止,你已经基本完成了一个 redux 的容器~

接下来,就是展示它怎么使用的时候了~

step5

我们创建一个 index.wpy 的文件,这里我把代码直接贴出来,然后慢慢来分析看看~

代码如下:

    <template lang="wxml">
<view class="container">
<text>同步{{ num }}</text>
<text>异步{{ asyncNum }}</text>
<button @tap="increment" type="primary">加一</button>
<button @tap="decrement" type="primary">减一</button>
<button @tap="asyncIncrement" type="primary">异步加一</button> <button @tap="addList">添加</button> <view class="box">
<view class="item" wx:for-items="{{ todoList }}" wx:key="index">
<view class="title">{{ item.title }}</view>
<view class="content">{{ item.text }}</view>
<button type="primary" class="delete" @tap="delete({{index}})">删除</button>
</view>
</view> </view> </template> <script>
import wepy from 'wepy'
import { connect } from 'wepy-redux'
import { INCREMENT , DECREMENT } from '../store/types/counter'
import { asyncInc } from '../store/actions' @connect({
num(state){
return state.counter.num;
},
asyncNum(state){
return state.counter.asyncNum;
}
},{
increment : INCREMENT ,
decrement : DECREMENT ,
asyncIncrement : asyncInc
}) export default class Index extends wepy.page { components = {} computed = {
todoList(){
return wepy.$store.getState().list;
}
} methods = {
delete(index){
wepy.$store.dispatch({ type : 'REMOVE' , payload : index })
},
addList(){
wepy.$store.dispatch({ type : 'ADD' , payload : {
title : '学习' ,
text : '好好学习'
}})
}
} onLoad () {
console.log(wepy.$store.getState())
}
}
</script> <style lang="less">
text{
display: block;
text-align: center;
margin: 10px auto;
}
button{
width: 90%;
display: block;
margin: 10px auto;
} .item{
display: flex;
align-items: center;
text-align: center;
padding: 0 15px;
.title{
font-size: 14px;
line-height: 20px;
margin: 10px auto;
}
.content{
font-size: 15px;
flex: 1;
} .delete{
width: 70px;
height: 40px;
line-height: 40px;
}
}
</style> 复制代码

不出意外,运行后,你的小程序的界面会跟下面一样————丑~

点一点看,发现卧槽,很牛逼,有木有~

ok~ 我们一起看看上面的代码是怎么做的~

样式结构方面我们这里不做讨论,主要看 js 部分,其中 import { INCREMENT , DECREMENT } from '../store/types/counter'import { asyncInc } from '../store/actions' 分别表示从 counteractions 导出所需的 action

我们重点看看 从 wepy-redux 中 引入的 connect ,这个 connect 很关键,它是连接 组件 和 状态 的桥梁,主要用法是 @connect(states, actions) ~

  • states: 访问 state 上的值,可以是数组或者对象,如果是对象的话,则包含的是 K-V 对,V 可以是函数还可以是字符串,如果是字符串的话则默认获取 state[V], 否则的话则是使用返回值;而对于如果是数组的话(数组中的项只能为字符串),则认为是相同的 K-V 对象结构。states 最终会附加到组件的 computed 属性值上。

  • actions: 只能传入对象,对象的 K-V 结构,如果 V 是字符串的话,则直接会 distatch 如下的结构:

    // args 就是调用传入参数
    {
    type: val,
    // 修正一般情况下的参数 一般支持只传一个参数
    // 如果真的是多个参数的话 那么 payload 就是参数组成的数组
    payload: args.length > 1 ? args : args[0]
    }
    复制代码

    如果是一个函数 fn,则会 dispatch(val.apply(store, args)),否则的话则直接 dispatch(V)

这里,我们定义的 加一减一异步加一 操作直接映射到 INCREMENTDECREMENTasyncInc 上,也就是相当于直接 dispacth 对应的操作,对数据进行变更~

现在效果应该可以看到了吧~

当然,我们也可以手动调用容器的 dispatch 方法对数据进行修改,我们的添加删除 就是这么做的, 点击添加按钮,我们直接 dispatch 列表中的 ADD action,如下:

wepy.$store.dispatch({ type : 'ADD' , payload : {
title : '学习' ,
text : '好好学习'
}})
复制代码

删除某一项,只需 dispatch 列表的 REMOVE action ,传入要删除的索引即可 :

delete(index){
wepy.$store.dispatch({ type : 'REMOVE' , payload : index })
},
复制代码

不信你看~

大功告成~

结语

ok,到现在我们也算是摸索着搞出来了一点名堂,回头来看发现其实也并没有那么困难吧,有学过 React 的同学应该对此不陌生,学起来光速吧~ 不过对于我来说,我确实是属于初探,希望能给跟我一样萌新的小伙伴一个抛砖引玉的作用,如果有哪里写的不对的地方,还请批评斧正~

代码我已经托管到 github上,有需要的小伙伴自行下载查阅~

ps:wepy真的有很多坑~

作者:Chris威
链接:https://juejin.im/post/5b067f6ff265da0de02f3887
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最新文章

  1. ORACLE &quot;ORA--22992:无法使用远程表选择的LOB定位器,database link&quot;
  2. 解决nf_conntrack: table full, dropping packet问题
  3. PHP中的常用魔术方法
  4. ANGULAR 开发用户选择器指令
  5. 设计模式 Mixin (混入类)
  6. 关于打开Eclipse时出现eclipse failed to create the java virtual machine与locking is not possible in the direc
  7. 福建百度seo和推广,关键词排名优化,网络营销推广培训
  8. Android Service与Activity的交互
  9. MySQL5.7开启独立表空间参数innodb_file_per_table【原创】
  10. [HackerRank]New Year Chaos[UNDONE]
  11. idea设置代码块
  12. js对象之window和document区别
  13. AangularJS入门总结二
  14. docker小demo
  15. gradle多项目 svn依赖
  16. Android-自定义开关(ViewGroup版)
  17. HDU1160:FatMouse&#39;s Speed(最长上升子序列,不错的题)
  18. Phoenix映射HBase数据表
  19. 平衡树学习笔记(6)-------RBT
  20. 简易高重用的jdbcutils工具封装实现类以及简易连接池实现

热门文章

  1. kvm安装及简单使用
  2. 安装Chrome扩展程序xpath
  3. IPC远程入侵
  4. &lt;JavaScript&gt; 普通函数与构造函数的区别
  5. web开发的三层架构
  6. thinkphp模版主题使用方法
  7. 启动Spring boot报错:nested exception is java.sql.SQLException: Field &#39;id&#39; doesn&#39;t have a default value
  8. mfc判断当前程序是否正在运行
  9. 运行React Native项目出现白屏,无法运行
  10. Flutter 路由 页面间跳转和传参 返回