Vuex使用和v-model语法详细教程

20 篇文章 1 订阅

Vuex基础–介绍


为什么会有vuex?

https://vuex.vuejs.org/zh/

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化

Vuex是采用集中式管理组件依赖的共享数据的一个工具,可以解决不同组件数据共享问题
在这里插入图片描述
结论:

  • 修改state状态必须通过mutations
  • mutations只能执行同步代码,类似ajax,定时器之类的代码不能在mutations中执行
  • 执行异步代码,通过actions,然后将数据提交给mutations才可以完成
  • state的状态即共享数据可以在组件中引用
  • 组件中可以调用aciton

Vuex使用

下载

yarn add vuex@3.5.1

src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({})

export default store

main.js引入

import store from './store/index'
new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app')
Vuex–state

state 放置所有公共状态的属性,如果你有一个公共状态数据,你只需要定义在state对象中

定义state
// 初始化vuex对象
const store = new Vuex.Store({
  state: {
    // 管理数据
    count: 0,
  },
})

如何在组件中获取count?

原始形式–插值表达式

Good.vue

组件中可以使用this.$store 获取到vuex中的store对象实例,可通过state属性获取count

<div>state的数据{{ $store.state.count }}</div>

<script>
export default {
  created() {
    console.log(this.$store.state.count)
  },
}
</script>
辅助函数–mapState

mapState是辅助函数,帮助我们把store中的数据映射到组件的计算属性中,属于一种方便用法

List.vue

第一步:导入mapState

第二步:采用数组形式引入state属性

第三部:利用展开运算法将导出的状态映射给计算属性

<template>
  <div>
    list
    {{ count }}
  </div>
</template>

<script>
//导入mapState
import { mapState } from 'vuex'
export default {
//采用数组形式引入state属性
//利用展开运算法将导出的状态映射给计算属性
  computed: {
    ...mapState(['count']),
    // 类似于
    // count() {
    //   return this.$store.state.count
    // },
  },
}
</script>
vuex–mutations

state数据的修改只能通过mutatons,并且mutations必须是同步更新,目的是形成数据快照

数据快照:一次mutation的执行,立刻得到一种视图状态,因为是立刻,所以必须是同步

定义mutations
const store = new Vuex.Store({
  state: {
    // 管理数据
    count: 70,
  },
  // d定义mutations
  mutations: {
    
  }
})

mutations是一个对象,对象中存放修改state的方法

mutations: {
    // 方法里的参数 第一个参数是当前store的state属性
    // 第二个参数payload 运输参数  调用mutations的时候 可以传递参数
     addCount(state) {
      state.count += 1
    },
    addCountN(state, n) {
      state.count += n
    },
  },

如何在组件中调用mutations?

原始形式 $store

Good.vue

<template>
  <div>
    state的数据{{ $store.state.count }}
    <hr />
    <button @click="addCount">+1</button>
  </div>
</template>

<script>
export default {
  created() {
    console.log(this.$store.state.count)
  },
  methods: {
    addCount() {
      // 调用store中的mutations 提交给mutations
      // commit('mutations方法名',参数)
      this.$store.commit('addCount')
    },
  },
}
</script>

带参数的传递

<button @click="addCountN(9)">+n</button>

 methods: {
    addCountN(n) {
      this.$store.commit('addCountN', n)
    },
  },
辅助函数-mapMutations

mapMutations和mapState很像,把位于mutations中的方法提取出来,可以将它导入到methods中

<template>
  <div>
    list
    {{ count }}
    <button @click="addCount">+1</button>
    <button @click="addCountN(8)">+n</button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
export default {
  computed: {
    ...mapState(['count']),
    // 类似于
    // count() {
    //   return this.$store.state.count
    // },
  },
  methods: {
    // 把位于mutations中的方法提取出来,可以将它导入到methods中
    ...mapMutations(['addCount', 'addCountN']),
  },
}
</script>
vuex-actions

state是存放数据的,mutations是同步更新数据,actions是负责进行异步操作

定义actions
actions: {
    // 获取异步的数据 context 表示当前的store实例
    // 可以通过context.state 获取状态
    // 也可以通过context.commit 来提交mutations
    // 也可以context.dispatch调用其它的action
    getAsyncCount(context) {
      setTimeout(() => {
        // 1秒后,要去修改state
        context.commit('addCount')
      }, 1000)
    },
  },
原始调用–$store.dispatch
addAsyncCount() {
      this.$store.dispatch('getAsyncCount')
    },
传参函数
  • actions

    actions: {
        getAsyncCountN(context, n) {
          setTimeout(() => {
            // 1秒后,要去修改state
            context.commit('addCountN', n)
          }, 1000)
        },
      },
    
  • 调用

     <button @click="addAsyncCountN(6)">+nAsync</button>
     
     addAsyncCountN(m) {
          this.$store.dispatch('getAsyncCountN', m)
     },
    
辅助函数–mapActions

actions也有辅助函数,可以将action导入到组件中

<template>
  <div>
    list
    {{ count }}

    <button @click="getAsyncCount">+1Async</button>
    <button @click="getAsyncCountN(6)">+nAsync</button>
  </div>
</template>

<script>
import { mapState,  mapActions } from 'vuex'
export default {
  computed: {
    ...mapState(['count']),
    // 类似于
    // count() {
    //   return this.$store.state.count
    // },
  },
  methods: {
    ...mapActions(['getAsyncCount', 'getAsyncCountN']),
  },
}
</script>
vuex-getters

除了state之外,有时还需要从state中派生出一些状态这些状态是依赖state的,会用到getters

state中定义了list,是1~10的数组

 state: {
    list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
  },

组件中需要显示大于5的数据,正常的方式,是需要list在组件中进行再一步的处理,但是getters可以帮助我们实现它

定义getters
getters: {
    // getters函数第一个参数是state
    // 必须要有返回值
    filterList: (state) => state.list.fiter((item) => item > 5),
  },
原始方式–getters
<ul>
      <li v-for="(item, index) in $store.getters.filterList">
        {{ item }}
      </li>
    </ul>
辅助函数–mapGetters
<template>
  <div>
    list
    {{ count }}
    <ul>
      <li v-for="(item, index) in filterList" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters(['filterList']),
    
  }
}
</script>

vuex-Module
为什么会有模块化

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变得非常复杂的时候,store对象就会变得相当臃肿。

我们把所有的状态都放在state中,项目变得越来越大的时候,vuex会变得越来越难以维护------Vuex模块化

在这里插入图片描述

模块化简单应用
  • 定义两个模块 countModule 和 arrModule
  • countModule 管理状态count
  • arrModule 管理状态 arr
const store = new Vuex.Store({
  modules: {
    countModule: {
      state: {
        count: 0,
      },
    },
    arrModule: {
      state: {
        arr: [2, 4, 67, 23, 12, 34, 68, 76],
      },
    },
  },
})

Good.vue组件中,分别显示count 和arr

<div>count:{{ $store.state.countModule.count }}</div>
    <div>
      <ul>
        <li v-for="item in $store.state.arrModule.arr">
          {{ item }}
        </li>
      </ul>
    </div>

注意:获取子模块的状态,通过$store.state.模块名.属性名来获取

上面的获取有点麻烦,可以getters 来改变一下

//getters是根级别的getters
getters: {
    count: (state) => state.countModule.count,
    arr: (state) => state.arrModule.arr,
  },

组件中通过mapGetters获取数据

<template>
  <div>
    <div>count:{{ count }}</div>
    <ul>
      <li v-for="(item, index) in arr" :key="index">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters(['count', 'arr']),
  },
}
</script>
模块化中的命名空间

namespaced 命名空间

默认情况下,模块内部的action,mutation,getter 是注册在全局命名空间的,—这样使得多个模块对同一mutation或者action作出响应

在这里插入图片描述

我们想要保证内部模块的高封闭性,可以采用namespaced来进行设置

const store = new Vuex.Store({
  modules: {
    countModule: {
      namespaced: true,  //命名空间
      state: {
        count: 0,
      },
      action: {},
      mutations: {
        addCount (state) {
          // 这里的state表示的是countModule的state
          state.count++
        },
      },
      getters: {},
    }
})
调用

方法一: 直接调用-带上模块的属性名路径

this.$store.commit('countModule/addCount')

方法二:辅助函数–带上模块的属性名路径

    <button @click="add">+1</button>
  methods: {
    ...mapMutations(['countModule/addCount', 'arrModule/delArr']),
    add() {
      this['countModule/addCount']()
    }
  },

v-model语法糖

父子组件通信,单项的,很多时候需要双向通信

父组件使用 msg.sync=“aa”,子组件使用 $emit(“update:msg”,参数)

父组件

 <Good :msg.sync="test"></Good>

子组件

<template>
  <div>
    {{ msg }}
    <button @click="fn">更改msg</button>
  </div>
</template>

<script>
export default {
  props: {
    msg: {
      default: '',
    },
  },
  methods: {
    fn() {
      this.$emit('update:msg', 'world')
    },
  },
}
</script>
父组件传值传对象

子组件收到对象后可以随意改变对象的属性,但是不能改变对象本身

父组件使用:v-model
  • 第一种

vue2.x中,v-model语法糖的简写

<List  :msg="msg" @ccEvent="fn"/>

父组件App.vue

<template>
  <div>
    <List v-model="test"></List>
  </div>
</template>

<script>
import List from './views/List.vue'
export default {
  components: {
    List,
  },
  data() {
    return {
      test: 'hello',
    }
  },
}
</script>

子组件 List.vue

<template>
  <div>
    {{ '值为' + msg }}
    <button @click="fn">更改父组件的值</button>
  </div>
</template>

<script>
export default {
  // model  有2个属性,
  // prop属性将msg作为该组件被使用时,v-model能取到的值
  // event 就是自定义事件 是emit('ccEvent')的时候  参数的值就是父组件v-model收到的值
  model: {
    prop: 'msg',
    event: 'ccEvent',
  },
  props: {
    msg: '',
  },
  methods: {
    fn() {
      this.$emit('ccEvent', this.msg + 2)
    },
  },
}
</script>
  • 第二种

    <List  :value="msg" @input="fn"/>
    

    父组件 App.vue

     <List v-model="test"></List>
    

    子组件 List.vue

    <template>
      <div>
        {{ '值为' + value }}
        <button @click="fn">更改父组件的值</button>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        value: {
          //必须使用value
          default: '',
        },
      },
      methods: {
        fn() {
          // 这里必须是input发送数据,
          // 发送数据会被父级v-model="test" 接收到,
          // 再被value=test传回来
          this.$emit('input', this.value + 2)
        },
      },
    }
    </script>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值