全家桶: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中自由的使用数据而不必在意其组件位置,官网上有一段话:

我们可以使用一对 provideinject。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 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)
    

点击按钮后发现,数据已经成功改变。

但是页面没有更新。

这是由于provideinject默认为非响应式操作,官网在provideinject一节出给出了响应式的解决方案。

Vue3:这是因为默认情况下,provide/inject 绑定并不是响应式的。我们可以通过传递一个 ref property 或 reactive 对象给 provide 来改变这种行为。

Vue2:provideinject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 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从使用到实现(超简单面霸必备知识点)的主要内容,如果未能解决你的问题,请参考以下文章

从零开始系列之vue全家桶安装使用vuex

? vue3 全家桶体验

Vue全家桶之Vuex

Vue 全家桶

❤️‍Spring全家桶从入门到大神--mvc 常见知识点

进阶 vue 全家桶