4、Wepy-Redux基本使用 参考自https://blog.csdn.net/baidu_32377671/article/details/86708019
摘抄自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 reducers 和 actions ,其中 types 用于定义我们要触发的 action 的名称,也就是表示 action的名称,这里我定义了 counter 和 list 两个 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
})
复制代码
首先将 counter 和 list 的分别引入进来,通过 redux 定义的 combineReducers 函数,将所有的 reducers 合并成一个整体,方便我们后面对其进行管理!
那么 counter 和 list 对应的 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 , 分别定义了 INCREMENT、 DECREMENT 和 ASYNC_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 导出即可~
这个里面我只定义了 counter 的 action , 也就是为了刚才异步数据 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' 分别表示从 counter 和 actions 导出所需的 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)
这里,我们定义的 加一 、 减一 和 异步加一 操作直接映射到 INCREMENT、DECREMENT、asyncInc 上,也就是相当于直接 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
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
4、Wepy-Redux基本使用 参考自https://blog.csdn.net/baidu_32377671/article/details/86708019的更多相关文章
- Mui本地打包笔记(一)使用AndroidStudio运行项目 转载 https://blog.csdn.net/baidu_32377671/article/details/79632411
转载 https://blog.csdn.net/baidu_32377671/article/details/79632411 使用AndroidStudio运行HBuilder本地打包的Mui项目 ...
- 银行卡所属公司判断 参考自https://blog.csdn.net/well2049/article/details/79429130
在网上找到了一个银行卡的验证,通过阿里的支付宝接口进行校验,能够准确识别是否存在,归属行,卡号类型是储蓄卡(DC)还是信用卡(CC). 接口api:需要传入的2个参数,卡号cardNo和cardBin ...
- https://blog.csdn.net/blmoistawinde/article/details/84329103
背景 很多场景需要考虑数据分布的相似度/距离:比如确定一个正态分布是否能够很好的描述一个群体的身高(正态分布生成的样本分布应当与实际的抽样分布接近),或者一个分类算法是否能够很好地区分样本的特征 ...
- 转载 WPF -- 控件模板 (ControlTemplate)(一) https://blog.csdn.net/qq_23018459/article/details/79899838
ControlTemplate(控件模板) https://blog.csdn.net/qq_23018459/article/details/79899838 WPF包含数据模板和控件模板,其中 ...
- https://blog.csdn.net/u011489043/article/details/68488459
转自https://blog.csdn.net/u011489043/article/details/68488459 String 字符串常量 StringBuffer 字符串变量(线程安全) ...
- 程序员的沟通之痛https://blog.csdn.net/qq_35230695/article/details/80283720
个人理解: 一般刚工作的程序员总觉得技术最重要.但是当工作年限超过3年.或者岗位需要涉及汇报.需求对接等就会发现沟通非常重要.也许在大公司还不那么明显,但是在小公司.小团队或者创业,沟通甚至可以说是第 ...
- https://blog.csdn.net/uftjtt/article/details/79044186
https://blog.csdn.net/uftjtt/article/details/79044186
- 自动车牌识别(ALPR)---https://blog.csdn.net/ELEVEN_ZOU/article/details/80893579
1.基本功能:从一张或者一系列的图片中提取车牌信息,比如车牌号码.车牌颜色等信息. 2.功能扩展:车型.车品牌.车牌类型等. 3.应用方向:电子交易系统(停车自动收费.收费站自动支付等).交通执法.交 ...
- Nginx 配置location root 转自https://blog.csdn.net/rofth/article/details/78581617
nginx指定文件路径有两种方式root和alias,root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上. 最基本的区别 ...
随机推荐
- 分享一个自己做的SpringMVC的PPT,由于比较忙只写了一些重要的部分
- Linux ldd -- 查看可执行文件所依赖的动态链接库
我们知道“ldd”这个命令主要是被程序员或是管理员用来查看可执行文件所依赖的动态链接库的.是的,这就是这个命令的用处.可是,这个命令比你想像的要危险得多,也许很多黑客通过ldd的安全问题来攻击你的服务 ...
- 全国数据json
{ "provinces": { "province": [ { "ssqid": "110000", "ss ...
- export default {} 和new Vue()区别?
export default 的用法:相当于提供一个接口给外界,让其他文件通过 import 来引入使用. 而对于 new Vue({})部分, 只是创建一个Vue的实例 就是相当于创建一个根组件 h ...
- PHP中smarty与MYSQL数据库的连接
进行与MYSQL数据库的关联 先从最简单的数据库查询语句开始 1.先创建mysql数据库 仅仅创建一个测试数据 2.引用smarty框架 3.按照上文在damo文件夹下创建smarty_inc.php ...
- CentOS7.5使用RPM包安装MySQL5.7.22
参考:https://blog.csdn.net/sevenkoala/article/details/76163853 1,安装环境查看 2,下载安装rpm包 下载地址:https://downlo ...
- Ubuntu 14.04安装vim8
本文介绍两种方法安装 VIM8.1 方法一:GitHub下载源码手动安装 1.查看系统是否有安装vim:如果有,先删除 dpkg -l | grep vim 2.从git上下载 git clone h ...
- 让SNIPER-MXNet从标准的COCO格式数据集中直接使用file_name作为图片路径
告别项目中“依index生成路径”的方法,直接使用我们在生成.json标签时就已经写入的图片路径(这里我写入的是绝对路径 full path)来获取图片. 需要做的,用以下代码替换SNIPER/lib ...
- OPC Utgard的数据访问方式
1.同步读取某个点位的值 Item项的read()方法 Server server = new Server(BaseConfiguration.getCLSIDConnectionInfomatio ...
- Centos7 yum源配置及关闭防火墙
清理源 #yum clean all更新源缓存 #yum makecache更新源 #yum update 设置主机名: #hostnamectl set-hostname 查看防火墙状态 #syst ...