Nuxt3 中的状态管理

218 阅读3分钟

大家好!本篇将要分享的内容是如何在Nuxt3中进行状态管理。在Nuxt 主要有两种方式进行状态管理:

  • 第一种是使用Nuxt3 中的useState,在Nuxt3中提供了一个内置的组合式函数useState来进行状态管理, 用useState设置的状态可以在组件之间进行共享, 在初始设置时他接收一个唯一的key作为第一个参数。第二个参数是一个函数,并且这个函数返回一个值,这个值就是状态。
  • 第二种是集成第三方库,比如说Pinia或者Vuex, 本篇以Pinia为例

useState 的使用

1. 先初始化一个项目:

pnpm dlx nuxi@latest init nuxt3-state

2. 创建项目结构

image.png

3. 登录页面编写

<template>
  <div>
    <div class="form-item">
      <label>用户名:</label>
      <input v-model="userName" />
    </div>
    <div class="form-item">
      <label>密码:</label>
      <input type="password" v-model="password" />
    </div>
    <div class="btn-wrap">
      <button @click="login">登录</button>
    </div>
  </div>
</template>

<script setup>
const userName = ref('')
const password = ref('')

const router = useRouter()
const login = () => {

  useState('userInfo', () => {
    return {
      name: userName.value,
      email: userName.value + '@163.com'
    }
  })
  router.push('/')
}

</script>

<style scoped>
.form-item {
  display: flex;
  margin-top: 20px;
}

.form-item label {
  width: 80px;
}

.form-item input {
  outline: none;
  border: none;
  box-shadow: 0 0 0 1px #dcdfe6 inset;
  border-radius: 4px;
  line-height: 40px;
}
.btn-wrap {
  margin-top: 20px;
}
.btn-wrap button {
  padding: 6px 12px;
  background: #409eff;
  border: none;
  border-radius: 4px;
  color: #fff;
  margin-left: 80px;
  cursor: pointer;
}
</style>

在登录组件中点击登录后,用useState设置了用户信息。

4. 首页

pages/index.vue

<template>
  <div>
    <h1>首页</h1>
    <p>恭喜您登录成功!以下是您的个人信息:</p>
    <p>用户名: <strong>{{ userInfo.name }}</strong></p>
    <p>邮箱: <strong>{{ userInfo.email }}</strong></p>
  </div>
</template>

<script setup>
const userInfo = useState('userInfo') | {}
</script>

<style scoped>

</style>

在首页中我们使用useState 获取登录页面设置的用户信息。

5. 运行效果

hello-state.gif 可以看到我们在登录页面设置的用户信息能在首页进行获取到。到这里我们就掌握了useState 的用法。

集成Pinia

1. 安装依赖

执行pnpm i pinia @pinia/nuxt

到这里很有可能会出现以下错误:

image.png

我们按照提示执行下pnpm install 命令,然后再执行pnpm i pinia @pinia/nuxt 就可以安装成功了。

我们将之前useState 实现的状态改成Pinia来写。

2. 修改nuxt.conifig.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  compatibilityDate: '2024-11-01',
  devtools: { enabled: true },
  modules:['@pinia/nuxt']
})

主要增加了modules:['@pinia/nuxt']

3. 项目根目录下新增stores,stores下新增user.ts

stores/user.ts

interface Iuser {
  name: string | '',
  email: string | ''
}
export default defineStore('userStore', {
  state () {
    return {
      userInfo: {
        name: '',
        email: ''
      }
    }
  },
  actions: {
    setUserInfo({ name, email}: Iuser) {
      this.userInfo.name = name
      this.userInfo.email = email
    }
  }
})

4. 修改login.vue

pages/login.vue

<template>
  <div>
    <div class="form-item">
      <label>用户名:</label>
      <input v-model="userName" />
    </div>
    <div class="form-item">
      <label>密码:</label>
      <input type="password" v-model="password" />
    </div>
    <div class="btn-wrap">
      <button @click="login">登录</button>
    </div>
  </div>
</template>

<script setup>
import useUserStore from '~/stores/user'
const userName = ref('')
const password = ref('')

const router = useRouter()
const userStore = useUserStore()
const login = () => {
  userStore.setUserInfo({
    name: userName.value,
    email: userName.value + '163.com'
  })
  router.push('/')
}

</script>

<style scoped>
.form-item {
  display: flex;
  margin-top: 20px;
}

.form-item label {
  width: 80px;
}

.form-item input {
  outline: none;
  border: none;
  box-shadow: 0 0 0 1px #dcdfe6 inset;
  border-radius: 4px;
  line-height: 40px;
}
.btn-wrap {
  margin-top: 20px;
}
.btn-wrap button {
  padding: 6px 12px;
  background: #409eff;
  border: none;
  border-radius: 4px;
  color: #fff;
  margin-left: 80px;
  cursor: pointer;
}
</style>

login.vue中,我们主要将login方法里面的逻辑改成了调用pinia的actions里面的方法来实现。

5. 修改index.vue

pages/index.vue

<template>
  <div>
    <h1>首页</h1>
    <p>恭喜您登录成功!以下是您的个人信息:</p>
    <p>用户名: <strong>{{ userInfo.name }}</strong></p>
    <p>邮箱: <strong>{{ userInfo.email }}</strong></p>
  </div>
</template>

<script setup>
import userUserStore from '~/stores/user.ts'
const { userInfo } = userUserStore()
</script>

<style scoped>

</style>

在index.vue中我们也是主要将useState 获取状态改成了用pinia 来实现。

6. 运行效果

login-pinia.gif

可以看到我们依然能正常设置用户信息。

总结

通过本篇的介绍,我们知道了Nuxt3中主要有两种方式管理状态,一种是Nuxt3内置的useState, 另一种是集成第三方库。本篇以Pinia 为例进行了介绍,并且介绍了安装依赖时出错处理的方式。