“vue“: “^3.0.0“使用 “vuex“: “^4.1.0“

本文详细介绍了如何在Vue项目中使用Vuex进行状态管理,包括安装Vuex、创建store、挂载store、组件中使用state的各种方法($store.state、计算属性、mapState)、mutations的创建与使用、actions的处理以及getters的定义与调用。同时,文章还探讨了Vuex的模块化使用,展示了如何在多个module中管理和使用state、mutations、actions和getters。

1.安装

// 安装vuex
npm install vuex --save

2.创建store

import { createStore } from 'vuex'
const store = createStore({
    state:{
        counter:100,
        name:'zql',
        age: 45,
        height:180,
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:60}
        ]
    },
    mutations: { // 方法 修改state唯一途径 同步操作
        increment(state) { // 默认就有个state参数,不用通过this.state
            state.counter++
        },
        decrement(state) {
            state.counter--
        }
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
 
    },
    getters: {
 
    },
    modules: {
 
    }
})

export default store

3.挂载使用store --> main.js

import { createApp } from 'vue'
import App from './App.vue'
import store from './store'

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

4.组件中使用store中的数据

第一种方法($store.state.xx和this.$store.commit('xx')):

<template>
    <div class="dome">
       <span>{{$store.state.counter}}</span>
       <button @click="increment">加1</button>
       <button  @click="decrement">减1</button>
    </div>
</template>

<script>
export default {
    data() {
    },
    created(){
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>

第二种方法 options API(3种)中 computed 和 映射mapState(1.数组写法,2.对象写法)

<template>
    <div class="dome">
       <span>{{sCounter}}</span>
       <button @click="increment">加1</button>
       <button  @click="decrement">减1</button>
        // <div>{{ sName }}</div>
        // <div>{{ sAge }}</div>
       <div>{{ name }}</div>
       <div>{{ age }}</div>
       <div>{{ height }}</div>
    </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
    data() {
    },
    created(){
    },
    computed:{
       //第一种写法
        sCounter(){
            return this.$store.state.counter
        },

       //第二种写法
        ...mapState(['name','age','height'])//数组写法

       //第三种写法
       // ...mapState({ //对象写法
       //    sName: state => state.name,
       //    sAge: state => state.age
       // })
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>

第三种方法composition api (2种) setup()与mapState,computed

<template>
    <div class="dome">
       <span>{{sCounter}}</span>
       <button @click="increment">加1</button>
       <button @click="decrement">减1</button>
       {{ name }}
       {{ age }}
       {{ height }}
    </div>
</template>

<script>
import { mapState, useStore } from 'vuex'
import { computed } from 'vue'
export default {
    setup(){
        const store = useStore()
        // 第一种写法
        const sCounter = computed(()=> store.state.counter)

        // 第二种写法
        const storeStateFns = mapState(['name','age','height'])
        //{name:function,age:function,height:function}
        //{name:ref,age:ref,height:ref}
        const storeState ={}
        Object.keys(storeStateFns).forEach(fnkey =>{
            const fn = storeStateFns[fnkey].bind({$store:store});
            storeState[fnkey] = computed(fn)
        }) 
        return {
            sCounter,
            ...storeState
        }
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>
封装mapState与computed混用
import { mapState, useStore } from 'vuex'
import { computed } from 'vue'
function useState(item){
    // 拿到store对象
    const store = useStore()

    // 获取到对应的对象:{name:function,age:function,height:function}
    const storeStateFns = mapState(item)

    //对数据转化{name:ref,age:ref,height:ref}
    const storeState ={}
    Object.keys(storeStateFns).forEach(fnkey =>{
        const fn = storeStateFns[fnkey].bind({$store:store});
        storeState[fnkey] = computed(fn)
    })
    return storeState
}
export default useState

页面使用(数组,对象两种)

<template>
    <div class="dome">
       <span>{{counter}}</span>
       <button @click="increment">加1</button>
       <button @click="decrement">减1</button>
       {{ name }}
       {{ age }}
       {{ height }}
        {{ sCounter }}
        {{ sName }}
    </div>
</template>

<script>
import useState from './hook/useState'
export default {
    setup(){
        const storeState = useState(['counter','name','age','height'])//数组
        const storeState2 = useState({//对象
            sCounter: state=> state.counter,
            sName: state=> state.name,
        })
        return {
            ...storeState,
            ...storeState2
        }
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>

5.getters的创建以及使用

第一种基本使用

gatters ==》store

import { createStore } from 'vuex'
const store = createStore({
    state:{
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:60}
        ]
    },
    mutations: { // 方法 修改state唯一途径 同步操作
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
 
    },
    getters: {
        bookPrice(state){
            let bookPrice= 0
            for(const item of state.book){
                bookPrice += item.price * item.count
            }
            return bookPrice
        }
 
    },
    modules: {
    }
})

export default store

页面展示

<template>
    <div class="dome">
        书本总数{{$store.getters.bookPrice}}
    </div>
</template>
<script>
export default {
    setup(){
    },
    methods:{
    }
}
</script>

第二种使用其他getters

import { createStore } from 'vuex'
const store = createStore({
    state:{
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:60}
        ],
        discount:0.6
    },
    mutations: { // 方法 修改state唯一途径 同步操作

    },
    actions: { // 如果有异步操作在这里写 比如网络请求
 
    },
    getters: {
        bookPrice(state, getters){
            let bookPrice= 0
            for(const item of state.book){
                bookPrice += item.price * item.count
            }
            return bookPrice * getters.bookDiscount
        },
        bookDiscount(state){
            return state.discount * 0.9
        }
    },
    modules: {
 
    }
})

export default store

<template>
    <div class="dome">
        书本总数{{$store.getters.bookPrice}}
    </div>
</template>
<script>
export default {
    setup(){
    },
    methods:{
    }
}
</script>

第三种返回函数

import { createStore } from 'vuex'
const store = createStore({
    state:{
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:1}
        ],
        discount:0.6
    },
    mutations: { // 方法 修改state唯一途径 同步操作
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
    },
    getters: {
        bookPrice(state, getters){
            let bookPrice= 0
            for(const item of state.book){
                bookPrice += item.price * item.count
            }
            return bookPrice * getters.bookDiscount
        },
        bookDiscount(state){
            return state.discount * 0.9
        },
        bookDiscountN(state, getters){
            return  function(N){
                let bookPrice= 0
                for(const item of state.book){
                    if(item.count > N){
                        bookPrice += item.price * item.count
                    }
                }
                return bookPrice * getters.bookDiscount
            }
        }
    },
    modules: {
 
    }
})

export default store

<template>
    <div class="dome">
        书本总数{{$store.getters.bookPrice}}
        筛选{{ $store.getters.bookDiscountN(6) }}
    </div>
</template>
<script>
export default {
    setup(){
    },
    methods:{
    }
}
</script>

第四种 options API(3种)中 computed 和 映射mapGetters(1.数组写法,2.对象写法)

import { createStore } from 'vuex'
const store = createStore({
    state:{
        counter:100,
        name:'zql',
        age: 45,
        height:180,
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:1}
        ],
        discount:0.6
    },
    mutations: { // 方法 修改state唯一途径 同步操作
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
    },
    getters: {
        nameInfo(state){
            return `name:${state.name}`
        },
        ageInfo(state){
            return `age:${state.age}`
        },
        heightInfo(state){
            return `height:${state.height}`
        },
        counterInfo(state){
            return `counter:${state.counter}`
        },
    },
    modules: {
 
    }
})

export default store

<template>
    <div class="dome">
        {{  $store.getters.nameInfo }}
        {{  ageInfo }}
        {{ heightInfo }}
        {{ counterInfo }}
    </div>
</template>

<script>
import { mapGetters } from 'vuex';
export default {
    computed:{
        // 第一种
        ageInfo(){
            return this.$store.getters.ageInfo
        },
        // 第二种数组
        ...mapGetters(['heightInfo']),
        // 第三种对象
        ...mapGetters({
            counterInfo:'counterInfo'
        })

    },
    setup(){

    },
    methods:{

    }
}
</script>

<style scoped>
</style>

第五种方法composition api (2种) setup()与mapGetters,computed

页面展示

<template>
    <div class="dome">
        {{  nameInfo }}
        {{  ageInfo }}
        {{  heightInfo }}
        {{  counterInfo }}

    </div>
</template>

<script>
import {computed} from 'vue'
import { useStore } from 'vuex'
import { mapGetters } from 'vuex';
import useMapper from './hook/useMapper'
export default {

    setup(){
        const store = useStore()
        const nameInfo = computed(()=>store.getters.nameInfo)//第一种

        const storeGettersFns = useMapper(['ageInfo','heightInfo','counterInfo'],mapGetters)//第二种函数封装
        return {
            nameInfo,
            ...storeGettersFns
        }
    },
    methods:{

    }
}
</script>

<style scoped>
</style>

封装

import { useStore } from 'vuex'
import { computed } from 'vue'
function useMapper(item,mapFn){
    // 拿到store对象
    const store = useStore()

    // 获取到对应的对象:{name:function,age:function,height:function}
    const storeStateFns = mapFn(item)

    //对数据转化{name:ref,age:ref,height:ref}
    const storeState ={}
    Object.keys(storeStateFns).forEach(fnkey =>{
        const fn = storeStateFns[fnkey].bind({$store:store});
        storeState[fnkey] = computed(fn)
    })
    return storeState
}
export default useMapper

6.mutations的创建以及使用

mutations必须是同步函数,devtool会记录mutation的状态。

第一种基础写法(三种)

import { createStore } from 'vuex'
const store = createStore({
    state:{
        counter:100,
    },
    mutations: { // 方法 修改state唯一途径 同步操作
        increment(state) { // 默认就有个state参数,不用通过this.state
            state.counter++
        },
        decrement(state) {
            state.counter--
        },
        incrementN(state,payload) { // 默认就有个state参数,不用通过this.state
            state.counter += payload.n
        },
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
    },
    getters: {
    },
    modules: {
    }
})

export default store

展示

<template>
    <div class="dome">
        {{  $store.state.counter }}

        <button @click="$store.commit('increment')">加1</button>
        //第一种

        <button @click="$store.commit('decrement')">减1</button>
        <button @click="addincrementN">加10</button>
    </div>
</template>

<script>
export default {
    methods:{
        addincrementN(){
            //第二种
            //this.$store.commit('incrementN',{n:10,name:'你好'})

            //第三种
            this.$store.commit({
                type:'incrementN',
                n:10,
                name:'你好'
            })
        }
    }
}
</script>
<style scoped>
</style>

第二种 options API辅助函数mapMutations

vuex使用上方

页面展示

<template>
    <div class="dome">

        {{  $store.state.counter }}
        <button @click="increment">加1</button>
        <button @click="decrement">减1</button>
        <button @click="incrementN({n:10})">加10</button>
    </div>
</template>

<script>
import { mapMutations } from 'vuex';
export default {
    methods:{
        //第一种数组
        ...mapMutations(['increment','decrement','incrementN'])

        //第二种对象
        //...mapMutations({
        //     add:'increment'
        // })
    }
}
</script>

<style scoped>
</style>

第三种方法composition api (1种) setup()与mapMutations

vuex使用上上方

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="increment">加1</button>
        <button @click="decrement">减1</button>
        <button @click="incrementN({n:10})">加10</button>
    </div>
</template>

<script>
import { mapMutations } from 'vuex';
export default {

    setup(){
        const mutation = mapMutations(['increment','decrement','incrementN'])
        return {
            ...mutation
        }
    },
    methods:{
    }
}
</script>

<style scoped>
</style>

7.actions的使用

Action类似与mutation不用在于:

1.Action提交的是mutation,而不是直接修改状态,

2.Action可以包含任意异步操作。

Action还有一个context参数。context是一个和store实例均有相同方法和属性的context对象;

所以可以从其中获取到commit方法来提交一个mutation,或者通过context.state和context.getters来获取state和getters;

第一种基础写法(三种)

import { createStore } from 'vuex'
import axios from 'axios'

const store = createStore({
    state:{
        counter:100,
        banner:null
    },
    mutations: { // 方法 修改state唯一途径 同步操作
        increment(state) { // 默认就有个state参数,不用通过this.state
            state.counter++
        },
        decrement(state) {
            state.counter--
        },
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
        incrementAction(context,number) {
            console.log('number',number)
            setTimeout(()=>{
                context.commit('increment')
            },1000)
        },
        decrementAction(context) {
            context.commit('decrement')
        },
        addBannerList(context){
            axios.get('http://123.207.32.32:8000/home/multidata').then((res)=>{
                // console.log(res.data.data.banner.list)
                context.commit('addBanner',res.data.data.banner.list)
            })
        }
    },
    getters: {
    },
    modules: {
    }
})

export default store

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="add">加1</button>
        <button @click="decrement">减1</button>
    </div>
</template>

<script>
export default {

    mounted(){
        this.$store.dispatch('addBannerList')//第一种
    },
    methods:{
        add(){
            this.$store.dispatch('incrementAction',{count:'ll'})//第二种
        },
        decrement(){
            this.$store.dispatch({//第三种
                type:'decrementAction'
            })
        }
    }
}
</script>

<style scoped>
</style>

第二种 options API辅助函数mapActions

vuex上方雷同

页面展示

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="incrementAction">加1</button>
        <button @click="decrementAction">减1</button>
    </div>
</template>

<script>
import { mapActions } from 'vuex';
export default {

    methods:{
       ...mapActions(['incrementAction','decrementAction']),//数组
       ...mapActions({ //对象
        add:'incrementAction',
        dec:'decrementAction'
       })
    }
}
</script>
<style scoped>
</style>

第三种方法composition api (2种) setup()与mapActions

vuex上上方雷同

页面展示

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="incrementAction">加1</button>
        <button @click="decrementAction">减1</button>
    </div>
</template>

<script>
import { mapActions } from 'vuex';
export default {

    setup(){
      const action = mapActions(['incrementAction','decrementAction'])//数组
      const action2 = mapActions({//对象
            add:'incrementAction',
            dec:'decrementAction'
        })
      return{
        ...action,
        ...action2
      }
    },
}
</script>

<style scoped>
</style>

第四种 高级操作 知道action什么时候结束?通过Promise

import { createStore } from 'vuex'
import axios from 'axios'

const store = createStore({
    state:{
        banner:null
    },
    mutations: { 
        addBanner(state,payload) {
            state.banner = payload
        },
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
        addBannerList(context){
            return new Promise((resove,rejack)=>{
                axios.get('http://123.207.32.32:8000/home/multidata').then((res)=>{
                    context.commit('addBanner',res.data.data.banner.list)
                    resove('成功')
                }).catch((err)=>{
                    rejack(err)
                })
            })
            
        }
    },
})
export default store

<template>
    <div class="dome">
    </div>
</template>

<script>
import { onMounted } from 'vue';
import {useStore} from'vuex'
export default {
    setup(){
        const store = useStore()
        onMounted(()=>{
            const actionPromise = store.dispatch('addBannerList')
            actionPromise.then((res)=>{
                console.log(res)
            }).catch((err)=>{
                console.log(err)
            })
        })
      return{
      }
    }
}
</script>

<style scoped>
</style>

8.moudle使用

基本使用

// homeModule.js
export default {
    namespaced: true,
    state() {
        return {
            title: "home"
        }
    },
}

// mineModuele.js
export default {
    namespaced: true,
    state() {
        return {
            title: "mine"
        }
    },
}

// rootModule.js
import { createStore } from 'vuex'
import home from './homeModule'
import mine  from './mineModule'

const store = createStore({
    state() {
        return {
            counter: 10,
            title: 'root'
        }
    },
    mutations: {
    },
    getters: {
    },
    actions: {
    },
    modules: {
        home,
        mine
    }
});

export default store;

// state数据的获取
<div>模板中获取值:{{$store.state.title}}</div>
<div>模板中获取值:{{$store.state.home.title}}</div>
<div>模板中获取值:{{$store.state.mine.title}}</div>
<div>模板中获取值:{{homeTitle}}</div>

computed: {
    homeTitle() {
        return this.$store.state.mine.title;
    }
}
        

多个module中使用getter和actions

homeModule.js
export default {
    namespaced: true,//命名空间,打开
    state() {
        return {
            title: "home"
        }
    },
    mutations: {
        changeTitle(state) {
            console.log(state);
        }
    },
    getters: {
        // getterTitle(state, getters, rootState, rootGetters)
        getterTitle(state) {
            return state.title + " getter"
        },
    },
    actions: {
        // context = {commit, dispatch, state, rootState, getters, rootGetters}
        changeTitleAction(context) {
            context.commit('changeTitle');
            // 派发root module中的mutations
            context.commit('changeTitle', null, {root: true});
        }
    }
}

// 模板
<button @click="changeTitle">changeTitle</button>
<div>{{$store.getters["home/getterTitle"]}}</div>

methods: {
    changeTitle() {
        this.$store.dispatch('home/changeTitleAction');
    }
}

在options API辅助函数中使用

<div>模板中获取值 - mapTitle:{{mapTitle}}</div>
<div>模板中获取值 - mapTitleHome: {{mapTitleHome}}</div>
<button @click="changeTitleAction">map changeTitle</button>
<button @click="homeObject">map homeObject</button>

import { mapState, mapActions,mapGetters,mapMutation } from "vuex";
export default {
    setup() {
        return {
        }
    },
    methods: {
        //写法一
        ...mapActions('home', ['changeTitleAction']),

        //写法二
        ...mapActions('home', {
            homeObject: 'changeTitleAction'
        })


        //写法一
        ...mapMutation("home", [incremet]),
        
         //写法二
        ...mapMutation('home',{
            incremet:"incremet"
        })
        },
    computed: {
        homeTitle() {
            return this.$store.state.mine.title;
        },
        //写法一
        ...mapState("home", [title]),
        //写法二
        ...mapState("home", {
            mapTitleHome: state => state.title
        }),
         //写法三
        ...mapState({
            mapTitle: state => state.home.title
        }),

        //写法一
        ...mapGetters("home", [doubleHimeCounter]),
        //写法二
        ...mapGetters('home',{
            doubleHimeCounter:"doubleHimeCounter"
        })

    }
}

利用options API createNamespacedHelpers导出使用

import { createNamespacedHelpers  } from "vuex";
const {mapState, mapActions,mapGetters,mapMutation} = createNamespacedHelpers("home");
export default {
    setup() {
        return {
        }
    },
    methods: {
        ...mapMutation([incremet]),

        ...mapActions(['changeTitleAction']),
        ...mapActions({
            homeObject: 'changeTitleAction'
        })
    },
    computed: {

        ...mapState([title]),

        ...mapState({
            mapTitle: state => state.title
        }),

         ...mapGetters([doubleHimeCounter]),
    }
}

composition api 封装

文件关系

index.js

import { useGetters } from './useGetters';
import { useState } from './useState';

export {
  useGetters,
  useState
}

useGetter.js

import { mapGetters, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'

export function useGetters(moduleName, mapper) {
  let mapperFn = mapGetters
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapGetters
  } else {
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}

useState.js

import { mapState, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'

export function useState(moduleName, mapper) {
  let mapperFn = mapState
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapState
  } else {
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}

useMapper.js

import { computed } from 'vue'
import { useStore } from 'vuex'

export function useMapper(mapper, mapFn) {
  // 拿到store独享
  const store = useStore()

  // 获取到对应的对象的functions: {name: function, age: function}
  const storeStateFns = mapFn(mapper)

  // 对数据进行转换
  const storeState = {}
  Object.keys(storeStateFns).forEach(fnKey => {
    const fn = storeStateFns[fnKey].bind({$store: store})
    storeState[fnKey] = computed(fn)
  })

  return storeState
}

页面使用

<template>
  <div>
    <hr>
    <h2>{{ homeCounter }}</h2>
    <h2>{{ doubleHomeCounter }}</h2>
    <!-- <h2>{{ doubleRootCounter }}</h2> -->
    <button @click="increment">home+1</button>
    <button @click="incrementAction">home+1</button>
    <hr>
  </div>
</template>

<script>
  import { createNamespacedHelpers, mapState, mapGetters, mapMutations, mapActions } from "vuex";

  import { useState, useGetters } from '../hooks/index'

  export default {

    setup() {
      // {homeCounter: function}
      const state = useState("home",["rootCounter"])

     const getters = useGetters("home", ["doubleHomeCounter"])

      // const mutations = mapMutations(["increment"])
      // const actions = mapActions(["incrementAction"])

      return {
        // ...state,
        // ...getters,
        // ...mutations,
        // ...actions
      }
    }
  }
</script>

<style scoped>

</style>
我需要查询的远程的数据库,以下是我目前的依赖,有没有合理的方案,并且告诉我还需要下载什么依赖{ "name": "yueji", "version": "3.0.0", "private": true, "scripts": { "dev": "vue-cli-service serve", "start": "vue-cli-service serve", "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "postinstall": "patch-package" }, "dependencies": { "@element-plus/icons-vue": "^2.3.1", "@inotom/vue-curve-text": "^3.0.0", "@planetscale/database": "^1.19.0", "animate.css": "^3.5.1", "axios": "^0.24.0", "buffer": "^6.0.3", "core-js": "^3.6.5", "crypto-browserify": "^3.12.1", "crypto-js": "^4.1.1", "css-color-function": "^1.3.3", "dayjs": "^1.10.6", "echarts": "^5.6.0", "element-plus": "^2.7.2", "file-saver": "^2.0.5", "highlight.js": "^11.6.0", "ip-regex": "^5.0.0", "jquery": "^3.7.1", "js-cookie": "^3.0.5", "markdown-it-abbr": "^2.0.0", "markdown-it-anchor": "^9.2.0", "markdown-it-footnote": "^4.0.0", "markdown-it-highlightjs": "^4.2.0", "markdown-it-sub": "^2.0.0", "markdown-it-sup": "^2.0.0", "markdown-it-task-lists": "^2.1.1", "markdown-it-toc-done-right": "^4.2.0", "marked": "^4.0.13", "md-editor-v3": "^5.5.0", "md5": "^2.3.0", "mysql": "^2.18.1", "mysql2": "^3.14.1", "nprogress": "^0.2.0", "pinyin-pro": "^3.26.0", "qs": "^6.11.2", "recorder-core": "^1.3.25011100", "rgb-hex": "^4.0.0", "screenfull": "^5.1.0", "stream-browserify": "^3.0.0", "url-regex": "^5.0.0", "use-element-plus-theme": "^0.0.5", "v-viewer": "^3.0.13", "vis-network": "^7.5.0", "vue": "^3.4.27", "vue-clipboard3": "^2.0.0", "vue-router": "4.3.2", "vue3-menus": "^1.1.2", "vue3-seamless-scroll": "^2.0.1", "vuex": "^4.1.0" }, "devDependencies": { "@babel/core": "^7.21.8", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", "@babel/plugin-proposal-optional-chaining": "^7.21.0", "@babel/preset-env": "^7.21.5", "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-vuex": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/compiler-sfc": "^3.0.0", "@vue/eslint-config-standard": "^5.1.2", "babel-eslint": "^10.1.0", "babel-loader": "^8.2.5", "compression-webpack-plugin": "^6.1.2", "eslint": "^6.7.2", "eslint-plugin-import": "^2.20.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.0", "eslint-plugin-vue": "^7.0.0", "hard-source-webpack-plugin": "^0.13.1", "linkify-it": "^4.0.1", "markdown-it": "^14.1.0", "patch-package": "^6.4.7", "sass": "^1.87.0", "sass-loader": "^8.0.2", "svg-sprite-loader": "^6.0.11" } }
05-30
{ "name": "admin", "version": "1.2.8", "description": "eapAdmin", "author": "shan", "email": "595485548@qq.com", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "unit": "jest --config test/unit/jest.conf.js --coverage", "e2e": "node test/e2e/runner.js", "test": "npm run unit && npm run e2e", "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs", "build": "node build/build.js", "analyz": "cross-env NODE_ENV=production npm_config_report=true npm run build", "startdll": "webpack --config build/webpack.dll.config.js" }, "dependencies": { "@jiaminghi/data-view": "^2.10.0", "ant-design-vue": "^1.7.2", "axios": "^0.19.2", "crypto-js": "^4.1.1", "dayjs": "^1.11.3", "echarts": "^4.1.0", "element-resize-detector": "^1.2.4", "element-ui": "^2.13.1", "file-save": "^0.2.0", "file-saver": "^2.0.5", "font-awesome": "^4.7.0", "js-cookie": "^2.2.0", "js-md5": "^0.7.3", "jsencrypt": "^3.3.2", "module": "^1.2.5", "moment": "^2.29.4", "nprogress": "^0.2.0", "pinyin": "^2.10.2", "screenfull": "^3.3.3", "scriptjs": "^2.5.8", "shortid": "^2.2.15", "sortablejs": "^1.7.0", "vue": "^2.5.2", "vue-i18n": "^8.4.0", "vue-quill-editor": "^3.0.6", "vue-router": "^3.0.1", "vue-svgicon": "^3.2.9", "vuex": "^3.0.1", "wangeditor": "^3.1.1", "xlsx": "^0.17.0" }, "devDependencies": { "ajv": "^5.5.2", "autoprefixer": "^7.1.2", "babel-core": "^6.22.1", "babel-eslint": "^8.2.1", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-jest": "^21.0.2", "babel-loader": "^7.1.1", "babel-plugin-dynamic-import-node": "^1.2.0", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", "babel-plugin-transform-runtime": "^6.22.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "babel-register": "^6.22.0", "browserslist": "^4.25.1", "cache-loader": "^4.1.0", "chalk": "^2.0.1", "chromedriver": "^2.27.2", "compression-webpack-plugin": "^3.1.0", "copy-webpack-plugin": "^4.0.1", "cross-env": "^6.0.3", "cross-spawn": "^5.0.1", "css-loader": "^3.5.2", "eslint": "^7.32.0", "eslint-config-standard": "^10.2.1", "eslint-friendly-formatter": "^3.0.0", "eslint-loader": "^4.0.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.4.0", "eslint-plugin-standard": "^3.0.1", "eslint-plugin-vue": "^4.0.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^3.0.1", "friendly-errors-webpack-plugin": "^1.6.1", "gulp": "^3.9.1", "hard-source-webpack-plugin": "^0.13.1", "html-webpack-plugin": "^4.2.0", "jest": "^22.0.4", "jest-serializer-vue": "^0.3.0", "less": "^3.10.3", "less-loader": "^5.0.0", "mini-css-extract-plugin": "^0.9.0", "nightwatch": "^0.9.12", "node-notifier": "^5.1.2", "optimize-css-assets-webpack-plugin": "^3.2.0", "ora": "^1.2.0", "portfinder": "^1.0.13", "postcss-import": "^12.0.1", "postcss-loader": "^3.0.0", "postcss-url": "^7.2.1", "rimraf": "^2.6.0", "sass-loader": "^7.1.0", "script-loader": "^0.7.2", "selenium-server": "^3.0.1", "semver": "^5.3.0", "shelljs": "^0.7.6", "style-loader": "^1.1.4", "svg-sprite-loader": "^6.0.11", "thread-loader": "^2.1.3", "uglifyjs-webpack-plugin": "^2.2.0", "url-loader": "^4.1.0", "vue-jest": "^1.0.2", "vue-loader": "^15.9.1", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^4.47.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.10.3", "webpack-merge": "^4.1.0" }, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] } 这是我的package.json
07-11
{ "name": "frappe-framework", "scripts": { "build": "node esbuild", "production": "node esbuild --production", "watch": "node esbuild --watch", "coverage:report": "npx nyc report --reporter=clover" }, "repository": { "type": "git", "url": "git+https://github.com/frappe/frappe.git" }, "author": "Frappe Technologies Pvt. Ltd.", "license": "MIT", "bugs": { "url": "https://github.com/frappe/frappe/issues" }, "engines": { "node": ">=18" }, "homepage": "https://frappeframework.com", "dependencies": { "@editorjs/editorjs": "^2.28.2", "@frappe/esbuild-plugin-postcss2": "^0.1.3", "@fullcalendar/core": "^6.1.11", "@fullcalendar/daygrid": "^6.1.11", "@fullcalendar/interaction": "^6.1.11", "@fullcalendar/list": "^6.1.11", "@fullcalendar/timegrid": "^6.1.11", "@headlessui/vue": "^1.7.16", "@popperjs/core": "^2.11.2", "@redis/client": "^1.5.8", "@sentry/browser": "^7.119.1", "@vue-flow/background": "^1.1.0", "@vue-flow/core": "^1.16.2", "@vue/component-compiler": "^4.2.4", "@vueuse/core": "^9.5.0", "ace-builds": "^1.4.8", "air-datepicker": "file:/mnt/e/air-datepicker", "autoprefixer": "10", "awesomplete": "^1.1.5", "bootstrap": "4.6.2", "chalk": "^2.3.2", "cliui": "^7.0.4", "cookie": "^0.7.0", "cropperjs": "^1.5.12", "cssnano": "^5.0.0", "driver.js": "^0.9.8", "editorjs-undo": "0.1.6", "esbuild": "^0.17.0", "esbuild-plugin-vue3": "^0.5.0", "fast-deep-equal": "^2.0.1", "fast-glob": "^3.2.5", "frappe-charts": "2.0.0-rc27", "frappe-datatable": "1.19.0", "frappe-gantt": "^0.6.0", "frappe-quill-image-resize": "^3.0.9", "highlight.js": "^10.4.1", "html5-qrcode": "^2.3.8", "jquery": "3.7.0", "js-sha256": "^0.9.0", "jsbarcode": "^3.11.0", "launch-editor": "^2.2.1", "localforage": "^1.10.0", "md5": "^2.3.0", "moment": "^2.29.4", "moment-timezone": "^0.5.35", "photoswipe": "^5.4.3", "pinia": "^2.0.23", "plyr": "^3.7.8", "popper.js": "^1.16.0", "postcss": "8", "quill": "2.0.3", "quill-magic-url": "^3.0.0", "qz-tray": "^2.0.8", "rtlcss": "^4.0.0", "sass": "^1.63.0", "showdown": "^2.1.0", "socket.io": "^4.7.1", "socket.io-client": "^4.7.1", "sortablejs": "^1.15.0", "touch": "^3.1.0", "vue": "^3.3.0", "vue-router": "^4.1.5", "vuedraggable": "^4.1.0", "vuex": "4.0.2", "yargs": "^17.5.1" }, "nyc": { "report-dir": ".cypress-coverage" }, "optionalDependencies": { "bufferutil": "^4.0.8", "utf-8-validate": "^6.0.3" } } 这个package.json 那些版本不兼容
最新发布
09-30
{ "name": "meadia-manage", "version": "1.0.0", "description": "A Vue.js project", "author": "winspread", "private": true, "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "build": "node build/build.js" }, "dependencies": { "axios": "^0.18.0", "echarts": "^4.2.1", "element-ui": "^2.15.10", "moment": "^2.29.4", "vue": "^2.5.2", "vue-puzzle-vcode": "^1.1.9", "vue-router": "^3.0.2", "vuex": "^3.1.0" }, "devDependencies": { "autoprefixer": "^7.1.2", "axios-mock-adapter": "^1.16.0", "babel-core": "^6.22.1", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-loader": "^7.1.1", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-runtime": "^6.22.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "chalk": "^2.0.1", "copy-webpack-plugin": "^4.0.1", "css-loader": "^0.28.0", "element-theme-chalk": "^2.15.10", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^1.1.4", "friendly-errors-webpack-plugin": "^1.6.1", "html-webpack-plugin": "^2.30.1", "mockjs": "^1.0.1-beta3", "node-notifier": "^5.1.2", "node-sass": "^6.0.1", "optimize-css-assets-webpack-plugin": "^3.2.0", "ora": "^1.2.0", "portfinder": "^1.0.13", "postcss-import": "^11.0.0", "postcss-loader": "^2.0.8", "postcss-url": "^7.2.1", "rimraf": "^2.6.0", "sass-loader": "^10.2.0", "semver": "^5.3.0", "shelljs": "^0.7.6", "uglifyjs-webpack-plugin": "^1.1.1", "url-loader": "^0.5.8", "vue-loader": "^13.3.0", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0" }, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }
04-01
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值