目录
10.本地缓存传值 localStorage/sessionStorage
11.注入的方式传值 provide/inject(不推荐)
1.父子传值
1. 父组件中的子组件标签上使用 :属性名 的方式来传值
-------------------------------------------
<template>
<Child :message="parentMessage" />
</template>
<script>
import { ref } from 'vue';
import Child from './Child.vue';
export default {
components: { Child },
setup() {
const parentMessage = ref('Hello from parent!');
return { parentMessage };
}
};
</script>
2. 子组件中的props中接父组件子组件标签的对应属性名
-------------------------------------------
<template>
<div>{
{ message }}</div>
</template>
<script>
import { defineProps } from 'vue';
export default {
setup(props) {
const { message } = defineProps(['message']);
console.log(props.message, message) // 效果一样
return { message };
}
};
</script>
2.子父传值
主要知识点:emit
子组件中:
<template>
<button @click="sendMessage">Send Message</button>
</template>
<script>
import { defineEmits } from 'vue';
export default {
setup() {
const emit = defineEmits(['send-message']);
const sendMessage = () => {
emit('send-message', 'Hello from child!');
};
return { sendMessage };
}
};
</script>
父组件的子组件标签上:
<template>
<Child @send-message="receiveMessage" />
</template>
<script>
import { ref } from 'vue';
import Child from './Child.vue';
export default {
components: { Child },
setup() {
const childMessage = ref('');
const receiveMessage = (msg) => {
childMessage.value = msg;
console.log('Message from child:', childMessage.value);
};
return { receiveMessage };
}
};
</script>
3.非父子传值
使用事件总线在非父子组件间通信。
1. 事件总线(EventBus.js):
import { createApp } from 'vue';
export const eventBus = createApp({}).config.globalProperties;
2. 发送方组件(Sender.vue):
<template>
<button @click="broadcastMessage">Broadcast Message</button>
</template>
<script>
import { ref } from 'vue';
import { eventBus } from './EventBus';
export default {
setup() {
const sendMessage = () => {
eventBus.$emit('broadcast', 'Hello from sender!');
};
return { sendMessage };
}
};
</script>
3. 接收方组件(Receiver.vue):
<template>
<div>{
{ broadcastMessage }}</div>
</template>
<script>
import { ref } from 'vue';
import { eventBus } from './EventBus';
export default {
setup() {
const broadcastMessage = ref('');
eventBus.$on('broadcast', (message) => {
broadcastMessage.value = message;
});
return { broadcastMessage };
}
};
</script>
4.children与parent(不推荐)
这种方式破坏了组件的封装性,不推荐使用。
5.ref的方式传值
最重要的一点,想要ref传值赋值,一定要用方法的方式去调用,直接赋值无效!!!
1.父组件(Parent.vue):
<template>
<Child ref="childRef" />
<button @click="sendMessageToChild">Send Message</button>
</template>
<script>
import { ref } from 'vue';
import Child from './Child.vue';
export default {
components: { Child },
setup() {
const childRef = ref(null);
const sendMessageToChild = () => {
if (childRef.value) {
childRef.value.receiveMessage('Hello from parent!');
}
};
return { childRef, sendMessageToChild };
}
};
</script>
2. 子组件(Child.vue):
<template>
<div>{
{ message }}</div>
</template>
<script>
import { defineExpose } from 'vue';
export default {
setup() {
const message = ref('');
const receiveMessage = (msg) => {
message.value = msg;
};
defineExpose({ receiveMessage });
return { message };
}
};
</script>
6.router路由传参query/params
在Vue 3中,您可以使用router.push
方法来传递参数给路由,这些参数可以是query
或params
类型。query
参数会附加在URL后面,通常用于非敏感信息的传递;而params
参数则包含在路由路径中,适合传递敏感信息或路由特定的参数。
1. 使用query
传参:
<template>
<button @click="navigateToUser">Navigate with Query</button>
</template>
<script setup>
import { useRouter } from 'vue-router';
const router = useRouter();
function navigateToUser() {
router.push({
path: '/user',
query: { id: 123, name: 'John Doe' }
});
}
</script>
2. 使用params
传参:
<template>
<button @click="navigateToUserParam">Navigate with Params</button>
</template>
<script setup>
import { useRouter } from 'vue-router';
const router = useRouter();
function navigateToUserParam() {
router.push({
name: 'User',
params: { id: 123 }
});
}
</script>
3. 接收路由参数(query & params):
<template>
<p>User ID: {
{ $route.query.id }}</p>
<p>User Name: {
{ $route.query.name }}</p>
<!-- 或者 -->
<p>User ID: {
{ $route.params.id }}</p>
</template>
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
console.log(route) // 包含query & params的参数
</script>
7.路由组件方式传值[:xxx]
步骤1: 配置路由
首先,你需要在路由配置中定义动态参数。这里我们假设有一个User
组件,它需要接收一个id
参数。
// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import User from '../views/User.vue';
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/user/:id',
component: User,
},
],
});
export default router;
在上面的路由配置中,:id
表示一个动态参数,它将在URL路径中被具体值替换。
步骤2: 创建组件
接下来,创建一个组件来接收和显示动态参数:
<!-- views/User.vue -->
<template>
<div>
<h1>User Information</h1>
<p>User ID: {
{ userId }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
const userId = route.params.id;
</script>
在这个组件中,我们使用useRoute
组合API从$route.params
中提取id
参数。
步骤3: 导航到动态路由
在其他组件中,你可以使用router.push
或router-link
来导航到动态路由,并传递参数:
<!-- components/SomeComponent.vue -->
<template>
<button @click="goToUser">Go to User</button>
</template>
<script setup>
import { useRouter } from 'vue-router';
const router = useRouter();
function goToUser() {
router.push({ path: '/user/123' });
}
</script>
或者使用router-link
:
<!-- components/SomeComponent.vue -->
<template>
<router-link :to="{ path: '/user/123' }">Go to User</router-link>
</template>
这样,当你点击按钮或链接时,应用程序将导航到/user/123
,并在User
组件中显示用户ID。
8.vuex状态管理工具传值
在Vue 3项目中,Vuex是一个常用的状态管理库,它可以帮助你在多个组件之间共享状态。以下是一个使用Vuex进行状态管理和传值的示例。
步骤 1: 安装Vuex
首先,确保你已经安装了Vuex。如果你的项目是基于Vue CLI创建的,可以通过以下命令安装Vuex:
npm install vuex@next
如果你的项目是使用Vite创建的,可以通过以下命令安装Vuex:
npm install vuex@next --save-dev
步骤 2: 创建Vuex store
在你的Vue项目中创建一个store
文件夹,并在里面创建index.js
文件来定义你的Vuex store。
// store/index.js
import { createStore } from 'vuex';
export default createStore({
state() {
return {
count: 0,
};
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
},
},
actions: {
increment(context) {
context.commit('increment');
},
decrement(context) {
context.commit('decrement');
},
},
});
步骤 3: 在主文件中引入Vuex store
在你的main.js
或main.ts
文件中,导入Vuex store并将其设置为Vue实例的一部分。
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import store from './store';
const app = createApp(App);
app.use(store);
app.mount('#app');
步骤 4: 在组件中使用Vuex状态
现在你可以在任何组件中通过mapState
、mapMutations
或mapActions
辅助函数来访问和修改Vuex store中的状态。
// components/Counter.vue
<template>
<div>
Count: {
{ count }}
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script setup>
import { mapState, mapActions } from 'vuex';
const count = mapState(['count']);
const { increment, decrement } = mapActions(['increment', 'decrement']);
</script>
步骤 5: 测试demo
你可以在App.vue
或其他组件中引入Counter.vue
来测试Vuex状态的传递和更新。
// App.vue
<template>
<div id="app">
<Counter />
</div>
</template>
<script setup>
import Counter from './components/Counter.vue';
</script>
当你点击Counter
组件中的按钮时,Vuex store中的count
状态会相应增加或减少,并且由于状态的响应式特性,所有使用了该状态的组件都会自动更新显示。
9. pinia状态管理工具传值
Pinia是专为Vue 3设计的状态管理库,它提供了一个简单、灵活的方式来组织和共享应用状态。以下是一个使用Pinia进行状态管理和传值的示例。
步骤 1: 安装Pinia
如果尚未安装Pinia,请运行以下命令来安装它:
npm install pinia
步骤 2: 创建Pinia store
在src/store
目录下创建一个新的JavaScript或TypeScript文件,例如user.js
,并定义你的store。
// store/user.js
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
firstName: '',
lastName: ''
}),
actions: {
setUserInfo(info) {
this.firstName = info.firstName;
this.lastName = info.lastName;
}
}
});
步骤 3: 在主文件中集成Pinia
在main.js
或main.ts
文件中,创建一个Pinia实例并将其注册到Vue应用中。
// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
const app = createApp(App);
app.use(createPinia());
app.mount('#app');
步骤 4: 在组件中使用Pinia store
在任何Vue组件中,你可以通过useUserStore
来访问和修改store中的状态。
// components/UserProfile.vue
<template>
<div>
<p>First Name: {
{ userStore.firstName }}</p>
<p>Last Name: {
{ userStore.lastName }}</p>
<button @click="updateUserInfo">Update Info</button>
</div>
</template>
<script setup>
import { useUserStore } from '../store/user';
const userStore = useUserStore();
function updateUserInfo() {
userStore.setUserInfo({
firstName: 'John',
lastName: 'Doe'
});
}
</script>
10.本地缓存传值 localStorage/sessionStorage
localStorage:
1.存储数据:localStorage.setItem(“自定义数据名”, 数据)
2.取存储的本地数据:localStorage.getItem(“存储数据的数据名”)
3.删除指定的本地数据:localStorage.removeItem(“存储数据的数据名”)
4.删除当前域名下所有内容:localStorage.clear()
sessionStorage:
1.存储数据:sessionStorage.setItem(“自定义数据名”, 数据)
2.取存储的本地数据:sessionStorage.getItem(“存储数据的数据名”)
3.删除指定的本地数据:sessionStorage.removeItem(“存储数据的数据名”)
4.删除当前域名下所有内容:sessionStorage.clear()
11.注入的方式传值 provide/inject(不推荐)
在Vue 3中,provide
和inject
是一种特殊的API,允许跨组件层次传递数据,而无需通过props。这种方式尤其适用于父子组件之间的通信,或者当你需要在组件树中的任何地方访问某个数据时。
下面是一个使用provide
和inject
的示例,其中一个父组件提供数据,一个孙子组件通过注射获取这些数据。
步骤 1: 创建父组件
首先,创建一个父组件,并在其setup
函数中使用provide
来提供数据。
<!-- ParentComponent.vue -->
<template>
<div>
<h1>Parent Component</h1>
<ChildComponent></ChildComponent>
</div>
</template>
<script setup>
import { provide } from 'vue';
const parentData = {
message: 'Hello from the Parent'
};
provide('parentData', parentData);
</script>
步骤 2: 创建中间组件(可选)
如果需要,可以创建一个中间组件,但在这个示例中,我们将直接从父组件跳转到孙子组件。
步骤 3: 创建孙子组件
接下来,创建一个孙子组件,并在其setup
函数中使用inject
来注射父组件提供的数据。
<!-- GrandchildComponent.vue -->
<template>
<div>
<h2>Grandchild Component</h2>
<p>{
{ grandchildData.message }}</p>
</div>
</template>
<script setup>
import { inject } from 'vue';
const grandchildData = inject('parentData');
</script>
步骤 4: 整合组件
在App.vue
或其他容器组件中,引入并使用上述创建的组件。
<!-- App.vue -->
<template>
<div>
<ParentComponent></ParentComponent>
</div>
</template>
<script setup>
import ParentComponent from './components/ParentComponent.vue';
import GrandchildComponent from './components/GrandchildComponent.vue';
</script>
步骤 5: 测试demo
运行你的Vue应用,你应该能够看到GrandchildComponent
中显示了来自ParentComponent
的数据。
12. 消息订阅与发表pubsub-js(了解)
PubSub-js 是一个轻量级的 JavaScript 库,用于实现基于发布/订阅模式的消息传递。在Vue 3中,您可以使用 PubSub-js 来实现组件之间的通信,即使这些组件不是直接父子关系。
安装 PubSub-js
首先,确保您已经安装了 pubsub-js
库。在终端中运行以下命令进行安装:
npm install pubsub-js
创建消息订阅
在需要接收消息的组件中,您可以使用 subscribe
方法来订阅一个特定的消息通道。当该消息通道上有消息被发布时,订阅的回调函数会被触发。
// SubscribingComponent.vue
<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
import pubsub from 'pubsub-js';
let subscription;
onMounted(() => {
// 订阅消息
subscription = pubsub.subscribe('my-channel', (msg, data) => {
console.log(`Received message: ${msg}, with data:`, data);
});
});
onBeforeUnmount(() => {
// 在组件销毁前取消订阅
if (subscription) {
pubsub.unsubscribe(subscription);
}
});
</script>
创建消息发表
在需要发送消息的组件或模块中,使用 publish
方法来发表消息到指定的通道。订阅了同一通道的所有订阅者都会收到这个消息。
// PublishingComponent.vue
<script setup>
import { ref } from 'vue';
import pubsub from 'pubsub-js';
const message = ref('Hello from publisher!');
const sendMessage = () => {
// 发表消息
pubsub.publish('my-channel', message.value);
};
</script>
完整的Demo测试
结合上述代码,您可以创建一个简单的Vue 3应用程序,其中包含一个用来发表消息的组件和另一个用来订阅消息的组件。
// App.vue
<template>
<div id="app">
<PublishingComponent />
<SubscribingComponent />
</div>
</template>
<script setup>
import PublishingComponent from './components/PublishingComponent.vue';
import SubscribingComponent from './components/SubscribingComponent.vue';
</script>
// components/PublishingComponent.vue
<script setup>
import { ref } from 'vue';
import pubsub from 'pubsub-js';
const message = ref('Hello from publisher!');
const sendMessage = () => {
pubsub.publish('my-channel', message.value);
};
</script>
<template>
<button @click="sendMessage">Send Message</button>
</template>
// components/SubscribingComponent.vue
<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
import pubsub from 'pubsub-js';
let subscription;
onMounted(() => {
subscription = pubsub.subscribe('my-channel', (msg, data) => {
console.log(`Received message: ${msg}, with data:`, data);
});
});
onBeforeUnmount(() => {
if (subscription) {
pubsub.unsubscribe(subscription);
}
});
</script>
<template>
<!-- No template needed for this component as it only listens to messages -->
</template>
运行您的Vue应用程序,并点击 PublishingComponent
中的按钮,SubscribingComponent
应该会在控制台打印出接收到的消息。这个示例演示了如何在Vue 3组件中使用 PubSub-js 进行消息的发布和订阅。
分享
重写
关于vue3的 消息订阅与发表pubsub-js,有没有官方推荐的写法
在 Vue 3 中使用 PubSub-js 有哪些最佳实践
PubSub-js 在移动端有什么特别的使用场景吗
文章评论