# Vue3 小菠萝 Pinia使用

Vue3 Pinia使用

在学习 Vue2 的宝子们一定都知道,在 vue2 版本中,如果想要使用状态管理器,那么一定是集成 Vuex,首先说明一点,Vuex 在 vue3 项目中依旧是可以正常使用的,是 vue 项目的正规军。但是,今天我们学习一下小菠萝,Pinia 目前也已经是 vue 官方正式的状态库。适用于 vue2 和 vue3。可以简单的理解成 Pinia 就是 Vuex5。也就是说, Vue3 项目,建议使用Pinia,当然很多公司或者是项目由 vue2 转为 vue3 之后,由于习惯了使用 vuex ,所以说,在 vue3 当中继续使用 vuex 的,也不是少数,都知道就可以,根据实际情况来选择。

什么是 Pinia

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。Pinia 的成功可以归功于他管理存储数据的独特功能,例如:可扩展性、存储模块组织、状态变化分组、多存储创建等。

Pinia 的优点

Pinia 被 vue 纳入正规编制,肯定是有原因的,那 pinia 有啥优点呢,主要是一下几点:

  • pinia 符合直觉,易于学习。
  • pinia 是轻量级状态管理工具,大小只有1KB.
  • pinia 模块化设计,方便拆分。
  • pinia 没有 mutations,直接在 actions 中操作 state,通过 this.xxx 访问响应的状态,尽管可以直接操作 state,但是还是推荐在 actions 中操作,保证状态不被意外的改变。
  • store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或者是 MapAction 辅助函数,这是在 Vuex 中很常见的。
  • 支持多个 store。
  • 支持 Vue devtools、SSR、webpack 代码拆分。

相关资料

Pinia 中文网:https://pinia.web3doc.top/

在这里插入图片描述

Pinia 安装

安装 pinia 就很简单了,直接命令安装就可以了。

npm install pinia -save

或者

yarn add pinia

在这里插入图片描述

Pinia 使用

安装完 pinia ,然后就是使用了,使用的第一步,就是在项目中引入 pinia。

Pinia 导入

首先在 main.js 文件中引入,很简单,不要慌宝子们。

import {createPinia} from 'pinia'

然后,这个 pinia 就在项目中导入了,但是上面是 vue3 的写法哈,我起的这个项目是 vue3 的。

Pinia 是支持 vue2 的,如果是 vue2 的项目,导入的方式是下面的样子:

import {PiniaVuePlugin} from 'pinia'

好的,我们还是以 vue3 来介绍这个 Pinia。

导入的时候是 hook ,我们需要调用一下

const state = createPinia()

调用完成,state 是以插件的形式存在的,所以说最后我们需要在项目使用一下。

app.use(state)

好的,编写完上边这一大堆,我们就实现了在 vue3 项目中导入 pinia 的全部操作。

![在这里插入图片描述](https://img-blog.csdnimg.cn/81468f2b51f542c8bf22a0d61bc7dce6.png

接下来就可以具体的使用 pinia 了。

Pinia 基本使用

创建 index.ts 文件

使用起来相对简单一些,我们首先在根目录下创建一个 store 文件夹,这个都晓得哈,当年用 vuex 的时候也是这个结构。毕竟 pinia 就是用来替换掉 vuex 的嘛。

创建完 store 文件夹,在里面创建一个 ts 文件,叫做 index.ts 。

在这里插入图片描述

编写 index.ts 文件

然后我们开始编写 index.ts 文件。

首先我们先引入 pinia。

import { defineStore } from "pinia";

由于 defineStore 也是一个 hooks ,所以说我们可以直接导出一下。

export const Test = defineStore()

这样子写是会报错的,因为这个 defineStore 是需要传参数的,其中第一个参数是id,就是一个唯一的值,简单点说就可以理解成是一个命名空间,我们可以写一个枚举再传值。

我们在同级在创建一个名字叫做 store_name.ts 的文件写一个枚举数据导出。

在这里插入图片描述

export const enum Names {
  TEST = "TEST"
}

然后在 index.ts 文件中引入一下枚举数据,然后传给这个 defineStore。

import { defineStore } from "pinia";
import { Names } from "./store_name";

export const useInfoStore = defineStore(Names.TEST)

ok, 这个样子还是报错的,因为还有其他的参数需要传递,第二个参数就是一个对象,里面有三个模块需要处理,第一个是 state,第二个是 getters,第三个是 actions。

  • state 和之前我们 vuex 里面的写法是不一样的,在 vuex 里面呢,state 是一个对象,但是在 pinia 中,state 必须是一个箭头函数,然后在返回一个对象。
  • getters 模块呢,类似于计算属性,是有缓存的,主要是帮助我们修饰一些值。
  • actions 呢,类似于 methods,帮助我们做一些同步的或者是异步的操作,提交 state 之类的。

到此完整的 index.ts 文件代码:

import { defineStore } from "pinia";
import { Names } from "./store_name";

export const useInfoStore = defineStore(Names.TEST, {
  state: () => {
    return {
      name: '我是𝒆𝒅.',
      age: 10,
    }
  },

  getters: {

  },

  actions: {

  }

})

好的,其实到这个地方为止呢,其实我们已经可以使用 pinia 了,我们写一个页面使用一下 pinia 的值。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()
</script>
<style scoped>

</style>

保存代码,刷新一下页面,我们可以看到,数据已经渲染在界面上了。

在这里插入图片描述

如果我们有 devtools 工具的话,我们可以看见我们的数据是可以查询到的。

在这里插入图片描述
未完待续~

继续

修改 Pinia 的值

修改 Pinia 的值有很多中方式,我们一个一个来。

修改 pinia 的值,其实就是修改 state 的值,上边的案例我们写了一个 state,里面有两个值,一个是 name, 一个是 age,今天我们的任务就是实现修改 pinia 中 state 的值。

修改值的方式呢,常见的有五种,我们一个一个看。

方式一:直接修改

这种方式呢,非常的简单粗暴,直接修改就可以了。

比如,上边我们页面上有一个按钮,点击按钮的时候实现 age 加一操作。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <el-button @click="changeAge">年龄+1</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()

  const changeAge = () => {
    userInfo.age++
  }

</script>
<style scoped>

</style>

保存刷新页面,我们看一下效果。

在这里插入图片描述
OK,成功实现了点击按钮的时候,age 自动 + 1 操作。

注意哈: 在 vuex 里面是坚决不允许这样子直接操作 state 数据的,但是小菠萝是可以允许滴!

方式二:$patch 函数修改

在我们实例化 const userInfo = useInfoStore() 这个 state 的时候,其实这个 userInfo 中,有一个方法,就是 patch 函数,它可以帮助我们批量修改。比如点击按钮,同时修改 name 和 age 的值,直接上代码:

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <el-button @click="change">修改name和age</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()
  
  // 方式二: 通过 patch 函数批量修改 name 和 age
  const change = () => {
    userInfo.$patch({
      age: 11,
      name: '𝒆𝒅.'
    })
  }

</script>
<style scoped>
</style>

保存刷新页面,开始测试效果。

在这里插入图片描述
好的,通过使用 patch 函数实现批量修改 state 的数据。

方式三:$patch 函数修改

哎呦喂,为什么和第二种一样,没错滴宝子们,和第二种一样都是使用 patch 函数来实现修改,但是有区别,方式二实在 patch 函数中传入修改的对象值,但是这种方式传入的是一个函数,作用是啥子呢?就是可以进行逻辑操作,比如说判断之类的。

上代码:

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <el-button @click="change">修改name和age</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()

  // 方式三
  const change = () => {
    userInfo.$patch((state) => {  // 这里传入的state就是pinia的state
      state.age = 11  
      state.name = '𝒆𝒅.'
    })
  }

</script>
<style scoped>

</style>

保存看一下效果,其实和方式二是一模一样的。

在这里插入图片描述
好的,这就是通过 patch 传入函数的方式修改 state 内容。

方式四:$state 方式

首先说一点儿哈,第四种方式不是很常用。为啥呢?尽管它也可以修改 state 的值,但是这种方式有一个很大的弊端,什么弊端呢,与其说是修改 state 的值,倒不如说直接替换掉 state,什么意思呢?简单点说,比如上边的 state 里面有两个值,一个是 name,一个是 age,如果我们只想修改 age 的值,那么我们必须把 age 和 name 的值都写上才可以,如果只写 age ,那么 name 的值就没有了,理解吧?直接看代码。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <el-button @click="change">修改name和age</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()

  // 方式四:state
  const change = () => {
    userInfo.$state = {
      name: '𝒆𝒅.',
      age: 11
    }
  }

</script>
<style scoped>

</style>

保存刷新页面,点击按钮查看效果,其实和上面的案例是一样的,可以修改 name 和 age。

在这里插入图片描述
我们可以看到,把数据全部传进去,数据改了。

方式五: action 方式

这个方式我们需要借助 actions 来实现,所以说我们需要去 store 文件夹下的 index.ts 文件中写一个 action。

import { defineStore } from "pinia";
import { Names } from "./store_name";

export const useInfoStore = defineStore(Names.TEST, {
  state: () => {
    return {
      name: '我是𝒆𝒅.',
      age: 10,
    }
  },

  getters: {

  },

  actions: {
    setAge () {  // 注意,这里就不要写箭头函数了,不然 this 指向会出问题。
      this.age = 11
    }
  }

})

写完 action 我们就可以使用 action 的方式修改 age 的值了。怎么使用呢,我们只需要使用实例去调用一下我们刚才写的 action 函数就行了。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <el-button @click="change">修改 age</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()
  
  // 方式五
  const change = () => {
    userInfo.setAge()
  }

</script>
<style scoped>

</style>

保存看一下效果。

在这里插入图片描述
好的,这个就是通过 action 方式修改。

当然了,这个 action 是可以传参的,我们修改一下 index.ts 文件编写的 action 函数,让他接受一个参数再赋值。

  actions: {
    setAge(num: number) {  // 注意,这里就不要写箭头函数了,不然 this 指向会出问题。
      this.age = num
    }
  }

然后我们页面代码直接传进去参数就可以了。

  // 方式五
  const change = () => {
    userInfo.setAge(12)
  }

修改完保存刷新,看一下效果。

在这里插入图片描述
好了,上边就是常见的五种修改 state 数据的方式,可以根据自己的实际情况选择使用。

pinia 解构

本来不想写了,但是还是稍微说一下吧。

上面的案例,我们实例化const userInfo = useInfoStore()了以后呢,这个 userInfo 是可以继续解构操作的,这个也不用细说,会ES的都知道解构操作。

const {name, age} = userInfo

解构完成,我们看一下效果。

全部代码:

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>解构前</p>
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <p>解构后</p>
  <p>pinia 中的信息: {{name}} --- {{age}}</p>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()
  const { name, age } = userInfo

</script>
<style scoped>

</style>

在页面分别展示一下解构前和解构后的数据,保存刷新看效果。

在这里插入图片描述
我们可以看到哈,就是结构前和结构后我们在页面都可以获取到数据展示。

但是有个问题哈,就是解构后的数据,是不具备响应式的,啥意思呢,就是我们修改了 state 的值,页面不会跟着变化,我们测试一下。

编写代码,点击按钮,age 加一,看一下结构前和解构后的数据在页面是否会实时渲染。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>解构前</p>
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <p>解构后</p>
  <p>pinia 中的信息: {{name}} --- {{age}}</p>

  <el-button @click="change">Age +1</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()
  const { name, age } = userInfo

  let change = () => {
    userInfo.age++
  }

</script>
<style scoped>

</style>

保存刷新,点击按钮查看效果。

在这里插入图片描述
通过测试我们可以看到,结构前的是可以实时渲染的,但是解构后的话是不可以的, 因为解构后的不是响应式数据。

怎么解决这个问题呢,其实也很简单哈,官方提供了了一个方法,可以把解构后的数据转换为响应式的数据。

就是 storeToRefs,使用 storeToRefs 需要导入一下。

 import { storeToRefs } from 'pinia'

然后把我们解构的对象包裹一下就可以了,这个方法和 toRefs 是类型的,应该理解哈。

const { name, age } = storeToRefs(userInfo)

然后我们修改案例的代码,再看一下效果。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>解构前</p>
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>
  <p>解构后</p>
  <p>pinia 中的信息: {{name}} --- {{age}}</p>

  <el-button @click="change">Age +1</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 导入storeToRefs
  import { storeToRefs } from 'pinia'
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()
  // 包裹一下结构对象
  const { name, age } = storeToRefs(userInfo)

  let change = () => {
    userInfo.age++
  }

</script>
<style scoped>

</style>

保存刷新一下。

在这里插入图片描述
我们可以看到,解构后的数据也已经变成响应式的了。

或者我们换一个写法,直接操作结构后的数据,记得,要 .value

  let change = () => {
    age.value++
  }

效果是一样的。

Pinia 的 actions

actions 是可以处理同步,也可以处理异步,同步的话相对来说简单一点,上面我们通过 action 修改 state 的时候,就用到了 actions 的同步,这里就不再赘述了。

actions 异步

首先我们模拟一个异步函数,比如说登录。

type User = {
  name: String,
  age: Number
}

const Login = (): Promise<User> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        name: 'wjw',
        age: 22
      })
    }, 2000)
  })
}

然后我们在 actions 中就可以调用这个异步的操作了,在 actions 处理异步的时候呢,我们一般是与 asyncawait 连用。

所有 index.ts 文件代码:

import { defineStore } from "pinia";
import { Names } from "./store_name";

type User = {
  name: String,
  age: Number
}

const Login = (): Promise<User> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        name: 'wjw',
        age: 22
      })
    }, 2000)
  })
}

export const useInfoStore = defineStore(Names.TEST, {
  state: () => {
    return {
      name: '我是𝒆𝒅.',
      age: 10,
    }
  },

  getters: {

  },

  actions: {
    async setUser() {
      const result = await Login()
      this.name = result.name
      this.age = result.age
    }
  }
  
})

然后我们修改一下使用的页面也修改一下。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>

  <el-button @click="change">修改用户内容</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()

  let change = () => {
    userInfo.setUser()
  }

</script>
<style scoped>

</style>

保存刷新,点击按钮,等两秒钟假装请求,然后看数据变不变。

在这里插入图片描述
奈斯! nice! 完成异步案例!

actions 同步、异步连用

这个 actions 里面的方法函数是可以相互调用的,啥意思呢,就是你 actions 里面有好几个方法,这几个方法是可以调过来调过去的,但是注意哈,别玩嗨了,直接死循环了。看个案例:

上面的代码一改造,本来异步模拟获取的 age 数据是 22 ,然后我们调用一个 action 把 age 改成 80,这个是可以的哈。

import { defineStore } from "pinia";
import { Names } from "./store_name";

type User = {
  name: String,
  age: Number
}

const Login = (): Promise<User> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        name: 'wjw',
        age: 22
      })
    }, 2000)
  })
}

export const useInfoStore = defineStore(Names.TEST, {
  state: () => {
    return {
      name: '我是𝒆𝒅.',
      age: 10,
    }
  },

  getters: {

  },

  actions: {

    async setUser() {
      const result = await Login()
      this.name = result.name
      this.age = result.age
      this.setAge(80)
    },
    
    setAge(num: number) {  // 注意,这里就不要写箭头函数了,不然 this 指向会出问题。
      this.age = num
    },

  }

})

我们保存代码,刷新点击按钮等两秒钟然后看一下效果。

在这里插入图片描述
看到效果,改了吧! 啊哈哈哈哈,666!

getter 函数

接下来我们稍微过一下 getter 函数。

getters 类似于 vue 里面的计算属性,可以对已有的数据进行修饰。有两种写法,我们一个一个看哈。

普通函数方式写法

这个就比较简单了,直接上代码:

  getters: {
    newName() {
      return `这是getter修饰过的名称  ${this.name}`
    }
  },

这个代码啥意思很简单是吧,就是在之前 name 的基础上拼接上了一个字符串,但是这样 ts 可能不会正确的进行数据类型转换,所以说我们可以加一个类型定义。

  getters: {
    newName():string {
      return `这是getter修饰过的名称  ${this.name}`
    }
  },

告诉他,就是字符串类型。

然后这个 getter 就可以直接在模板上使用,直接改一下之前的让他在页面上展示出来。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>

  <el-button @click="change">修改用户内容</el-button>

  <p>getter: {{userInfo.newName}}</p>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()

  let change = () => {
    userInfo.setUser()
  }

</script>
<style scoped>

</style>

保存刷新,看一下效果。

在这里插入图片描述
现在默认的数据是上面截图的样子,然后我们点一下按钮,修改一下 name,然后看一下效果。
在这里插入图片描述
我们可以看见,点击修改 name 之后呢,getter 也会实时的去渲染出来。

相互调用

嘻嘻,没错啦,这个 getter 也是可以像 actions 一样相互调用的啦!

看代码:

  getters: {
    newName():string {
      return `这是getter修饰过的名称  ${this.name} ,他的年纪是 ${this.getAge}`
    },

    getAge():number {
      return this.age
    }
  },

保存,刷新一下看效果。

在这里插入图片描述
也是可以的哈。

API 的使用

pinia 里面呢,有很多的 API,今天就稍微说几个常见的哈。

$reset :重置到初始值

这个 $reset 可以将 state 的数据初始到初始值,比如我们有一个数据,点击按钮改变了,然后我们可以通过这个 API ,将数据恢复到初始状态值。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>

  <el-button @click="change">修改用户内容</el-button>

  <p>getter: {{userInfo.newName}}</p>

  <el-button @click="reset">$reset</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()

  let change = () => {
    userInfo.setUser()
  }

  // 重置
  let reset = () => {
    userInfo.$reset()
  }

</script>
<style scoped>

</style>

我们先修改用户信息,然后在重置。

在这里插入图片描述
流弊!完美实现重置。

$subscribe:监听 state 数据变化

$subscribe 使用来监听的,监听 state 数据的变化,只要 state 里面的数据发生了变化,就会自动走这个函数。

<template>
  <h3>pinia</h3>
  <!-- 在页面中直接使用就可以了 -->
  <p>pinia 中的信息: {{userInfo.name}} --- {{userInfo.age}}</p>

  <el-button @click="change">修改用户内容</el-button>

  <p>getter: {{userInfo.newName}}</p>

  <el-button @click="reset">$reset</el-button>
</template>
<script setup>
  // 首先需要引入一下我们刚刚创建的store
  import { useInfoStore } from '../store';
  // 因为是个方法,所以我们得调用一下
  const userInfo = useInfoStore()

  let change = () => {
    userInfo.setUser()
  }

  // 重置
  let reset = () => {
    userInfo.$reset()
  }

  // 监听 state 的变化,返回一个工厂函数
  userInfo.$subscribe((args, state) => {
    console.log(args, state)
  })

</script>
<style scoped>

</style>

监听函数写一下,然后保存刷新。

在这里插入图片描述
可以打印出数据,需要啥进去取就可以了。

$onAction:一调用 actions 就触发

这个看名字就很好理解了吧,就是 action 一调用就会被触发。

它里面只有一个参数 args。写一下关键代码吧。

  userInfo.$onAction((args) => {
    console.log(args)
  })

保存刷新。

在这里插入图片描述
我们在点击的时候,之前案例是相互调用了两个 action,所以打印了两个。

其中打印出来的有一个 after ,这是回调,我们可以看一下,监听到了之后再走的回调,我们测试一下。

  // $onAction
  userInfo.$onAction((args) => {
    args.after(() => {
      console.log('after 回调')
    })
    console.log(args)
  })

我们先打印了回调,在打印数据,保存看结果。

在这里插入图片描述
看到结果,反而是先输出了数据,在走的回调,理解了吧?

我们看到打印的数据还有一个 args,这个args 是 actions 传进来的参数。

好的,继续。

补充

补充一点哈,$onAction 刚才的案例我们只传了一个参数,就是一个工厂函数,其实他还有第二个参数—— true,传 true 的意义是啥呢?就是当这个组件销毁了,这个 $onAction 还可以继续保活。

  // $onAction
  userInfo.$onAction((args) => {
    args.after(() => {
      console.log('after 回调')
    })
    console.log(args)
  }, true)

不止 $onAction 可以传第二个参数,$subscribe 也有第二个参数,只不过 $subscribe 的参数是一个对象,对象里面设置的是 detached 为 true ,效果和 $onAction 是一样的,当然还有其它的参数,和 watch 是类似的。

  userInfo.$subscribe((args, state) => {
    console.log(args, state)
  }, {
    detached: true,
    deep: true,
    flush: 'post'
  })

好了,关于常见的 API 也就这样了。

结束!

posted @ 2022-07-28 11:46  我是+V  阅读(1188)  评论(0编辑  收藏  举报