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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ctsj/vuexgenerator

v2.0.2

Published

Vuex的生成器

Downloads

119

Readme

CTSJ-VuexGenerator

vuex 生成器,能通过 Service 自动映射成组件引用 vuex 的 State、Action 和 Mutation 并带有自动重置功能(此功能是一个 vuex 的插件)

简介

  一个简单的例子,用 vuex 编写一个标椎用户的模块,用户模块中是标准的 CRUD 操作,我们大致会这样去写

  1. 定义 UserService,UserService 大致会是这样
import { stringify } from 'qs';
import request from '@/utils/request';

// 列表
export async function fetchtList(params) {
    return request.get('fetchList');
}

// 详情
export async function fetchtInfo(id) {
    return request.get('fetchtInfo');
}

// 添加
export async function fetchtSave(payload) {
    return request.post('fetchSave');
}

// 删除
export async function fetchtDelete(id) {
    return request.delete('fetchtDelete');
}

// 修改
export async function fetchtUpdate(payload) {
    return request.put('fetchtUpdate');
}
  1. 定义 UserModel,UserModel 大致会是这样
import {
    fetchtList,
    fetchtInfo,
    fetchtSave,
    fetchtDelete,
    fetchtUpdate,
} from '@/services/UserService';

export default {
    namespace: true,
    state: {
        list: {
            list: [],
            total: 0,
        },
        info: {},
    },
    actions: {
        // 列表
        fetchList({ commit, state }, payload) {
            fetchtList(payload).then((response) => {
                if (response.code === 0) {
                    commit('receive', {
                        ...state,
                        list: response.data,
                    });
                }
            });
        },
        // 详情
        fetchInfo({ commit, state }, { id }) {
            fetchInfo(id).then((response) => {
                if (response.code === 0) {
                    commit('receive', {
                        ...state,
                        info: response.data,
                    });
                }
            });
        },
        // 添加
        feachSave({ commit, state }, { success, ...other }) {
            feachSave(other).then((response) => {
                if (response.code === 0) {
                    if (success) {
                        success();
                    }
                }
            });
        },
        // 修改
        feachUpdate({ commit, state }, { success, ...other }) {
            feachUpdate(other).then((response) => {
                if (response.code === 0) {
                    if (success) {
                        success();
                    }
                }
            });
        },
        // 删除
        feachDelete({ commit, state }, { success, id }) {
            feachDelete(id).then((response) => {
                if (response.code === 0) {
                    if (success) {
                        success();
                    }
                }
            });
        },
    },
    mutations: {
        receive(state, payload) {
            const keys = Object.keys(state);
            for (let i = 0; i < keys.length; i++) {
                const key = keys[i];
                state[key] = payload[key];
            }
        },
    },
};
  1. 定义 UserPage, UserPage 大致会是这样
<template>...</template>
<script>
    export default {
    computed: {
    ...mapState({
    list: state => state.user.list.list,
    info: state => state.user.info,
}),
},
    methods: {
    ...mapActions({
    fetchList: 'user/fetchList',
    fetchInfo: 'user/fetchInfo',
    feachSave: 'user/feachSave',
    feachUpdate: 'user/feachUpdate',
    feachDelete: 'user/feachDelete',
}),
    ...mapMutations({
    receive:'user/receive'
}),
}
};
</script>

  我们会发现一个问题,像这样比较常规的 CRUD 操作,从 Service -> Model -> Component 的 computed 和 methods 方法的名字都是一一对应的, 而 Model 中的 actions 操作基本都是调用 Service 中相应的接口,并且注入到数据流当中,而且 Service 也是按照相应模块编写的比如 UserService 就是处理 User 相关的操作, 这样就和 Model 中的 namespace 相对应,再则 Model 中的 Mutations 里面应该只有一个 receive 的 Mutation, 不应该有多个处理,actions 中所有的 commit(mutation)都应该调用 commit('receive')来进行处理 所以我们就可以根据 Service 自动生成 computed 和 methods 和 Model 中的 actions 和 mutations, 我们只处理标椎模块,如果自动生成的这三部分不能满足需求,可以进行重写覆盖

安装

  npm install @ctsj/vuexgenerator
  yarn add @ctsj/vuexgenerator

例子

  1. 定义 UserService
import { stringify } from 'qs';
import request from '@/utils/request';

// &#x5217;&#x8868;
export async function fetchtList(params) {
  return request.get('fetchList');
}

// &#x8BE6;&#x60C5;
export async function fetchtInfo(id) {
  return request.get('fetchtInfo');
}

// &#x6DFB;&#x52A0;
export async function fetchtSave(payload) {
  return request.post('fetchSave');
}

// &#x5220;&#x9664;
export async function fetchtDelete(id) {
  return request.delete('fetchtDelete');
}

// &#x4FEE;&#x6539;
export async function fetchtUpdate(payload) {
  return request.put('fetchtUpdate');
}

// &#x9ED8;&#x8BA4;&#x5BFC;&#x51FA;&#x4E0E;&#x63A5;&#x53E3;&#x5148;&#x5173;&#x7684;&#x53C2;&#x6570;
export default {
  // &#x63A5;&#x53E3;&#x6210;&#x529F;&#x5931;&#x8D25;&#x7684;&#x72B6;&#x6001;&#x952E;
  codeKey: 'code',
  // &#x63A5;&#x53E3;&#x6210;&#x529F;&#x7684;&#x72B6;&#x6001;&#x503C;
  codeSuccessKey: 200,
  // &#x63A5;&#x53E3;&#x6570;&#x636E;&#x7684;&#x952E;
  dataKey: 'data',
  // &#x63A5;&#x53E3;&#x6D88;&#x606F;&#x952E;
  messageKey: 'message',
};
  1. 定义 UserModel
export default {};
  1. 定义 UserPage
<template>
  <a-table :columns="columns" :data-source="userFetchList.list" :loading="loading['user/fetchList']" :pagination="false">
    <a slot="name" slot-scope="text">{{ text }}</a>
    <span slot="customTitle"><a-icon type="smile-o"> Name</a-icon></span>
    <span slot="tags" slot-scope="tags">
      <a-tag v-for="tag in tags" :key="tag" :color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'">
        {{ tag.toUpperCase() }}
      </a-tag>
    </span>
    <span slot="action" slot-scope="text, record">
      <a>Invite &#x4E00; {{ record.name }}</a>
      <a-divider type="vertical">
      <a>Delete</a>
      <a-divider type="vertical">
      <a class="ant-dropdown-link"> More actions <a-icon type="down"> </a-icon></a>
    </a-divider></a-divider></span>
  </a-table>
</template>

<script>
  import { mapState, mapMutations, mapActions, cleanMixin } from '@ctsj/vuexgenerator';
  export default {
    data() {
      return {
        columns: [
            {
              dataIndex: 'name',
              key: 'name',
              slots: { title: 'customTitle' },
              scopedSlots: { customRender: 'name' },
            },
            {
              title: 'Age',
              dataIndex: 'age',
              key: 'age',
            },
            {
              title: 'Address',
              dataIndex: 'address',
              key: 'address',
            },
            {
              title: 'Tags',
              key: 'tags',
              dataIndex: 'tags',
              scopedSlots: { customRender: 'tags' },
            },
            {
              title: 'Action',
              key: 'action',
              scopedSlots: { customRender: 'action' },
            },
        ]
      }
    },
    mounted() {
      this.userFetchListAction();
    },
    mixins: [cleanMixin(['user'])],
    computed: {
      ...mapState(['user']),
    },
    methods: {
      ...mapActions(['user']),
      ...mapMutations(['user']),
    },
};
</script>
  1. 使用setup
<template>
    <a-table
      :columns="columns"
      :data-source="userFetchList.list"
      :loading="loading['user/fetchList']"
      :pagination="false"
    />
</template>

<script lang="js">
import { useState, useActions, cleanMixin } from '@ctsj/vuexgenerator'
import { onMounted } from 'vue'

export default {
  mixins: [cleanMixin(['user'])],
  setup () {
    const state = useState(['user'])

    const actions = useActions(['user'])

    onMounted(() => {
      actions.userFetchListAction().then((res) => {
        console.log('userFetchListAction success', res, state)
      }) 
    })
    
    return {
      columns: [
        {
          dataIndex: 'name',
          key: 'name'
        },
        {
          title: 'Age',
          dataIndex: 'age',
          key: 'age'
        },
        {
          title: 'Address',
          dataIndex: 'address',
          key: 'address'
        },
        {
          title: 'Tags',
          key: 'tags',
          dataIndex: 'tags'
        },
        {
          title: 'Action',
          key: 'action'
        }
      ],
      ...state
    }
  }
}
</script>
  1. 注册 Service(在一个单独的文件中 VuexGeneratorPlugin.js)
import VuexGenerator from '@ctsj/vuexgenerator';

import UserModel from '../modules/user';
import PersonModel from '../modules/person';

function serviceRegister() {
  const requireComponent = require.context('../../service', false, /.*\.(js)$/);

  const services = {};
  requireComponent.keys().forEach((fileName) => {
    const serviceKey = fileName.substring(2, fileName.length - 3);
    services[serviceKey] = requireComponent(fileName);
  });

  return services;
}

// &#x521B;&#x5EFA;VuexGeneratorPlugin&#x63D2;&#x4EF6;
export default VuexGenerator(serviceRegister(), {
  user: UserModel,
  person: PersonModel,
});
  1. 在 main.js 中进行引用插件
import { createApp } from 'vue'
import Antd from 'ant-design-vue'

import store from './store'
import router from './router'
import App from './App.vue'

import './registerServiceWorker'

import 'ant-design-vue/dist/antd.css'

createApp(App).use(store).use(router).use(Antd).mount('#app')

API

  • 工厂方法 - 创建 vuex 的插件(传入 ServiceConfig 和 Modules 的定义)

  • mapState - state 的辅助函数

  • mapActions - action 的辅助函数

  • mapMutations - Mutations 的辅助函数

  • useState - 在setup中获取数据的辅助函数

  • useMutations - 在setup中更新state的辅助函数

  • useActions - 在setup中进行异步更新state的辅助函数

  • cleanMixin - 用户自动重置 vuex 数据的 mixin

其他

demo 目录下附带了一个 demo