Vue组件通信(三)——路由传参和Teleport

1,605 阅读3分钟

前面两篇文章讲解了组件通讯的几种方法如props、$emit、v-model和事件总线等方法实现各种情况下组件的通信。

Vue组件通讯(一) - 掘金 (juejin.cn)

Vue组件通信(二) - 掘金 (juejin.cn)

感兴趣可以去看一看,这篇准备在讲一下路由传参和Teleport这两种组件通信的方法

路由传参

对于路由传参它这里有两种方法来传递参数,分别是query传参params传参,接下来来分别说一说这两种方法。

query传参

这种方式类似于普通的 URL 查询字符串参数。当你导航到一个新的路由时,可以在 URL 的末尾附加查询字符串,在目标组件中,你可以通过 $route.query 来访问这些参数。还是拿到我们前面举的例子来做示例。

开局肯定还是要安装vue router然后配置路由:

import { createRouter, createWebHistory } from "vue-router";
import Home from "@/views/Home.vue";
import About from "@/views/About.vue";
const routes = [
    {
        path: "/",
        name: "home",
        component: Home
    },{
        path: "/about",
        name: "about",
        component: About,
        props: true
    }]
const router = createRouter({
    history: createWebHistory(),
    routes
})
export default router;

这是常规操作,然后这里配置了两个组件那么我们也得来创建两个组件,代码分别为:

<template>
    <div class="header">
        <input type="text" v-model="newMsg">
        <button @click="add">确定</button>
    </div>
</template>

<script setup>
import { reactive, ref } from 'vue';
import { useRouter } from 'vue-router';

const router = useRouter();
const newMsg = ref('');
const query = reactive({});

const add = () => {
    query.name = newMsg.value;
    router.push({ 
        path: '/about',
        query: query 
    });
};
</script>
<template>
    <div>
        <p>输入的内容: {{ $route.query.name }}</p>
    </div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>

这里注意,如果像这样需要在组件之间传递数据,并希望目标组件能够响应数据变化,我们应该使用reactive来创建query对象。即使query是一个普通对象,也可以直接传递给router.push,但使用reactive确保了数据的响应式特性,使得目标组件能够自动更新。

parmas传参

params传参是一种通过路由路径本身来传递参数的方法。与query传参(通过URL查询字符串)不同,params传参是在路由路径中定义动态段,并在导航时填充这些动态段。这种方法大致使用方法与query差不多但需要修改一点地方。

在配置router文件中path修改为

path: '/about/:name'

另外两个组件修改为:

<template>
    <div class="header">
        <input type="text" v-model="newMsg">
        <button @click="add">确定</button>
    </div>
</template>
<script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const newMsg = ref('');
const add = () => {
    router.push({ 
        name: 'about', // 这里使用了命名路由
        params: { name: newMsg.value } // 使用params传递参数
    });
};
</script>
<template>
    <div>
        <p>输入的内容: {{ $route.params.name }}</p>
    </div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.name);
</script>

这里的关键点是path中的:name,它指定了一个动态段,表示这部分路径可以变化,并且会被解析为params对象的name属性。

关于这两种方法都有各自的使用场景下面总结一下:

  • 如果你的参数是为了标识唯一的资源或页面,比如一个用户的具体资料页面,使用params传参会更合适,因为这使得URL更具有可读性和语义性。
  • 如果你的参数是用于筛选、排序或携带状态信息,比如分页信息或搜索条件,使用query传参会更合适,因为它们可以灵活地添加和更改,同时也方便用户复制链接进行分享。

Teleport

Teleport在Vue 3中是一种特殊的组件,它允许你将一个组件的渲染结果“传送”到DOM树中的另一个位置,而不影响组件自身的逻辑和数据流。这种方法很适合我们写登录弹窗像我们使用的这个掘金的登陆弹窗一样。

首先我们得在index.html中定义目标文件

在HTML中定义一个目标位置,可以是任何有效的DOM节点,例如:

<div id="teleport-target"></div>

然后在App.vue中我们就可以使用了

<template>
  <div>
    <h1>主应用</h1>
    <button @click="showModal = true">显示模态对话框</button>
    <!-- 使用Teleport组件 -->
    <teleport to="#teleport-target">
      <div v-if="showModal" class="modal">
        <p>这是一个模态对话框</p>
        <button @click="showModal = false">关闭</button>
      </div>
    </teleport>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      showModal: false,
    };
  },
};
</script>

<style>
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: white;
  padding: 20px;
  border: 1px solid #ccc;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>

效果如下:

ezgif-1-b74713de62.gif

<Teleport> 接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。这段代码的作用就是告诉 Vue“把以下模板片段传送到 teleport-target 标签下”。并且我们在使用这个组件时有几个注意的点:

  1. 目标元素必须存在
  2. 目标元素应具有唯一的 ID
  3. 避免在父组件中添加样式
  4. 注意事件绑定
  5. 确保样式一致性

总结

这篇文章总结了如何在 Vue 3 中通过路由传参(包括 queryparams 传参)和 Teleport 组件来实现灵活的组件通信和内容渲染。我们探讨了 query 传参适用于动态数据和状态信息,而 params 传参则用于标识唯一资源。 Teleport 组件则允许将组件内容传送到 DOM 树中的任意位置,以便于处理如模态对话框等全局渲染的需求。这些技术能够有效提升应用的功能性和用户体验。