1. Некоторые способы борьбы с состоянием в прошлом
Первый: повесить globalData на приложение, так будет писаться прямо в приложении, так удобнее присваивать значения.
App.js
App({
globalData: {
name: '前端学者',
// ...other globalData
},
// ...other globalData
});
// 取值
var name = getApp().globalData.name;
// 赋值
getApp().globalData.name = '改个名字';
Второй: определите один или несколько файлов libData для хранения данных самостоятельно, создайте свои собственные колеса и просто катите их, если хотите бросить
например, libData.js
module.exports = {
name: '前端学者',
// ...other globalData
}
// ...other
// 简单使用
var store = require('./path/to/lib/libData.js');
// 取值
var name = store.name;
// 赋值
store.name = '改个名字';
Третий тип: хранение данных, которые будут использоваться на странице данных или непосредственно на странице, относительно разбросано и не способствует управлению и обслуживанию, но этого достаточно для сверхмалых проектов, которые необходимо реализовать быстро. Не смейтесь, наш интерфейс не боится так писать, O(∩_∩)О, ха-ха~
dataInPage.js
Page({
data: {
name: '前端学者'
},
name: '前端学者'
});
// 取值
var name = this.data.name;
var name = this.name;
// 赋值
this.setData('name', '改个名字');
this.name = '改个名字');
2. Для обработки данных о статусе вышеперечисленные методы могут иногда смешиваться.По мере увеличения сложности проекта статусом будет трудно управлять.
Поэтому нам нужно учиться на некоторых из существующих отличных и зрелых решений в веб-сфере. Сегодняшняя главная героиня — это она. Всем она может быть знакома. Добро пожаловать.ReduxПоявляться! Все виды информации в Интернете были представлены подробно, и студенты, которые не уверены, должны понятьRedux, здесь только подробное описание как использовать в апплете, и как использовать в апплетеReactИспользование очень похоже на основную библиотекуmina-redux.jsАвтор (ранее wechat-weapp-redux) изменил вот так, и этот руль уже очень хорош. Код размещен непосредственно ниже.Хотя существует много кодов, они имеют реальную справочную ценность сайта, поэтому они публикуются напрямую.
Не используйте никакие инструменты сборки, поместите все хуки настроек проекта в инструменты разработчика WeChat, щедро используйте импорт и экспорт, теперь вам не нужно писать свою собственную сборку.
- от ES6 до ES5
- Автодополнение стиля при загрузке кода
- Автоматически сжимать код при загрузке
- Не проверяет безопасные доменные имена, версии TLS и сертификаты HTTPS.
Core или Redux и несколько полезных связанных библиотек, они оптимизированы для использования в Интернете, не используются инструменты управления пакетами npm и т. д.
В папке lib:
- redux.js(основной файл, требуется)
- redux-logger(core.js, deep-diff.js, defaults.js, diff.js, helpers.js, index.js — все для печати журналов, необязательно)
- redux-thunk.js(рекомендуется промежуточная обработка асинхронного действия)
- mina-redux.js(Должен быть выбран основной файл, который синхронизирует данные о отправке и складе избыточности со страницей)
- remote-redux-devtool.js(Для удаленной отладки вы можете визуально увидеть поток данных, очень мощный, необязательный)
- remotedev-server.js(Услуги удаленного отладки, необязательно, удобная отладки)
- regenerator-runtime.js(асинхронная библиотека facebook, не имеет ничего общего с избыточностью, необязательна, настоятельно рекомендуется)
Сначала напишите редукторы типа действия, связанные с редукцией
app.redux.js (личное предпочтение записи редьюсера действия типа в файле)
/**
* 处理小程序生命周期和载入的一些数据
*/
import regeneratorRuntime from '../lib/regenerator-runtime';
import util from '../lib/util';
import api from '../lib/api';
import { minaScecne } from '../config/config';
const WX_SYSTEM_INFO = 'WX_SYSTEM_INFO';
const WX_USER_INFO = 'WX_USER_INFO';
const WX_ON_LAUNCH = 'WX_ON_LAUNCH';
const WX_GET_CODE = 'WX_GET_CODE';
const WX_API_PROMISIFY = 'WX_API_PROMISIFY';
const LOGIN_BEGIN = 'LOGIN_BEGIN';
const LOGIN_PENDING = 'LOGIN_PENDING';
const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
const LOGIN_FAIL = 'LOGIN_FAIL';
// 用法1
// 不用中间件,一个action每次只能dispatch一个action
export const wxApiPromisify = () => ({
type: WX_API_PROMISIFY,
data: util.initWxMethod()
})
export const wxSystemInfo = (data) => ({
type: WX_SYSTEM_INFO,
data: data
})
export const wxUserInfo = (data) => ({
type: WX_USER_INFO,
data: data
})
export const wxOnLaunch = (data = {}) => {
const { scene, query, path } = data;
Object.keys(minaScecne).map((item => {
if (scene.toString() === item) {
data.sceneText = minaScecne[item]
}
}));
return {
type: WX_ON_LAUNCH,
data: data
}
}
// 用法2
// app上以store.dispatch(actionMethodName)的方式调用,可以组合action
export const login = async dispatch => {
const wxLoginResult = await wx.async.login();
await dispatch({
type: WX_GET_CODE,
data: wxLoginResult
})
await dispatch({
type: LOGIN_BEGIN,
data: {
isFetching: false
}
})
await dispatch({
type: LOGIN_PENDING,
data: {
isFetching: true
}
})
if(wxLoginResult.code){
try {
const apiLoginResult = await api.user.login({ code: wxLoginResult.code });
await dispatch({
type: LOGIN_SUCCESS,
data: apiLoginResult
})
wx.setStorageSync('token', apiLoginResult.data.token)
} catch (error) {
await dispatch({
type: LOGIN_FAIL,
data: error
})
}
} else {
await dispatch({
type: LOGIN_FAIL,
data: wxLoginResult.errMsg
})
}
}
// 用法3
// 使用thunk中间件可以对一个action进行细化出多个状态,比如请求,可以做用于处理ui loading
// TODO 写个request action helper 封装一下,不用每次写那么多...
export const thunkExampleAction = () => (
async dispatch => {
const wxLoginResult = await wx.async.login();
await dispatch({
type: WX_GET_CODE,
data: wxLoginResult
})
await dispatch({
type: LOGIN_BEGIN,
data: {
isFetching: false
}
})
await dispatch({
type: LOGIN_PENDING,
data: {
isFetching: true
}
})
if(wxLoginResult.code){
try {
const apiLoginResult = await api.user.login({ code: wxLoginResult.code });
await dispatch({
type: LOGIN_SUCCESS,
data: apiLoginResult
})
wx.setStorageSync('token', apiLoginResult.data.token)
} catch (error) {
await dispatch({
type: LOGIN_FAIL,
data: error
})
}
} else {
await dispatch({
type: LOGIN_FAIL,
data: wxLoginResult.errMsg
})
}
}
);
// 仓库数据结构预定义
const initState = {
wxApiPromisify: {
isFinish: false
},
wxSystemInfo: {},
wxUserInfo: {},
wxOnLaunch: {},
wxLogin: {
code: null,
token: null,
userId: null,
phone: null,
errMsg: null
},
userLogin: {
isFetching: false,
data: null
}
};
export const appReducer = (state = initState, action) => {
switch (action.type) {
case WX_API_PROMISIFY:
return Object.assign({}, state, { wxApiPromisify: { isFinish: action.data } });
case WX_GET_CODE:
return Object.assign({}, state, { wxLogin: action.data });
case WX_SYSTEM_INFO:
return Object.assign({}, state, { wxSystemInfo: action.data});
case WX_USER_INFO:
return Object.assign({}, state, { wxUserInfo: action.data});
case WX_ON_LAUNCH:
return Object.assign({}, state, { wxOnLaunch: action.data});
case LOGIN_BEGIN:
var userLogin = action.data;
userLogin.isFetching = false;
return Object.assign({}, state, { userLogin });
case LOGIN_PENDING:
var userLogin = action.data;
userLogin.isFetching = true;
return Object.assign({}, state, { userLogin });
case LOGIN_SUCCESS:
var userLogin = action.data;
userLogin.isFetching = false;
return Object.assign({}, state, { userLogin });
case LOGIN_FAIL:
var userLogin = action.data;
userLogin.isFetching = false;
return Object.assign({}, state, { userLogin });
default:
return state;
}
};
Запись запуска апплета app.js
import regeneratorRuntime from './lib/regenerator-runtime';
import util from './lib/util'; // 自定义的工具库
import { createStore, applyMiddleware, combineReducers, compose } from './lib/redux';
import thunk from './lib/redux-thunk';
import { Provider } from './lib/mina-redux';
// 所有的reducer 主要分为小程序相关和业务相关两类
import { appReducer } from './redux/app.redux';
import { channelReducer } from './redux/channel.redux';
import { practiceReducer } from './redux/practice.redux';
// 小程序项目常用的操作相关action,如处理小程序启动option,小程序api Promise化,系统信息,小程序用户信息,api登录等
import { wxOnLaunch, wxApiPromisify, wxSystemInfo, wxUserInfo, login } from './redux/app.redux';
import composeWithDevTools from './lib/remote-redux-devtool';
import logger from './lib/redux-logger/index';
// 创建仓库
export const store = createStore(combineReducers({
appReducer,
channelReducer,
practiceReducer,
}), compose(
applyMiddleware(thunk, logger),
composeWithDevTools({ hostname: '127.0.0.1', port: 8080, secure: false })
));
App(Provider(store)({
async onLaunch(option) {
// 处理小程序启动option
store.dispatch(wxOnLaunch(option));
// 小程序api Promise化
store.dispatch(wxApiPromisify());
// 获取小程序系统信息
store.dispatch(wxSystemInfo(wx.getSystemInfoSync()));
// 获取小程序用户信息
store.dispatch(wxUserInfo(await wx.async.getUserInfo()));
// 用户登录(小程序登录 + api登录)
login(store.dispatch);
}
}));
страница home.js
import regeneratorRuntime from '../../lib/regenerator-runtime';
import util from '../../lib/util';
import { connect } from '../../lib/mina-redux';
import { getChannelList } from '../../redux/channel.redux';
const pageConfig = {
data: {
userLogin: {
data: null,
},
channelList: {
data: [],
isFetching: false,
}
},
async onLoad(option) {
try {
console.log(` ${getCurrentPages().slice(-1)[0]['__route__']} onLoad`);
util.initPageOnLoad.call(this, option);
wx.showLoading({
title: '加载中...',
mask: true,
});
// 首先一切后端一切api调用必须在登录后,这里首先等待app生命周期里面拿到登录权限token
await util.waitfor(this.data, ['userLogin', 'data', 'token'], 0, null, 50);
// 之后就可以愉快地进行各种api数据流了,
await this.getChannelList();
wx.hideLoading();
} catch (error) {
console.error(` `, error);
// TODO
}
}
}
// 定义页面上的data,这个是自动注入到page data上的,需要什么就用什么,据说小程序有page data的性能瓶颈,按需注入吧
const mapStateToPage = state => ({
...state.appReducer,
...state.channelReducer,
});
// 定义页面上的方法,直接this.actionName(param)就可以了调用了
const mapDispatchToPage = dispatch => ({
getChannelList: async () => {
await dispatch(getChannelList());
}
});
// 串起来
const nextConfig = connect(mapStateToPage, mapDispatchToPage)(pageConfig);
Page(nextConfig);
3. Хоть код и очень длинный, может выглядеть очень неприятно, но лично мне он кажется намного элегантнее, чем раньше, просто немного с ним ознакомитесь, и наконец увидите конечный эффект (^__^) Ух……
Сначала включите отладку, затем посетите http://localhost:8080 в браузере или используйте плагин отладки Redux DevTools.
$ npm install -g remotedev-server
$ remotedev --hostname=localhost --port=8080
[Busy] Launching SocketCluster
[Active] SocketCluster started
Version: 6.8.0
Environment: dev
WebSocket engine: uws
Port: 8080
Master PID: 14961
Worker count: 1
Broker count: 1
Скриншот страниц AppData/home/home data инструмента разработчика WeChat
Скриншот журнала консоли инструментов разработчика WeChat
Диаграмма структуры данных состояния инструмента Redux RemoteDev
Временная шкала действия инструмента Redux RemoteDev и древовидная структура
Монитор журнала Redux RemoteDev Tools
Redux DevTools имеет множество мощных функций, таких как легендарное «путешествие во времени» и т. д., которые могут реализовать множество интересных функций.
THANKS
[Учебник] Апплет WeChat интегрирует Redux и представляет богатые периферийные инструменты