vue3.0,vuex使用(dark不必),用provide、inject、localStorage实现

再vue3.0之后,推出了组合式api以及新的响应式。使状态管理可不必再用vuex实现,就有点借鉴react-redux的状态管理了。接下来一 一介绍

常规vuex

// 这里store创建挂载就不讲了,cli创建就会有,只讲再.vue文件中使用,大致与2.x类似
// vue2.x中vuex使用参考:https://blog.csdn.net/HockJerry/article/details/113977151

import { ref } from "vue";
import { useStore } from "vuex";
export default {
  setup() {
    const store = useStore()
    const state = store.state
    function addNum () {
      // state
      // console.log(state.num)

      // mutations
      // store.commit("addNum",{num:1})
      // store.commit({type:"addNum",num:1})

      // actions
      // store.dispatch("add",{num:10})
      // store.dispatch({type:"add",num:10})

      // getters
      // num.value= store.getters.getNum
    }
    return {
      state,
      addNum
    }
  }
}

使用provide,inject,localStorage

这里provideinject如果不理解可以去vue.js官网,看一会就懂了。
实现原理:
因为vue都是挂载在App下面的,所以在最上层provide,在下面的所有组件都可以通过inject获取到,
但是这样刷新的话就会与vuex一样状态初始化,所以借用localStorage作为数据存储中心实现永久储存。
在这里插入图片描述
创建actions

// createStore/actions.js

function setAge (state) {
  return (age) => {
    state.user.age += age
  }
}
function addNum (state) {
  return (count) => {
    state.count += count
  }
}
export default function setAction (state) {
  return {
    add: addNum(state),
    setAge: setAge(state)
  }
}

创建localStorage储存机制
这里借用watch来同步更新state和localStorage的数据,使用的时候可以去查看浏览器的localStorage更直观些,不会查看以前也写过

// createStore/save.js
import { readonly, watch, toRaw } from 'vue'

export default function createStore (state, key = 'default') {
  const STORAGE_KEY = 'vue3'	// 这是所有数据储存的标记,看自己命名

  // 每次执行都会先去取一次,这样刷新就不会丢失数据
  Object.entries(getItem(key)).forEach(([key, value]) => { 
    state[key] = value
  })

  function setItem (state, keys) {
    const stateRow = getItem()
    stateRow[keys] = state
    const stateStr = JSON.stringify(stateRow)
    localStorage.setItem(STORAGE_KEY, stateStr)
  }

  function getItem (keys) {
    const stateStr = localStorage.getItem(STORAGE_KEY) || '{}'
    const stateRow = JSON.parse(stateStr) || {}
    return keys ? stateRow[keys] || {} : stateRow
  }
  // 这里的watch不懂的可以在前面的文章里看
  watch(() => state, () => {
    const stateRow = toRaw(state) // 这里的state还具有响应性,要用toRaw去掉响应性
    setItem(stateRow, key)
  }, { deep: true })
  
  // 这里要用到readOnly,因为state是响应式的,所以外部不能随意更改只能通过定义的actions更改
  return readonly(state)
}

定义state并组合
数据多的话也可以把定义state这一块单独拿出来,再引入合并

// createStore/index.js
import { reactive, readonly } from 'vue'
import setAction from './actions'
import createStore from './save'

export function doUser () {
  const state = reactive({
    user: {
      name: 'jerry',
      age: 18
    },
    count: 0
  })
  // actions 也要用readonly,不能更改
  return {
    state: createStore(state, 'hospital'), // 这里创建为hospital模块,也可以按照index.js多创几个
    actions: readonly(setAction(state))
  }
}

在App.vue中注入

<template>
  <div id="nav">
    <div>
      {{state.user.name}}--{{state.user.age}}
    </div>
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
  </div>
  <router-view/>
</template>

<script>
// 在最上层注入,里面的所有子组件就可通过inject获取
import { doUser } from './creatStore'
import { provide } from 'vue'
export default {
  setup () {
    const { state, actions } = doUser()
    provide('hospital', { state, actions }) // 第一个参数是注入名(键名),第二个参数是值
    return {
      state
    }
  }
}
</script>

在Home.vue中inject获取
在这里点,App.vue的数据也会跟着变,刷新也不会丢失。
需要在actions添加方法,手动清除state的数据。或者直接浏览器清除localStorage(你肯定会的)

<template>
  <div class="home">
    <button type="button" class="" @click="setAge(1)">click</button>
    <p>{{state.user.name}}--{{state.user.age}}</p>
  </div>
</template>

<script>
import { inject } from 'vue'
export default {
  name: 'Home',
  setup () {
    const { state, actions } = inject('hospital')
    const setAge = actions.setAge
    return {
      state,
      setAge
    }
  }
}
</script>

这就是通过provide,inject,localStorage实现全局状态管理。
下篇文章改动下,不用provide,inject实现。

顺便把文件夹贴出来,要不然到处引入怕混乱:

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值