- 作者:老汪软件技巧
- 发表时间:2024-08-27 11:02
- 浏览量:
本文所有源码均在:/Sunny-117/t…
通信方式总结
通信方式整体来讲能够分为两大类:
父子组件通信跨层级组件通信
父子组件通信
Props:通过 Props 可以实现父组件向子组件传递数据。
Event:又被称之为自定义事件,原理是父组件通过 Props 向子组件传递一个自定义事件,子组件通过 emit 来触发自定义事件,触发自定义事件的时候就会传递一些数据给父组件
属性透传:一些没有被组件声明为 props、emits 或自定义事件的属性,但依然能传递给子组件,例如常见的 class、style 和 id.
ref引用:ref除了创建响应式数据以外,还可以拿来作为引用。
<template>
<div>
<B ref="childRef" />
<button @click="clickhandle">change namebutton>
div>
template>
<script setup>
import { ref } from 'vue'
import B from './B.vue'
// 这里的ref是拿来做引用的
const childRef = ref(null)
function clickhandle() {
if (childRef.value) {
// 当前存在组件的引用
console.log(childRef.value.name)
childRef.value.changeName()
}
}
script>
<template>
<div>这是B组件div>
<div>{{ name }}div>
template>
<script setup>
import { ref } from 'vue'
const name = ref('bill')
function changeName() {
name.value = 'john'
}
// 需要将数据和方法进行暴露
defineExpose({
name,
changeName
})
script>
作用域插槽:子组件在设置 slot 的时候,上面绑定一些属性,回头父组件通过 v-slot 来拿到这些属性。
跨层级组件通信
依赖注入:通过 provide(提供数据方)和 inject(注入数据方)来实现的。
事件总线:从 Vue2 时期就支持的一种通信方式。从 Vue3 开始更加推荐 依赖注入 或者 Pinia 来进行组件通信。不过事件总线这种方式仍然保留了下来。
自定义数据仓库:其实就是简易版的 Pinia.
Pinia
Pinia自定义插件
在 Pinia 中,可以为仓库添加插件,通过插件可以扩展以下内容:
首先建议插件单独放置于一个目录下,一个插件其实就是一个方法:
export function myPiniaPlugin1() {
// 给所有的仓库添加了一条全局属性
return {
secret: "the cake is a lie",
};
}
export function myPiniaPlugin2(context) {
// console.log(context);
const { store } = context;
// 在仓库上扩展状态
store.test = "this is a test";
}
/**
* 给特定的仓库来扩展内容
* @param {*} param0
*/
export function myPiniaPlugin3({ store }) {
if (store.$id === "counter") {
// 为当前 id 为 counter 的仓库来扩展属性
return {
name: "my name is pinia",
};
}
}
/**
* 重置仓库状态
*/
export function myPiniaPlugin4({ store }) {
// 我们首先可以将初始状态深拷贝一份
const state = deepClone(store.$state);
// 提供一个 reset 方法可以重置仓库状态
store.reset = () => {
store.$patch(deepClone(state));
};
}
每个插件扩展内容,其实就是对仓库进行内容扩展。如果想要针对某一个仓库进行内容扩展,可以通过 context.store.$id 来指定某一个仓库来扩展内容。
插件书写完毕后,需要通过 pinia 实例对插件进行一个注册操作:
// 引入自定义插件
import { myPiniaPlugin1, myPiniaPlugin2, myPiniaPlugin3, myPiniaPlugin4} from './plugins';
// 注册
pinia.use(myPiniaPlugin1);
pinia.use(myPiniaPlugin2);
pinia.use(myPiniaPlugin3);
pinia.use(myPiniaPlugin4);
之后就可以在 store 上使用插件添加的状态或者方法,例如:
// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
// 自定义插件
// 在该自定义插件中,扩展了一个数据和方法
function myPlugin({ store }) {
store.$state.pluginData = '这是插件添加的数据';
store.pluginMethod = function () {
console.log('这是插件添加的方法');
};
}
const pinia = createPinia();
// 注册自定义插件
pinia.use(myPlugin);
const app = createApp(App);
app.use(pinia);
app.mount('#app');
// store.js
import { defineStore } from 'pinia';
export const useMyStore = defineStore('myStore', {
state: () => ({
myData: '初始数据'
}),
actions: {
usePluginMethod() {
this.pluginMethod(); // 使用插件提供的方法
console.log(this.pluginData); // 访问插件提供的数据
}
}
});
实战案例:记录操作日志和捕获错误
书写一个插件,该插件用来记录操作日志和捕获错误。
export function logPlugin({ store }) {
// 监听所有的 action
// 当触发了某一个 action 的时候,会执行这个回调函数
/**
* name: 本次触发 action 的名称
* args:触发 action 时传入的参数
* after:action 执行成功后的回调函数
* onError:action 执行失败后的回调函数
*/
store.$onAction(({ name, args, after, onError }) => {
// 记录开始时间
const startTime = Date.now()
console.log(`Action ${name} started with arguments: ${JSON.stringify(args)}`)
// action 执行成功后的回调函数
// result 是 action 执行成功后的返回值
after((result) => {
// 记录结束时间
const endTime = Date.now()
console.log(
`Action ${name} finished in ${endTime - startTime}ms with result: ${JSON.stringify(result)}`
)
})
onError((error) => {
// 记录结束时间
const endTime = Date.now()
console.error(`Action ${name} failed in ${endTime - startTime}ms with error: ${error}`)
})
})
}
第三方插件
在 npm 官网搜索关键字 “pinia plugin”,之后根据文档使用。
自主学习:pinia-plugin-persistedstate 插件的使用。
「❤️ 感谢大家」
如果你觉得这篇内容对你挺有有帮助的话:点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。觉得不错的话,也可以阅读 Sunny 近期梳理的文章(感谢掘友的鼓励与支持 ):
我的博客:
Github:
前端八股文题库:sunny-117.github.io/blog/
前端面试手写题库:/Sunny-117/j…
手写前端库源码教程:sunny-117.github.io/mini-anythi…
热门文章
专栏