vue2 - Day04 - 插槽、路由

插槽、路由

  • 一、插槽(solt)
    • 1.1 概念
    • 1.2 基本用法
    • 1.3 分类
      • 1.3.1 默认插槽(Default Slot)
        • 例子:
      • 1.3.2 具名插槽(Named Slots)
        • 语法:
      • 1.3.3 作用域插槽(Scoped Slots)
        • 例子:
        • 父组件中使用作用域插槽
    • 1.4 插槽的使用场景
  • 二、路由 router
    • 2.1 单页面应用(SPA)
      • Vue2中的SPA特点
      • SPA与MPA(多页面应用)对比
    • 2.2 路由
      • 2.2.1 使用过程
      • 2.2.2 组件.vue 和 页面.vue对比
        • 1. 组件分类概述
        • 2. 推荐的组件目录结构
        • 3. 详细说明
          • a. 页面组件 (Page Components)
          • b. 复用组件 (Reusable Components)
          • c. 路由与页面组件的关系
        • 4. 总结
    • 2.3 路由模块
      • 2.3.1 路由链接与导航
      • 2.3.2 路由参数
        • a.路径参数
        • b.查询参数
        • c.区别
      • 2.3.3 在 Vue Router 中,**路由重定向**、**路由 404 处理** 和 **路由模式** 是常见的功能和配置选项。下面详细介绍这几个概念。
        • 1. 路由重定向(Redirect)
          • 配置重定向
        • 示例:
          • 默认路由重定向
        • 2. 路由 404 处理
          • 配置 404 路由
        • 例如
        • 3. 路由模式
          • 哈希模式(默认模式)
          • 历史模式(HTML5 History API)
          • Nginx服务器配置(历史模式)
        • 总结
    • 2.4 组件缓存 keep-alive
      • 1. Vue.js 中的 `keep-alive` 组件缓存
        • 基本用法:
        • 主要属性:
      • 2. 工作原理
      • 3. 生命周期钩子
        • 示例:
      • 4. 优化性能
      • 5. 与 Vue Router 配合
      • 6. 何时使用:
    • 2.5 数据传递的方式
        • 1. 父子组件间通过 `props` 和 `emit` 传值
          • 示例:多层级的 `props` 传递
        • 2. 使用 Vuex (状态管理) 进行跨页面/组件的数据传递
          • 示例:使用 Vuex 进行状态管理
        • 3. 事件总线(Event Bus)
          • 示例:使用事件总线传递数据
        • 4. 总结

一、插槽(solt)

在 Vue 2 中,插槽(slot) 是一种强大的功能,它允许你在父组件中定义内容并将这些内容传递给子组件的特定位置。插槽的主要目的是让你能够在组件的模板中留出占位符,以便将内容插入到这些占位符的位置。

1.1 概念

插槽是 Vue 组件中一种特性,它提供了一种将父组件的内容传递到子组件的方式。父组件可以通过 <slot></slot> 标签在子组件模板中指定插槽的位置,然后通过在父组件中传递内容来填充这些位置。

1.2 基本用法

假设我们有一个子组件 <Card>,它包含了一个插槽来显示卡片的内容。子组件的代码如下:

<!-- Card.vue -->
<template>
  <div class="card">
    <h3 class="card-title">Card Title</h3>
    <div class="card-content">
      <slot></slot> <!-- 这是默认插槽 -->
    </div>
  </div>
</template>

<script>
export default {
  name: 'Card'
}
</script>

父组件传递内容到子组件时,插槽中的内容会被替换为父组件提供的内容:

<!-- Parent.vue -->
<template>
  <div>
    <Card>
      <p>This is the card content passed from the parent.</p>
    </Card>
  </div>
</template>

<script>
import Card from './Card.vue';

export default {
  name: 'Parent',
  components: {
    Card
  }
}
</script>

1.3 分类

1.3.1 默认插槽(Default Slot)

如上所示,当没有指定插槽名称时,使用的是默认插槽。默认插槽非常简单,父组件传入的任何内容都会插入到子组件中的 <slot></slot> 标签位置。

带有多个插槽的组件 
如果你的组件需要多个插槽,你可以在子组件中定义多个插槽,并通过 `name` 属性来区分它们。
例子:
<!-- Card.vue -->
<template>
  <div class="card">
    <h3 class="card-title">Card Title</h3>
    <div class="card-header">
      <slot name="header"></slot> <!-- 带名字的插槽 -->
    </div>
    <div class="card-body">
      <slot></slot> <!-- 默认插槽 -->
    </div>
  </div>
</template>

父组件传递内容时需要使用 slot 属性来指定插槽的名称:

<!-- Parent.vue -->
<template>
  <div>
    <Card>
      <template v-slot:header>
        <h4>Custom Header</h4>
      </template>
      <p>This is the card content passed from the parent.</p>
    </Card>
  </div>
</template>

1.3.2 具名插槽(Named Slots)

具名插槽是有 name 属性的插槽,可以让你在父组件中插入不同位置的内容。通过 v-slot 语法在父组件中为每个具名插槽指定内容。

语法:
<slot name="slotName"></slot>

父组件中使用具名插槽时,通过 v-slot:slotName 语法来填充具名插槽:

<!-- 父组件 -->
<Card>
  <template v-slot:header>
    <h4>Custom Header</h4>
  </template>
  <template v-slot:footer>
    <p>Footer content</p>
  </template>
  <p>This is the body content.</p>
</Card>

1.3.3 作用域插槽(Scoped Slots)

作用域插槽(scoped slots)是 Vue 2 中提供的一个非常强大的功能,它允许父组件向插槽传递数据,这些数据可以在子组件内部进行处理,并通过作用域插槽的方式传递给父组件使用。

给solt,添加属性方式传递指定的值;

例子:

假设子组件要显示一个列表,并希望父组件根据列表的每一项来决定如何渲染它。

<!-- List.vue -->
<template>
  <div>
    <ul>
      <li v-for="item in items" :key="item.id">
        <slot :item="item">{{ item.name }}</slot> <!-- 作用域插槽 -->
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'List',
  props: {
    items: Array
  }
}
</script>

父组件可以通过作用域插槽来访问传递的数据,并根据数据自定义渲染:

<!-- Parent.vue -->
<template>
  <div>
    <List :items="itemList">
      <template v-slot:default="{ item }">
        <p>{{ item.name }} - {{ item.price }}</p>
      </template>
    </List>
  </div>
</template>

<script>
import List from './List.vue';

export default {
  name: 'Parent',
  components: {
    List
  },
  data() {
    return {
      itemList: [
        { id: 1, name: 'Item 1', price: '10' },
        { id: 2, name: 'Item 2', price: '20' }
      ]
    }
  }
}
</script>

在上面的代码中,item 对象通过作用域插槽传递给父组件,父组件可以自由使用这些数据来进行自定义渲染。

父组件中使用作用域插槽
<template #default="slotProps">
        <!-- slotProps 中包含子组件传递的数据 -->
        <button @click="deleteItem(slotProps.id)">删除 {{ slotProps.name }}</button>
      </template>

在这里插入图片描述

1.4 插槽的使用场景

  1. 自定义组件布局:父组件可以决定子组件的布局细节(例如,卡片的头部、内容和底部)。
  2. 灵活的组件设计:通过插槽,可以让子组件在设计时保持灵活,父组件可以根据不同的需求传递不同的内容。
  3. 提高组件复用性:通过插槽可以提高组件的复用性,不需要重新设计组件,而是通过插槽填充内容。

二、路由 router

Vue Router 是 Vue.js 的官方路由管理器,它允许你在单页面应用(SPA)中管理不同的页面或视图。
通过与 Vue 实例进行绑定来实现路由管理,实现前端的页面跳转、参数传递、嵌套路由等功能。

2.1 单页面应用(SPA)

单页应用程序: Single Page Application
用户访问的所有内容都加载在一个HTML页面中,
只有不同的视图或组件会根据URL变化进行更新,给用户带来更加流畅的交互体验。

单页面应用(SPA) 是一种通过动态加载内容来代替传统页面加载的技术,其特点是页面内容会在不重新加载整个页面的情况下动态更新。

Vue2中的SPA特点

  1. 组件化开发:Vue2中通过组件化来管理应用程序的各个部分。每个视图、模块或者功能通常被封装成一个组件,方便代码的复用和维护。

  2. 虚拟DOM:Vue2使用虚拟DOM来提高性能。每当数据变化时,Vue会先在虚拟DOM中进行比较,从而减少页面重新渲染的次数,提高响应速度。

  3. 路由管理:通过vue-router进行页面的路由管理,vue-router能够实现URL的动态变化,使得单页面应用能够根据用户操作展现不同的内容和视图。

  4. 状态管理:Vue2通常结合Vuex来进行全局状态管理,Vuex通过集中式存储来管理所有组件的状态,避免了在多个组件间直接传递数据的问题。

  5. 异步数据加载:SPA中常常使用Ajax或者Fetch来实现异步数据加载,当用户访问新的视图时,通过API请求加载相应的数据,而不是重新加载整个页面。

SPA与MPA(多页面应用)对比

特性单页面应用(SPA)多页面应用(MPA)
页面加载只有一个HTML页面,动态加载内容每次请求都会加载一个新的HTML页面
路由通过前端路由(如vue-router)控制页面的切换每个页面都有独立的URL,刷新时重新加载
性能初次加载时较慢,但后续交互速度快(无需重载页面)每次页面切换都需要重新加载整个页面
开发模式组件化开发,前端逻辑和视图高度集成页面之间通常是独立开发,前后端分离较多
用户体验流畅的用户体验,没有明显的页面跳转感用户每次点击链接都会看到明显的跳转和页面刷新
SEOSEO需要额外配置(如使用服务端渲染或预渲染)每个页面都有独立的HTML,默认支持SEO
技术栈主要是前端技术(如Vue、React等)通常是前端与后端的完整开发栈(如PHP、Java、ASP.NET等)
开发复杂度对前端开发要求较高,需要处理路由、状态管理等前端和后端开发相对独立,开发难度较低
状态管理通常使用Vuex集中管理状态状态管理通常通过后端处理
维护性由于组件化,较易维护和重用代码由于页面独立,维护较为复杂

2.2 路由

在 Vue 中,路由(vue-router)的核心功能是路径(URL)和组件之间的映射关系。通过路由配置,Vue 可以根据浏览器的 URL 路径,动态加载和渲染不同的组件,从而实现单页面应用(SPA)的页面切换。

2.2.1 使用过程

  • (1)安装 VueRouter模块
    npm install vue-router

  • (2)引入并注册使用

import VueRouter from 'vue-router'
Vue.use(VueRouter)
  • (3)配置路由

路由的核心是将 URL 路径映射到组件上。我们通过创建一个路由表(routes)来实现这个映射。

// 配置路由
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

// 创建路由实例
const router = new VueRouter({
  routes // 等价于 routes: routes
})
  • (4)在 Vue 实例中使用路由
new Vue({
  el: '#app',
  router, // 注入路由
  render: h => h(App)
})

在 App.vue 中,我们通常使用 <router-view></router-view> 标签来显示匹配到的组件:

<template>
  <div id="app">
    <h1>Vue Router 示例</h1>
    <nav>
      <router-link to="/">首页</router-link>
      <router-link to="/about">关于</router-link>
    </nav>
    <router-view></router-view> <!-- 渲染匹配的路由组件 -->
  </div>
</template>
  • (5)路由链接与导航
    router-link:用于生成页面跳转的链接,它自动处理<a>标签的行为,支持 to 属性来定义跳转的路径。
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>

router-view:这是路由占位符,用于显示当前匹配的组件。

2.2.2 组件.vue 和 页面.vue对比

1. 组件分类概述
  • 页面组件(Page Components):这些组件通常直接对应一个页面或视图,负责处理整个页面的内容和布局。它们通常较大,包含多个子组件,并且与路由路径密切相关。
  • 复用组件(Reusable Components):这些组件通常是可复用的、较小的 UI 组件,提供特定的功能或视觉展示。例如,按钮、卡片、列表等组件,它们通常不直接与路由相关,而是可以在多个页面组件中重复使用。
2. 推荐的组件目录结构

为了清晰地管理和维护组件,通常会按页面组件和复用组件将 .vue 文件放置在不同的目录下。

src/
├── assets/                   # 静态资源(图片、字体等)
├── components/               # 复用组件(UI 组件)
│   ├── Button.vue            # 按钮组件
│   ├── Card.vue              # 卡片组件
│   └── Modal.vue             # 弹窗组件
├── views/                    # 页面组件(每个视图对应一个路由)
│   ├── Home.vue              # 首页组件
│   ├── About.vue             # 关于页面组件
│   └── Profile.vue           # 个人资料页面组件
├── router/                   # 路由配置
│   └── index.js              # 路由定义
└── App.vue                   # 根组件
3. 详细说明
a. 页面组件 (Page Components)

页面组件通常是与特定路由路径直接相关的 Vue 组件,代表单个页面。它们可能由多个复用组件组成,主要功能是呈现和管理页面的布局、数据、交互等。

  • 路径映射:页面组件通常对应一个路由路径,例如 /home/about 等。
  • 大小:页面组件通常较大,因为它们包含了多个子组件,负责协调页面内不同部分的内容和交互。
  • 文件位置:页面组件放置在 src/views/ 目录下,这个目录通常包含了项目中的所有页面。
// src/views/Home.vue
<template>
  <div>
    <h1>Welcome to Home Page</h1>
    <MyCard /> <!-- 引入复用组件 -->
  </div>
</template>

<script>
import MyCard from '@/components/Card.vue'

export default {
  components: {
    MyCard
  }
}
</script>
b. 复用组件 (Reusable Components)

复用组件是小而独立的功能模块,通常用于在多个页面或地方复用。它们应当具有高度的可重用性和较低的耦合度。

  • 功能:复用组件通常处理页面的一部分 UI 展示或特定功能,例如按钮、输入框、卡片、模态框等。
  • 文件位置:这些组件通常放置在 src/components/ 目录下。通过这种方式,它们可以很容易地被不同的页面组件引用。
// src/components/Card.vue
<template>
  <div class="card">
    <h2>{{ title }}</h2>
    <p>{{ description }}</p>
  </div>
</template>

<script>
export default {
  props: {
    title: String,
    description: String
  }
}
</script>

在页面组件中引用复用组件:

// src/views/Home.vue
<template>
  <div>
    <h1>Home Page</h1>
    <Card title="Card Title" description="This is a reusable card" />
  </div>
</template>

<script>
import Card from '@/components/Card.vue'

export default {
  components: {
    Card
  }
}
</script>
c. 路由与页面组件的关系

在 Vue Router 中,页面组件是通过路径与 URL 映射的,因此页面组件通常与路由配置紧密关联。你可以在 router/index.js 文件中定义路由:

// src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'

Vue.use(VueRouter)

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

const router = new VueRouter({
  routes
})

export default router
4. 总结
  • 页面组件:负责页面级别的布局和数据处理,通常对应一个路由,放在 views/ 目录下。
  • 复用组件:小型的、功能独立的组件,能够在多个页面中复用,放在 components/ 目录下,可以根据功能细分为多个子目录。

2.3 路由模块

2.3.1 路由链接与导航

  • router-link:用于生成页面跳转的链接,它自动处理 <a> 标签的行为,支持 to 属性来定义跳转的路径。
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
  • router-view:这是路由占位符,用于显示当前匹配的组件。

router-link-active:这是路由模糊匹配时,router-link 会添加的类名。
router-link-exact-active:这是路由精确匹配时添加的类名。
请添加图片描述

2.3.2 路由参数

路由参数有两种:路径参数查询参数

a.路径参数

路径参数通过 :param 方式在路由路径中指定。例如:

const routes = [
  { path: '/user/:id', component: User }
]

配置导航链接to="/path/参数值"
在组件中,你可以通过 this.$route.params 获取路径参数:

export default {
  computed: {
    userId() {
      return this.$route.params.id
    }
  }
}
  • 路径参数:适用于表示资源的唯一标识符或主要信息。例如,用户的个人页面、文章详情页等。这类信息是页面内容的核心部分,通常是必需的。
  • 示例:to="/user/:id"/product/:productId

在这里插入图片描述

b.查询参数

查询参数使用 URL 的 ? 后跟 key=value 方式传递,例如 /user?id=123.

你可以通过 this.$route.query 来访问查询参数:

this.$route.query.id  // 获取查询参数 id
  • 查询参数:适用于传递不影响路由匹配的额外信息,例如排序、过滤、分页等。这些信息通常不是必需的,而是用来改变页面内容的展示方式。
  • 示例:to="/search?q=vue&page=2"/products?category=electronics&sort=price

在这里插入图片描述

c.区别
  • 路径参数:用于必须的、重要的信息,通常在 URL 中使用 : 来定义,访问时通过 this.$route.params 获取。

  • 查询参数:用于附加的、可选的信息,通常通过 URL 的查询字符串传递,访问时通过 this.$route.query 获取。

特性路径参数查询参数
定义位置路由路径的一部分(通过 : 定义)URL 中的查询字符串(?key=value
必选性通常是必选的可选的
URL 结构更简洁、更语义化(如 /user/123适用于附加额外信息(如 /search?q=vue
参数顺序顺序固定顺序不固定,可以自由组合
访问方式通过 this.$route.params 获取通过 this.$route.query 获取
典型使用场景资源标识(如用户、文章等)过滤、搜索、分页等
影响路由匹配路由匹配时参数必须存在查询参数不会影响路由匹配,只影响组件的渲染

2.3.3 在 Vue Router 中,路由重定向路由 404 处理路由模式 是常见的功能和配置选项。下面详细介绍这几个概念。

1. 路由重定向(Redirect)

路由重定向用于将访问某个路径的请求自动跳转到另一个路径,通常用于处理 URL 改变或某些路径的默认跳转。

配置重定向

你可以通过 redirect 配置选项来实现路由重定向

示例:
  1. 静态重定向(直接指定目标路径)

    // 如果访问 `/home`,自动重定向到 `/`:
    const routes = [
      { path: '/home', redirect: '/' }
    ]
    
  2. 动态重定向(可以根据条件动态决定跳转到哪里)

    const routes = [
      { 
        path: '/old-home', 
        redirect: to => {
          // 可以根据 to 对象中的信息进行动态重定向
          if (to.query.redirectTo) {
            return to.query.redirectTo
          }
          return '/'
        }
      }
    ]
    
默认路由重定向

当用户访问根路径 / 时,通常我们会配置一个默认路由进行重定向:

const routes = [
  { path: '/', redirect: '/home' },
  { path: '/home', component: Home },
  { path: '/about', component: About }
]
2. 路由 404 处理

路由 404 处理是当用户访问一个不存在的路径时,跳转到一个错误页面或者其他合适的页面。通常,这种情况会在所有其他路由之后进行配置。

配置 404 路由

* 是一个通配符路径,表示匹配任何没有明确配置的路径。通常将 404 页面作为路由的最后一个配置项。

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
  // 404 页面路由
  { path: '*', component: NotFound }
]

在上面的例子中,如果用户访问 /unknown-path 这样的路径,路由会自动匹配到 NotFound 页中。

例如

如果项目大型的时候,我们可以给用户一种友好的提示信息告知其在错误等页面中,并随之接下来就是的动态的倒计时告知其倒计时重定向跳转页面
或者 返回首页或热门链接 、搜索功能 、个性化推荐:如果可以追踪用户行为或用户历史

<template>
  <div>
    <h2>页面不存在</h2>
    <p>您访问的页面不存在,请检查网址是否正确。</p>
  </div>
</template>

<script>
export default {
  name: 'NotFound'
}
</script>
3. 路由模式

Vue Router 提供了两种路由模式:哈希模式历史模式

哈希模式(默认模式)

在哈希模式下,URL 的路径会带有一个 # 符号。

http://example.com/#/home

这种模式的优点是兼容性好,特别是对于老旧的浏览器,且不需要服务器的额外配置,因为 # 后面的路径不会发送到服务器。只会在浏览器的前端处理。

在 Vue Router 中,哈希模式是默认模式,不需要特别配置:

const router = new VueRouter({
  routes, // 路由表
  mode: 'hash' // 默认为 hash
})
历史模式(HTML5 History API)

在历史模式下,URL 的路径不会包含 #,而是直接显示路径。

http://example.com/home

这更符合现代网页的表现方式,路径看起来更干净,也便于 SEO。但使用历史模式时,要求服务器进行一些配置,否则刷新页面时会导致 404 错误。

在 Vue Router 中使用历史模式时,需要进行一些配置来确保服务器能够正确处理路径:

const router = new VueRouter({
  routes, // 路由表
  mode: 'history' // 使用 history 模式
})
Nginx服务器配置(历史模式)

当你使用历史模式时,需要确保你的服务器能够处理所有的路径,并将它们指向 index.html,这样 Vue Router 才能接管路由控制。

不配置:为刷新时时通过 nginx 去访问静态资源的,明显这个路径是找不到,因为这个只是前端路由。
问题原因:
前端路由和 Nginx 配置冲突:前端路由(如 /h5/about)是由 JavaScript 控制的,它不会重新加载页面,而是通过浏览器控制路径的变化。
但是当你刷新页面,浏览器向服务器发送了一个 GET 请求,期望从服务器获取 /h5/about 路径的资源。
而如果 Nginx 没有正确配置,它会去文件系统中查找这个路径,结果找不到,导致返回 404 错误。

server {
  location / {
    try_files $uri $uri/ /index.html;
  }
}
总结
  1. 路由重定向:通过 redirect 配置项可以实现路径跳转,支持静态和动态重定向。
  2. 路由 404 处理:使用 * 路径来匹配未定义的路径,通常设置为最后一个路由进行 404 页面跳转。
  3. 路由模式:Vue Router 提供哈希模式和历史模式两种选择。哈希模式使用 # 来保持路径,而历史模式提供更干净的 URL,但需要服务器进行额外配置。

这些配置使得 Vue Router 能够更加灵活地应对各种场景,帮助你更好地管理 SPA 应用的路由。

2.4 组件缓存 keep-alive

keep-alive 是一种常用于 Vue.js 和其他前端框架中的缓存策略,用于在组件之间切换时保持组件的状态,而不是每次切换时重新渲染。

1. Vue.js 中的 keep-alive 组件缓存

在 Vue.js 中,<keep-alive> 组件可以包裹需要缓存的组件。这样,当你切换不同的组件时,被包裹的组件不会被销毁,而是被保留在内存中,避免重新渲染,提升性能。

基本用法:
<template>
  <keep-alive>
    <component :is="currentComponent" />
  </keep-alive>
</template>

<script>
export default {
  data() {
    return {
      currentComponent: 'ComponentA'
    };
  }
};
</script>
主要属性:
  1. include:指定需要缓存的组件(通过正则或数组的方式)。

    <keep-alive :include="['ComponentA', 'ComponentB']">
      <component :is="currentComponent" />
    </keep-alive>
    
  2. exclude:指定不需要缓存的组件。

    <keep-alive :exclude="['ComponentC']">
      <component :is="currentComponent" />
    </keep-alive>
    
  3. max:缓存的最大组件数目,超过后会销毁最早的缓存。

    <keep-alive :max="10">
      <component :is="currentComponent" />
    </keep-alive>
    

2. 工作原理

keep-alive 的工作原理是,在组件被隐藏时,它会保持组件的状态和生命周期。这样,当组件重新显示时,状态能够保留,避免重新加载、重新渲染,提升性能。

  • 缓存:组件在 keep-alive 内部会被缓存,状态不被丢失。
  • 销毁与复用:当组件切换时,Vue 会通过保存其内部状态来复用组件,而不是销毁后重新创建。

3. 生命周期钩子

当组件被缓存时,keep-alive 会触发一些特定的生命周期钩子:

  • activated:组件重新激活时调用。
  • deactivated:组件被缓存时调用(即从视图中移除时)。
示例:
export default {
  data() {
    return {
      isComponentVisible: true,
    };
  },
  activated() {
    console.log('组件被激活');
  },
  deactivated() {
    console.log('组件被缓存');
  },
};

4. 优化性能

keep-alive 常用于以下场景来提升性能:

  • 切换页面时缓存内容:比如在多页面的单页应用(SPA)中,使用 keep-alive 来缓存切换的页面,避免重复加载。
  • 减少不必要的重新渲染:避免组件因切换而重新渲染,从而节省性能开销。

5. 与 Vue Router 配合

在 Vue Router 中,keep-alive 常与路由切换一起使用,缓存切换的路由组件。例如:

<keep-alive>
  <router-view></router-view>
</keep-alive>

结合 Vue Router 的 meta 配置,控制哪些路由组件需要缓存:

const routes = [
  {
    path: '/home',
    component: Home,
    meta: { keepAlive: true }, // 需要缓存
  }
];

const router = new VueRouter({
  routes,
});

6. 何时使用:

注意事项

  • 内存占用keep-alive 会增加内存占用,因为缓存的组件实例会一直保留在内存中。所以需要合理使用,避免不必要的缓存。
  • 状态管理:对于需要缓存的组件,需要注意状态的管理和数据同步,避免旧数据残留。
  • 适用于那些需要在不同状态之间切换的场景,如 tab 切换、页面切换、动态加载组件等。
  • 在需要提高性能,减少不必要的重新渲染时非常有用。

keep-alive 在 Vue.js 中是一种非常有用的缓存策略,可以有效减少组件的重渲染,提升应用性能~ 需要注意的是,keep-alive 只对 Vue 组件有效,对于 HTML 元素或普通的 DOM 元素并不起作用哦~ (๑˃̵ᴗ˂̵)

2.5 数据传递的方式

你提到的场景是:一个页面组件通过传递数据到其他页面组件的复用组件,而这种传值过程确实可能比较繁琐,尤其是当页面层级较深或组件之间的关系复杂时。

在 Vue 中,数据传递的方式主要有两种:

  1. 父子组件间通过 propsemit 传值
  2. 跨组件(无直接父子关系)使用 Vuex 或事件总线(Event Bus)进行数据传递
1. 父子组件间通过 propsemit 传值

当你在一个父页面组件中通过 props 向子组件传递数据时,父组件与子组件的通信是直接的。但问题来了,如果传值需要跨越多个页面或者多个层级,那么中间的每个父组件都需要接收并传递这个数据,这就会导致数据传递过程非常繁琐。

示例:多层级的 props 传递

假设你有一个页面组件 PageA.vue,它需要将数据传递给 PageB.vue 中的 Card.vue 组件。为了实现这个传递,PageA 需要将数据传递给它的子组件(假设是 PageB.vue),而 PageB.vue 又需要将数据传递给它的子组件(假设是 Card.vue):

<!-- PageA.vue -->
<template>
  <div>
    <PageB :data="pageData" />
  </div>
</template>

<script>
import PageB from './PageB.vue'

export default {
  components: {
    PageB
  },
  data() {
    return {
      pageData: 'Hello from PageA'
    }
  }
}
</script>

<!-- PageB.vue -->
<template>
  <div>
    <Card :data="data" />
  </div>
</template>

<script>
import Card from './Card.vue'

export default {
  components: {
    Card
  },
  props: {
    data: String
  }
}
</script>

<!-- Card.vue -->
<template>
  <div>
    <p>{{ data }}</p>
  </div>
</template>

<script>
export default {
  props: {
    data: String
  }
}
</script>

这种方式在页面或组件层级较深时,会导致每个父组件都需要添加 props,并且不断将数据向下传递,导致代码冗长且难以维护。

2. 使用 Vuex (状态管理) 进行跨页面/组件的数据传递

为了解决这类繁琐的问题,Vue 推荐使用 Vuex 来进行全局状态管理,特别是在数据需要在多个页面或组件之间共享时。Vuex 可以将数据存储在一个集中式的 store 中,组件可以直接从 Vuex 中获取或修改数据,而不需要经过一层一层的传递。

示例:使用 Vuex 进行状态管理
  1. 安装并配置 Vuex:

    首先,需要安装并配置 Vuex:

    npm install vuex
    
  2. 创建 Vuex store:

    src/store/index.js 中创建 store:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        pageData: 'Hello from Vuex'
      },
      mutations: {
        updatePageData(state, newData) {
          state.pageData = newData
        }
      },
      actions: {
        updatePageData({ commit }, newData) {
          commit('updatePageData', newData)
        }
      }
    })
    
  3. 在组件中使用 Vuex:

    现在,你可以直接在任何页面组件中使用 Vuex 中的数据,而不需要通过层层的 props 传递。

    • PageA.vue

      <template>
        <div>
          <PageB />
        </div>
      </template>
      
      <script>
      import PageB from './PageB.vue'
      
      export default {
        components: {
          PageB
        }
      }
      </script>
      
    • PageB.vue(从 Vuex 获取数据并传递给复用组件 Card.vue):

      <template>
        <div>
          <Card :data="pageData" />
        </div>
      </template>
      
      <script>
      import { mapState } from 'vuex'
      import Card from './Card.vue'
      
      export default {
        components: {
          Card
        },
        computed: {
          ...mapState(['pageData']) // 直接从 Vuex 获取数据
        }
      }
      </script>
      
    • Card.vue(展示从 Vuex 获取的 data):

      <template>
        <div>
          <p>{{ data }}</p>
        </div>
      </template>
      
      <script>
      export default {
        props: {
          data: String
        }
      }
      </script>
      
  4. 全局共享状态:

    使用 Vuex 后,你可以在任何页面或组件中通过 mapStatethis.$store.state 直接访问或修改 Vuex 中的数据,而无需传递 props。如果你需要修改数据,只需通过 mutationsactions 来进行修改,不必通过层层传递。

3. 事件总线(Event Bus)

虽然 Vuex 是管理全局状态的标准方式,但对于某些场景(例如跨越页面的简单数据传递),也可以使用 事件总线。通过事件总线,可以实现组件间的即时通信,适合在非父子组件间传递数据。

示例:使用事件总线传递数据
  1. 创建事件总线(Event Bus):

    创建一个简单的事件总线,在 src/event-bus.js 文件中:

    import Vue from 'vue'
    export const EventBus = new Vue()
    
  2. 在发送数据的组件中触发事件:

    // 在 PageA.vue 中触发事件
    import { EventBus } from '@/event-bus'
    
    export default {
      mounted() {
        EventBus.$emit('data-from-pageA', 'Hello from PageA')
      }
    }
    
  3. 在接收数据的组件中监听事件:

    // 在 Card.vue 中接收数据
    import { EventBus } from '@/event-bus'
    
    export default {
      data() {
        return {
          receivedData: ''
        }
      },
      created() {
        EventBus.$on('data-from-pageA', (data) => {
          this.receivedData = data
        })
      },
      beforeDestroy() {
        EventBus.$off('data-from-pageA') // 组件销毁时移除监听
      }
    }
    
4. 总结

如果你在 Vue 项目中需要传递数据到其他页面的复用组件,可以选择以下方法:

  • 使用 propsemit 进行父子组件通信:适用于父子组件间的数据传递,但对于层级较深的组件会比较繁琐。
  • 使用 Vuex 管理全局状态:适用于多个组件之间共享数据,不需要一层一层传递。
  • 使用事件总线(Event Bus):适用于跨组件(无直接父子关系)传递简单数据。

对于复杂项目,通常推荐使用 Vuex 来集中管理状态和数据,以减少跨组件传值的复杂性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/945931.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序:定义页面标题,动态设置页面标题,json

1、常规设置页面标题 正常微信小程序中&#xff0c;设置页面标题再json页面中进行设置&#xff0c;例如 {"usingComponents": {},"navigationBarTitleText": "标题","navigationBarBackgroundColor": "#78b7f7","navi…

【数据可视化-10】国防科技大学录取分数线可视化分析

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

Spring Boot教程之四十一:在 Spring Boot 中调用或使用外部 API

如何在 Spring Boot 中调用或使用外部 API&#xff1f; Spring Boot 建立在 Spring 之上&#xff0c;包含 Spring 的所有功能。它现在越来越受到开发人员的青睐&#xff0c;因为它是一个快速的生产就绪环境&#xff0c;使开发人员能够直接专注于逻辑&#xff0c;而不必费力配置…

L25.【LeetCode笔记】 三步问题的四种解法(含矩阵精彩解法!)

目录 1.题目 2.三种常规解法 方法1:递归做 ​编辑 方法2:改用循环做 初写的代码 提交结果 分析 修改后的代码 提交结果 for循环的其他写法 提交结果 方法3:循环数组 提交结果 3.方法4:矩阵 算法 代码实践 1.先计算矩阵n次方 2.后将矩阵n次方嵌入递推式中 提…

面试题解,JVM的运行时数据区

一、请简述JVM运行时数据区的组成结构及各部分作用 总览 从线程持有的权限来看 线程私有区 虚拟机栈 虚拟机栈是一个栈结构&#xff0c;由许多个栈帧组成&#xff0c;一个方法分配一个栈帧&#xff0c;线程每执行一个方法时都会有一个栈帧入栈&#xff0c;方法执行结束后栈帧…

代码随想录算法【Day7】

DAY7 454.四数相加II 特点&#xff1a; 1.只用返回元组的个数&#xff0c;而不用返回具体的元组 2.可以不用去重 暴力思路&#xff1a;遍历&#xff0c;这样时间复杂度会达到O(n^4) 标准思路&#xff1a;用哈希法&#xff08;场景&#xff1a;在一个集合里面判断一个元素…

网络渗透测试实验四:CTF实践

1.实验目的和要求 实验目的:通过对目标靶机的渗透过程,了解CTF竞赛模式,理解CTF涵盖的知识范围,如MISC、PPC、WEB等,通过实践,加强团队协作能力,掌握初步CTF实战能力及信息收集能力。熟悉网络扫描、探测HTTP web服务、目录枚举、提权、图像信息提取、密码破解等相关工具…

[羊城杯 2024]不一样的数据库_2

题目描述&#xff1a; 压缩包6 (1).zip需要解压密码&#xff1a; 尝试用ARCHPR工具爆破一下&#xff1a; &#xff08;字典可自行在github上查找&#xff09; 解压密码为&#xff1a;753951 解压得到13.png和Kee.kdbx文件&#xff1a; 二维码图片看上去只缺了正常的三个角&…

JSON结构快捷转XML结构API集成指南

JSON结构快捷转XML结构API集成指南 引言 在当今的软件开发世界中&#xff0c;数据交换格式的选择对于系统的互操作性和效率至关重要。JSON&#xff08;JavaScript Object Notation&#xff09;和XML&#xff08;eXtensible Markup Language&#xff09;是两种广泛使用的数据表…

小程序租赁系统构建指南与市场机会分析

内容概要 在当今竞争激烈的市场环境中&#xff0c;小程序租赁系统正崭露头角&#xff0c;成为企业转型与创新的重要工具。通过这个系统&#xff0c;商户能够快速推出自己的小程序&#xff0c;无需从头开发&#xff0c;节省了大量时间和资金。让我们来看看这个系统的核心功能吧…

单词统计详解---pyhton

有一个.txt的文本文件&#xff0c;对齐单词进行统计&#xff0c;并显示单词重复做多的10个单词 思路&#xff1a; 1将文本文件进行逐行处理&#xff0c;并进行空格分割处理 2新建一个字典&#xff0c;使用get方法将单词一次添加到字典中&#xff0c;并用sorted方法进行排序。…

如何逐步操作vCenter修改DNS服务器?

在vSphere 7中有一个新功能&#xff0c;它允许管理员更改vCenter Server Appliance的FQDN和IP。因此本文将介绍如何轻松让vCenter修改DNS服务器。 vCenter修改DNS以及修改vCenter IP地址 与在部署 vCenter Server Appliance 后&#xff0c;您可以根据需要修改其 DNS 设置和 IP…

[创业之路-225]:《华为闭环战略管理》-4-华为的商业智慧:在价值链中探索取舍之道与企业边界

目录 一、在价值链中探索取舍之道与企业边界 价值链的深刻洞察 取舍之道&#xff1a;有所为&#xff0c;有所不为 垂直整合与横向整合的平衡 企业边界与活动边界的界定 采购与外包的智慧运用 结语 二、企业外部价值流&#xff1a;上游、中游、下游、终端 上游&#xf…

鸿蒙1.2:第一个应用

1、create Project&#xff0c;选择Empty Activity 2、配置项目 project name 为项目名称&#xff0c;建议使用驼峰型命名 Bundle name 为项目包名 Save location 为保存位置 Module name 为模块名称&#xff0c;即运行时需要选择的模块名称&#xff0c;见下图 查看模块名称&…

python小项目:使用多剪贴板自动回复消息

使用多剪贴板自动回复消息 一、效果展示二、实现步骤2.1 编写python脚本2.2 批处理脚本2.3 运行脚本 三、用到知识3.1 sys.argv3.2 pyperclip3.2.1 主要功能3.2.2 跨平台支持3.2.3 安装方法3.2.4 基本用法3.2.5 高级用法3.2.6 注意事项 一、效果展示 说明&#xff1a;在windows…

Qt监控系统放大招/历经十几年迭代完善/多屏幕辅屏预览/多层级设备树/网络登录和回放

一、前言说明 近期对视频监控系统做了比较大的更新升级&#xff0c;主要就是三点&#xff0c;第一点就是增加了辅屏预览&#xff0c;这个也是好多个客户需要的功能&#xff0c;海康的iVMS-4200客户端就有这个功能&#xff0c;方便在多个屏幕打开不同的视频进行查看&#xff0c…

基于Spring Boot + Vue3实现的在线汽车保养维修预约管理系统源码+文档

前言 基于Spring Boot Vue3实现的在线汽车保养维修预约管理系统是一种前后端分离架构的应用&#xff0c;它结合了Java后端开发框架Spring Boot和现代JavaScript前端框架Vue.js 3.0的优势。这样的系统可以为汽车服务站提供一个高效的平台来管理客户的预约请求 技术选型 系统…

Spring源码下载与测试

引言 下载了Spring源码想阅读阅读&#xff0c;发现用的是Gradle&#xff0c;原来实习的时候公司用的也是Gradle&#xff0c;但不怎么会用&#xff0c;感觉相比于Maven&#xff0c;Gradle更适合非常大型的项目&#xff0c;因为他的jar包下载的是真快 下载 由于Spring6开始就强…

#渗透测试#红蓝攻防#红队打点web服务突破口总结01

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

活动预告 | Microsoft Azure 在线技术公开课:使用 Azure OpenAI 服务构建生成式应用

课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课&#xff0c;掌握创造新机遇所需的技能&#xff0c;加快对 Microsoft Cloud 技术的了解。参加我们举办的“使用 Azure OpenAI 服务构建生成式应用”活动&#xff0c;了解如何使用包括 GPT 在内的强大的…