npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vedux

v0.1.6

Published

Provide redux in weapp. Less count of setdata in weapp.

Downloads

6

Readme

vedux

概述

  • vedux是微信小程序和redux绑定库,类react-redux。
  • wechat-weapp-redux的基础上改进,控制setdata次数与渲染次数,在页面的交互、加载、跳转时setdata次数减少50-80%,渲染时间减少约50%。
  • 微信小程序 + vedux + redux + webpack 工程化脚手架参考 https://github.com/ludejun/wxapp-webpack

特性

有如下功能特性:

  • Redux store变化时禁止后台页面setdata,后台页面的setdata汇总到此页面onload时进行;
  • 优化stateDiff算法;
  • 过滤与当前页面无关的变更;
  • 内部对action触发做节流处理,允许不节流,默认节流;
  • 支持给action传入callback,在action触发后执行;
  • connect的传参mapStateToData,支持传入options(即onLoad的options);
  • connect新增参数mergeProps(对mapStateToData的返回结果做进一步处理);
  • connect新增参数extraOptions(给mergeProps方法传参);
有以下注意点:
  • Store.getState()中某个状态的属性值禁止为Set, WeakSet, Map, WeakMap, Symbol类型。不然将分辨不出有state变化
  • 每一个dispatch的action默认都为异步100ms执行,合理节流。当有某些操作后,有立即执行并且依赖前一个操作的,可以将此action变为同步执行,{lazy: false},详见下方示例。
  • store中存储的state值,应保持为基础类型或object,且state的值不应过大

快速接入

yarn add vedux

安装之后:

Step 1:创建store,纯粹redux API

store.js

const {
  createStore,
  // applyMiddleware,
  // compose,
} = require('redux');
const reducer = require('./reducers'); // reducer聚合文件
const store = createStore(
  reducer,
);
module.exports = store;

Step 2:app上绑定store

app.js

import { Provider } from 'vedux';
import store from './store';
const config = Provider(store)({
  onLaunch() {
    // TODO
  },
});
App(config);

Step 3:在页面上绑定store,比如首页,写法和redux类似

pages/index/index.js

import { connect } from 'vedux';
import { fetchAPI } from '../../actions/home'; // 下面创建
const pageConfig = {
  data: {
    motto: 'Hello World!',
    userInfo: {},
  },
  onLoad() {
    // 异步触发1次,最终态Hello Vedux!
    this.fetchAPI({motto: 'Hello Vedux!'})
  },
};
const mapStateToData = ({user, home}) => {
  return {
    userInfo: user.userInfo,
    motto: home.motto,
  };
};
const mapDispatchToPage = dispatch => ({
  storeUserInfo: userInfo => {
    dispatch(storeUserInfo(userInfo));
  },
  fetchAPI: (payload) => {
    // action第二个参数是callback,当这次action引起data变更后触发
    dispatch(fetchAPI(payload, () => {
      // TODO
    }))
  },
});
Page(connect(
  mapStateToData,
  mapDispatchToPage,
)(pageConfig));

Step 4:创建redux数据流中的模版文件:action、reducer

actions/home.js

export const types = {
  HOME_FETCH_API: 'HOME_FETCH_API',
};
export function fetchAPI(payload, cb, options) {
  return {
    type: types.HOME_FETCH_API,
    payload,
  };
}

reducers/home.js

import { types } from '../actions/home';
const initialState = {
  motto: null,
};
export default function user(state = initialState, action = {}) {
  switch (action.type) {
    case types.HOME_FETCH_API:
      return {
        ...state,
        motto: action.payload.motto,
      };
    default:
      return state;
  }
}

最后

这样redux数据流就跑下来了,可以通过绑定在app上的store来控制全局状态的页面更新,通过mapStateToData可以将变化之后的state打到页面的data中,并自动让页面刷新。dispatch导致的页面data变化默认不是同步的。当然也有些场景,比如登录后,dispatch必须为同步可以参考后续API文档或者高阶使用文档。

API介绍

vedux的API整体上比较简单,具体使用示例详见高级使用。主要分为三部分:connect参数、reducer返回的state可以多加options、Provider:

  1. connect

    | 参数 | 类型 | 是否必填 | 说明 | | ----------------- | -------- | -------- | ------------------------------------------------------------ | | mapStateToData | Function | 否 | 页面需要的store数据,似redux connect的mapStateToProps。函数可以两个参数,第一个为需要的state,第二个为onLoad的options,支持拿schema中的数据在此函数中做运算 | | mapDispatchToPage | Function | 否 | 绑定页面要用的action creator,同redux connect的mapDispatchToProps | | mergeProps | Function | 否 | 对mapStateToData的返回结果做进一步处理的函数,似redux connect的mergeProps。函数可以三个参数,详见高级使用注释 | | extraOptions | Object | 否 | 给mergeProps方法传参 |

  2. reducer

| 属性 | 类型 | 是否必填 | 说明 | | ------------------ | -------- | -------- | ------------------------------------------------------------ | | [CONST.VEDUX_CB] | Function | 否 | store变化后页面刷新后(setdata)的回调,不管是同步还是异步 | | [CONST.VEDUX_OPTS] | Object | 否 | 可以控制此次store变化导致的页面setdata是同步,还是debounce 100ms。如含有{lazy:false}则为同步 |

注:CONST为vedux库暴露出来的常量,demo见高级使用

  1. Provider

| 参数 | 类型 | 是否必填 | 说明 | | ----- | ------ | -------- | ------------------------------------------------------------ | | store | Object | 是 | 以全局store为参数,返回一个处理appConfig的函数(此函数以appConfig为参数),见快速使用的app.js |

高级使用

app.js

import { Provider } from 'vedux';
import store from './store';

const config = Provider(store)({
  onLaunch() {
    // TODO
  },
});

App(config);

actions/home.js

export const types = {
  HOME_FETCH_API: 'HOME_FETCH_API',
};

const fetch = (data, t = 0) => new Promise((resolve) => {
  setTimeout(resolve, t, data)
});

export function fetchAPI(payload, cb, options) {
  return dispatch => {
    return fetch(payload, 1500).then(
      data => {
        dispatch({
          type: types.HOME_FETCH_API,
          cb, // 示例:传递vedux回调函数
          options, // 示例:传递vedux可选配置
          payload,
        })
      },
    )
  };
}

reducers/home.js

import { types } from '../actions/home';
import { CONST } from 'vedux';

const initialState = {
  motto: null,
};

export default function user(state = initialState, action = {}) {
  switch (action.type) {
    case types.HOME_FETCH_API:
      return {
        ...state,
        motto: action.payload.motto,
        // vedux回调函数【专用key】
        [CONST.VEDUX_CB]: action.cb,
        // vedux可选配置【专用key】
        [CONST.VEDUX_OPTS]: action.options,
      };

    default:
      return state;
  }
}

pages/index/index.js

import { connect } from 'vedux';
import { fetchAPI } from '../../actions/home';

const pageConfig = {
  data: {
    motto: 'Hello World!',
    userInfo: {},
  },
  onLoad() {
    // 触发1次,最终态Hello Vedux7!
    this.fetchAPI({motto: 'Hello Vedux!'})
    this.fetchAPI({motto: 'Hello Vedux2!'})
    this.fetchAPI({motto: 'Hello Vedux3!'})
    this.fetchAPI({motto: 'Hello Vedux4!'})
    this.fetchAPI({motto: 'Hello Vedux5!'})
    this.fetchAPI({motto: 'Hello Vedux6!'})
    this.fetchAPI({motto: 'Hello Vedux7!'})
    // 触发7次,最终态Hello Vedux7!
    this.fetchAPI2({motto: 'Hello Vedux!'})
    this.fetchAPI2({motto: 'Hello Vedux2!'})
    this.fetchAPI2({motto: 'Hello Vedux3!'})
    this.fetchAPI2({motto: 'Hello Vedux4!'})
    this.fetchAPI2({motto: 'Hello Vedux5!'})
    this.fetchAPI2({motto: 'Hello Vedux6!'})
    this.fetchAPI2({motto: 'Hello Vedux7!'})
  },
};

const mapStateToData = ({user, home}, options) => {
  return {
    userInfo: user.userInfo,
    motto: home.motto,
  };
};

const mapDispatchToPage = dispatch => ({
  storeUserInfo: userInfo => {
    dispatch(storeUserInfo(userInfo));
  },
  fetchAPI: (payload) => {
    // action第二个参数是callback,当这次action引起data变更后触发
    dispatch(fetchAPI(payload, () => {
      // TODO
    }))
  },
  fetchAPI2: payload => {
    // action第二个参数是options,目前可以设置
    // lazy [boolean] 是否延时setData,默认true,即延时100ms
    dispatch(fetchAPI(payload, () => {
      // TODO
    }, {
      lazy: false,
    }));
  },
});

// 用于处理本次action触发变更的数据,用于最终做stateDiff
const mergeProps = (
  propsFromState, // 本次改动的数据
  page, // 当前页面
  ownProps, // onLoad的options以及extraOptions
) => {
  return {
    // 页面本身props
  };
};

const extraOptions = {
  // mergeProps需要的额外参数
};

Page(connect(
  mapStateToData,
  mapDispatchToPage,
  mergeProps,
  extraOptions,
)(pageConfig));

store导致setdata后的回调

在某些场景,此次dispatch action后,需要在页面渲染后做一些回调,比如曝光埋点、页面渲染计时等。在上例中,fetchAPI的第二个参数会传给reducer的[CONST.VEDUX_CB]专用key,这就是setdata后的回调。

异步action,中间件使用

比如thunk使用,接入方式和react-redux一样

store.js

const {
  createStore,
  applyMiddleware,
  // compose,
} = require('redux');
import thunk from 'redux-thunk';
const reducer = require('./reducers');
const store = createStore(
  reducer,
  applyMiddleware(thunk)
  //    createEnhancer({
  //        beforeDispatch: [],
  //        afterDispatch: [wmRequest.update],
  //    })
);
export default store;

action/home.js

export const types = {
  HOME_FETCH_API: 'HOME_FETCH_API',
};
const fetch = (data, t = 0) =>
  new Promise(resolve => {
    setTimeout(resolve, t, data);
  });
export function fetchAPI(payload) {
  return dispatch => {
    return fetch(payload, 1500).then(data => {
      dispatch({
        type: types.HOME_FETCH_API,
        payload: data,
      });
    });
  };
}