全家桶:vuex从使用到实现(超简单面霸必备知识点)
Posted 前端呆头鹅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全家桶:vuex从使用到实现(超简单面霸必备知识点)相关的知识,希望对你有一定的参考价值。
一 功能简介
vuex的定义是全局状态管理工具,通俗的说是一个管理全局变量的工具。
vue组件化的开发基础上,暴露了很多变量的通讯方式,如父向子传递使用props,子向父传递使用emit事件传参等。
尽管有这些方法,当项目达到规模后,有一些变量是希望在大量组件可用的,如登录状态,用户名,主题颜色等。
这种变量如果采用组件间传递的方式,会变得混乱繁琐。
这是我们希望有一个统一的机制,对数据进行存储和发放。这就是vuex的由来。
二 快速上手
我们先体验一下vuex,列出要实现的功能点。
npm install vuex@next
2.1 数据存储
首先我们使用vuex,将我们准备好的数据存储起来,这里使用vuex暴露的方法createStore。
import createStore from 'vuex'
const store = createStore(
state ()
return count: 666
,
mutations:
add (state) state.count++
)
export default store
我们的数据格式是安装store的要求准备的,是一个含有state和mutations属性的对象。
将该对象作为参数调用vuex暴露的方法createStore,可以返回一个store变量,导出store。
2.2 Use注册
在main.js中引入并注册store。
// vue3版示例
import createApp from 'vue'
import App from './App.vue'
import store from './store/index'
createApp(App)
.use(store)
.mount('#app')
2.3 数据使用
使用数据用到vuex暴露的方法useStore,这个方法可以返回一个对象,通过这个对象我们可以调用开始时传入的数据中的值和方法。
<script setup>
import useStore from 'vuex'
let store = useStore()
</script>
<template>
store.state.count
<button @click="store.commit('add')"></button>
</template>
三 实现解析
3.1 思路梳理
我们整理出需要暴露的两个方法。
createStore:用来存储数据,返回值可use;
useStore:用来暴露数据,返回值含有state,commit。
function createStore(options)
function useStore()
export createStore, useStore
数据存储后放在哪儿?store在use(注册)时做了什么?useStore又是从哪儿取得的数据?
搞明白这些,需要做一点知识补充。
如何实现在vue中自由的使用数据而不必在意其组件位置,官网上有一段话:
我们可以使用一对
provide
和inject
。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个provide
选项来提供数据,子组件有一个inject
选项来开始使用这些数据。
3.2 实现:state
整理脉络可得,实现vuex分为三步:
数据存储:在createStore中对输入数据整理后返回,返回的对象包含注册函数install和所有要用的数据。
use注册:在install中,我们使用provide()对数据全局注册到app实例上。
数据使用:在useStore中,使用inject对数据进行读取,返回读取后的对象。
import inject from "vue"
// 数据存储
function createStore(options)
return new Store(options)
// 数据使用
function useStore()
return inject('__store__')
class Store
constructor(options)
this._state = options.state
this._mutation = options.mutations
// use注册
install(app)
app.provide('__store__', this)
export createStore, useStore
这时基本功能已经可以使用了,我们可以试试。
存储数据:
import createStore from './gvuex'
const store = createStore(
state ()
return count: 123
,
mutations:
add (state: any)
state.count++
)
export default store
将这个导出的store注册。
数据使用:
<script setup>
import useStore from './store/gvuex'
let store = useStore()
</script>
<template>
store._state
</template>
可以看到store._state是一个对象,我们可以通过store._state.count访问数据。
3.3 实现:mutation
我们在修改数据的时,希望通过commit调用mutation,进行修改。
通过调用方式我们可知:commit是挂在Store上的一个函数,根据传入的参数调用对应的mutation。
store.commit('add')
向Store类中加入commit方法。
class Store
...
commit = (type: any) =>
this._mutation[type](this.state)
我们知道在commit中。
如果我们传入不正确的type值怎么处理?如果我们需要携带参数怎么处理?
在原来代码基础上更改如下,我们添加了type校验和参数传递。
class Store
...
commit = (type: any, payload: any) =>
const entry = this._mutation[type]
entry && entry(this.state, payload)
在页面中调用mutation事件。
<template>
store._state
<button @click="store.commit('add')"></button>
</template>
<script setup>
import useStore from '../store/gvuex'
let store = useStore()
</script>
但是点击按钮后,页面上的数据没有发生变化。
3.4 实现:数据响应
我们在commit中打印log。
class Store
...
commit = (type: any, payload: any) =>
const entry = this._mutation[type]
entry && entry(this.state, payload)
console.log(this.state)
点击按钮后发现,数据已经成功改变。
但是页面没有更新。
这是由于provide和
inject默认为非响应式操作,官网在provide和
inject一节出给出了响应式的解决方案。
Vue3:这是因为默认情况下,
provide/inject
绑定并不是响应式的。我们可以通过传递一个ref
property 或reactive
对象给provide
来改变这种行为。Vue2:
provide
和inject
绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
这里给出vue3的响应实现方式:
import inject, reactive from "vue"
...
class Store
constructor(options: any)
this._state = reactive(data: options.state())
this._mutation = options.mutations
get state()
return this._state.data
...
vue2是通过new一个vue实例,数据挂在vue实例的data下,直接访问返回的vue实例就可以访问到变化的值。
class Store
constructor (options)
this.vm = new _Vue(
data:
state: options.state
)
get state ()
return this.vm.state
以上是关于全家桶:vuex从使用到实现(超简单面霸必备知识点)的主要内容,如果未能解决你的问题,请参考以下文章