vue3中各种灵活传递数据的方式

前言、理解Vue 3的数据流

Vue 3 提供了多种数据传递的方式,让我们的组件之间可以尽情地交流。接下来,我们就直接一个个来看,这些方式都是怎么工作的。

一、Props:从父到子的经典路径

在 Vue 中,子组件可以通过 props 接收父组件传递过来的数据,这可是从父组件到子组件传递数据的老传统了。这就像家长给孩子零花钱一样,孩子只能使用家长给的,不能自己去拿家里的钱。

javascript 复制代码
// 父组件
<template>
  <ChildComponent :message="greeting" />
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';

const greeting = 'Hello!';
</script>

// 子组件
<script setup>
const props = defineProps({
  message: String,
});
console.log(message); // "Hello!"
</script>

<script setup> 使用了 Composition API,它简化了 prop 的访问方式。所以我们不需要通过 props 对象来访问 prop 的值,可以直接将 prop 声明为一个变量,并在模板或逻辑中使用它。

二、Emits:子组件的呼唤

如果���组件需要某些数据时呢,总不能坐等着父组件传递吧。所以接着是Emits,它让子组件能够向上发射信号。通过defineEmits$emit,子组件可以告诉父组件:"我有事情要通知!"

javascript 复制代码
// 父组件
<template>
  <ChildComponent @updateMessage="newGreeting = $event" />
  <p>{{ newGreeting }}</p>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
let newGreeting = '';
</script>

// 子组件
<script setup>
const emit = defineEmits(['updateMessage']);
const updateParent = () => {
  emit('updateMessage', 'Updated from child!');
};
</script>

父组件包含一个子组件实例,并监听子组件发出的 updateMessage 事件。当这个事件被触发时,父组件会更新其内部的 newGreeting 数据属性。

子组件中定义了一个方法 updateParent,当调用这个方法时,它会触发 updateMessage 事件,并传递一个字符串作为参数给父组件。

每当触发 updateMessage 事件,父组件会接收到这个事件并更新 newGreeting 的值,从而在页面上显示更新后的消息。

这里,$event 只是一个约定俗成的变量名,用于在事件处理器中捕获事件对象或者事件传递的数据。通常为了使代码更易于阅读和理解,我们会根据事件数据的实际内容来选择合适的变量名。

三、provide / inject:上下文中的通信

有时候组件会嵌套的比较深,如父组件中有子组件,子组件中有孙组件......当组件层级很深,或者需要跨多个组件共享数据时,provideinject 就派上用场了。它们能让我们在组件树中自由传递数据,而不必层层传递props。这在处理深层次嵌套的组件时非常有用。

xml 复制代码
// 父组件
<script setup>
import { provide } from 'vue';
provide('theme', 'dark');
</script>

// 子孙组件
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
console.log(theme); // "dark"
</script>

在父组件中,我们使用 provide 函数来提供一个名为 'theme' 的键以及对应的值 'dark'。这使得 'theme' 可以被其所有子组件及其子代组件访问。

在子孙组件中,你使用 inject 函数来获取 'theme' 键的值。inject 函数会查找最近的祖先组件中提供的与 'theme' 键相匹配的值。

inject 被调用时,Vue 会沿着组件树向上查找,直到找到一个与注入键匹配的提供者。如果找不到匹配的提供者,inject 将返回 undefined。为了避免这种情况,可以为 inject 提供一个默认值。

ini 复制代码
const theme = inject('theme', 'light'); // 如果没有找到提供者,则使用 'light' 作为默认值

虽然 provide / inject 避免了必须在每一层组件之间传递 props 的繁琐,但过度使用这种方法可能导致组件之间的耦合度增加,使得代码难以追踪和维护,所以建议适当使用。

四、Vuex:全局状态管理的专家

既然 provide / inject 不好过度使用,那么现在就讲到 Vuex,它是处理复杂应用中全局状态的理想选择。通过Vuex,我们可以轻松地管理跨组件的状态。

1、安装 Vuex

如果还没有安装 Vuex,就直接 npm。

复制代码
npm install vuex
2、创建 Vuex Store

首先,需要创建一个 Vuex store 文件。

javascript 复制代码
import { createStore } from 'vuex';

export default createStore({
  state: {
    theme: 'light',
  },
  mutations: {
    setTheme(state, theme) {
      state.theme = theme;
    },
  },
  actions: {
    changeTheme({ commit }, theme) {
      commit('setTheme', theme);
    },
  },
  getters: {
    currentTheme(state) {
      return state.theme;
    },
  },
});
  • state 是 store 的数据容器。

  • mutations 是提交到 store 的唯一方式,它们负责修改 state。

  • actions 是异步操作的处理函数,可以包含任意的异步操作逻辑。

  • getters 是 store 的计算属性,用于从 store 中获取状态的派生状态。

3、在主应用文件中使用 Vuex Store

在我们的主应用文件中 main.js 中,引入并使用 Vuex store。

javascript 复制代码
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 Store

直接使用 store 的属性和方法。

xml 复制代码
<template>
  <div :class="theme">
    <!-- 使用 getter -->
    <p>The current theme is {{ currentTheme }}.</p>
    <!-- 使用 action -->
    <button @click="changeTheme('dark')">Switch to dark theme</button>
  </div>
</template>

<script setup>
import { computed, onMounted } from 'vue';
import { useStore } from 'vuex';

const store = useStore();

const theme = computed(() => store.state.theme);
const currentTheme = computed(() => store.getters.currentTheme);

function changeTheme(newTheme) {
  store.dispatch('changeTheme', newTheme);
}

onMounted(() => {
  console.log('Current theme:', store.getters.currentTheme);
});
</script>
  • themecurrentTheme 是使用 computed 创建的响应式引用,分别映射到 store 的状态和 getter。

  • changeTheme 函数使用 store.dispatch 来触发 changeTheme action,参数是新的主题值。

  • onMounted 钩子确保在组件挂载后立即执行,用于检查并记录当前的主题。

当主题在 Vuex store 中发生变化时,由于 themecurrentTheme 的响应式特性,组件会自动更新 UI 以反映新的主题。changeTheme 函数提供了切换主题的功能,可以通过点击按钮来触发主题的改变。

除了 vuex ,还有一个 pinia 和它相似,这里就不介绍了。

结语

到这里,我们一同探索了Vue 3中丰富多彩的数据传递方式,从基础的Props和Emits,到进阶的Provide与Inject,以及全局状态管理的Vuex。每种方法都有其独特的应用场景,就看我们怎么选择了。

相关推荐
Carlos_sam15 分钟前
OpenLayers:ol-wind之渲染风场图全解析
前端·javascript
拾光拾趣录24 分钟前
闭包:从“变量怎么还没死”到写出真正健壮的模块
前端·javascript
拾光拾趣录1 小时前
for..in 和 Object.keys 的区别:从“遍历对象属性的坑”说起
前端·javascript
OpenTiny社区1 小时前
把 SearchBox 塞进项目,搜索转化率怒涨 400%?
前端·vue.js·github
编程猪猪侠1 小时前
Tailwind CSS 自定义工具类与主题配置指南
前端·css
qhd吴飞1 小时前
mybatis 差异更新法
java·前端·mybatis
YGY Webgis糕手之路2 小时前
OpenLayers 快速入门(九)Extent 介绍
前端·经验分享·笔记·vue·web
患得患失9492 小时前
【前端】【vueDevTools】使用 vueDevTools 插件并修改默认打开编辑器
前端·编辑器
ReturnTrue8682 小时前
Vue路由状态持久化方案,优雅实现记住表单历史搜索记录!
前端·vue.js
UncleKyrie2 小时前
一个浏览器插件帮你查看Figma设计稿代码图片和转码
前端