Использование управления состоянием Redux в мини-программах WeChat
предисловие
Некоторое время назад я разрабатывал небольшие программы, используя официальный фреймворк.wepy
, если вы не знаете одноклассников, вы можете пойти к немуОфициальный сайтОбратитесь к соответствующим материалам, чтобы узнать; я должен сказать, что этот фреймворк действительно намного удобнее, чем традиционный режим разработки небольших программ. Его синтаксис очень похож на синтаксис Vue. Он может осуществлять разработку компонентов, а также настраивать и поддерживать код позади. ..но! ! Ям у этого фреймворка не мало и при разработке всегда будут странные проблемы.Наступайте сами,чтобы прогрессировать~~
Столько ерунды, кхм, вышеописанное не в фокусе нашего обсуждения, сегодня наш фокус - использование в небольших программахRedux
для государственного управления,Redux
Это контейнер для внешнего управления состоянием.Для создания масштабных приложений очень удобно управлять общими данными и состоянием в нем.Я научилсяReact
Одноклассники, знакомые с ним, не должны быть незнакомы с ним.посмотри;
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
;
хорошо, пока вы в основном завершили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>
Неудивительно, что после запуска интерфейс вашего апплета будет таким, как показано ниже — Ugly~
Немного поискав, я нашел корыто, оно очень классное, есть дрова~
хорошо~ Давайте посмотрим, как выполняется приведенный выше код~
С точки зрения структуры стиля, мы не будем здесь ее обсуждать, мы в основном рассмотрим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 })
},
Если не веришь, посмотри~
Вы закончили~
Эпилог
хорошо, до сих пор мы пытались придумать маленький трюк. Оглядываясь назад, мы обнаружили, что это было не так уж сложно. Я научилсяReact
Мои одноклассники должны быть знакомы с этим, давайте изучим скорость света~ Но что касается меня, я действительно новичок, и я надеюсь дать такому новому другу, как я, роль в привлечении новых идей.Если что-то не так в письме , Пожалуйста, также критикуйте топор~
код, который я разместил дляgithubНа, если вам это нужно, вы можете скачать его самостоятельно~
пс:wepy
Там действительно много дыр~