Vue组件与路由精通指南:深入解析组件化开发与路由管理

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Vue组件和路由详解:组件是应用的基石,用于封装可重用代码,可扩展HTML元素。动态组件根据需求切换。父子组件间通过props单向数据流通信,子组件使用`$emit`触发父组件方法。Vue Router提供`router.push`、`.replace`、`.go`等方法管理导航,`$route`对象包含`path`、`params`、`query`等信息。路由钩子如`beforeEach`允许在导航发生时执行逻辑。

@TOC


前言

    本文将深入探讨 Vue 组件的精髓,从组件的定义、动态组件的使用、父子组件的交互与传参等方面展开,帮助读者深入理解 Vue 组件化的设计理念与实现方法。此外,我们还将详细介绍 Vue 路由的常见操作,包括 router.pushrouter.replacerouter.go 等方法的使用,以及路由对象属性 $route.path$route.params$route.query$route.fullPath的含义与应用。


一、Vue组件

1. 组件的定义

组件系统Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树 :
在这里插入图片描述

功能组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。

  • 在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能
  • 在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素
  • 所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子

2. 动态组件的使用

组件名应该始终是多个单词的,根组件 App 除外
    这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的单文件组件的文件名应该要么始终是单词大写开头 (PascalCase),要么始终是 (kebab-case)混用文件命名方式,有的时候会导致大小写不敏感的文件系统的问题,这也是横线连接命名同样完全可取的原因。

使用 kebab-case:
当使用 kebab-case (短横线分隔命名)定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>

Vue.component('my-component-name', {
    
     /* ... */ })

使用 PascalCase:
当使用 PascalCase (驼峰式命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name><MyComponentName> 都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的.

Vue.component('MyComponentName', {
    
     /* ... */ })

组件注册:

//在要展示的页面 导入组件,并注册
     <script>
        import my_comp from './my-comp'

        export default {
    
    
            data(){
    
    
                return{
    
    
                }
            },
            components:{
    
    
                'Mycomp': my_comp
            }
        }
      </script>

      // 在要展示的地方加入下面这行代码
         <Mycopm></Mycopm>

3. 父子组件

父子组件使用

    在vue组件通信中其中最常见通信方式就是父子组件之中的通性,而父子组件的设定方式在不同情况下又各有不同。最常见的就是父组件为控制组件,子组件为视图组件。父组件传递数据给子组件使用,遇到业务逻辑操作时子组件触发父组件的自定义事件

父组件到子组件通讯
   父组件到子组件的通讯主要为:子组件接受使用父组件的数据,这里的数据包括属性和方法(String, Number, Boolean, Object, Array, Function)。vue提倡单项数据流,因此在通常情况下都是==父组件传递数据给子组件使用,子组件触发父组件的事件,并传递给父组件所需要的参数==

父子组件传参

通过 [props]传递数据 (推荐)

    父子通讯中最常见的数据传递方式 就是通过props传递数据,就像方法的传参一样,父组件调用子组件并传入数据,子组件接受到父组件传递的数据进行验证,使用props (可以是数组或对象)用于接收来自父组件的数据。
ps:props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义校验和设置默认值

<!-- 父组件 -->
<template>
    <div>
        <my-child :parentMessage="parentMessage"></my-child>
    </div>
</template>

<script>
    import MyChild from '@components/common/MyChild'

    export default {
    
    
        components: {
    
    
            MyChild
        },
        data() {
    
    
            return {
    
    
                parentMessage: "我是来自父组件的消息"
            }
        }
    }
</script>
<!-- 子组件 -->
<template>
    <div>
        <span>{
  
  { parentMessage }}</span>
    </div>
</template>

<script>
    export default {
    
    
        props: {
    
    
            parentMessage: {
    
    
                type: String,
                default: '默认显示的信息'
                // require: true // 必填
            }
        }
    }
</script>

子父组件传参
    通过 $emit 传递父组件数据 与父组件到子组件通讯中的$on配套使用,可以向父组件中触发的方法传递参数供父组件使用。

<!-- 父组件:一旦触发子组件时,事件child-event就调用parentEvent打印data -->
<template>
  <div>
    <!-- 子组件传递数据给父组件 -->
    <my-child @child-event="parentEvent"></my-child>
  </div>
</template>

<script>
import myChild from "./MyChild.vue";

export default {
    
    
  name: "ParentEl",
  data() {
    
    
    return {
    
    
      msg: "我是父元素的组件",
    };
  },
  components: {
    
    
    myChild,
  },
  methods: {
    
    
    // 父组件方法, data是子组件传递的数据
    parentEvent(data) {
    
    
      console.log(data);
    },
  },
};
</script>
<style lang="scss" scoped></style>
<!-- 子组件:一旦点击按钮,就调用toParent函数,toParent函数发送事件child-event并传递数据"我是子组件传递给父组件的"给父组件 -->
<template>
  <div>
    <!---触发事件给父组件传值 -->
    <button @click="toParent">点击实现传值给父组件</button>
  </div>
</template>

<script>
export default {
   
   
  name: "myChild",
  methods: {
   
   
    toParent() {
   
   
      // 使用$emit传值,this.$emit(事件, 数据)
      // 子组件通过$emit发送一个事件给父组件 (click,change)
      // $emit(参数1, 参数2); 参数1:发送的事件名  参数2:发送的数据
      this.$emit("child-event", "我是子组件传递给父组件的"); 
    },
  },
};
</script>
<style lang="scss" scoped></style>

二、Vue路由

1. 常见路由操作

<router-link>组件支持用户在具有路由功能的应用中单击导航。

  • 通过to属性可以指定目标地址,默认渲染成带有正确链接的<a>标签,通过配置tag属性可以生成别的标签。
  • 另外,当目标路由成功激活时,链接元素会自动设置一个表示激活的css类名。
 <!-- 直接给to指定属性值, 不提倡使用,尽量使用属性绑定 -->
 <router-link to='/goods'>商品</router-link>

 <!-- 使用v-bind 绑定 JS表达式-->
 <router-link :to="'/goods'">商品</router-link>

 <!-- 绑定data中的变量path -->
 <router-link :to='path'>商品</router-link>

 <!-- 绑定对象,自定义网址,携带查询参数 ==> /goods?id=1 -->
 <router-link :to="{
    
    'path':'/goods', query:{
    
    'id':1}}">商品</router-link>

 <!-- 绑定 对象,命名路由,携带params参数 ==> /goods/1 -->
 <router-link :to="{name:'goods', params:{
    
    'id':1}}">商品</router-link>

router.push

routerVueRouter的一个对象,通过Vue.use(VueRouter)VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由,包含了许多关键的对象和属性。

router.push(location): 要导航到不同的URL,则使用router.push方法。该方法会向history栈添加一个新的记录,当用户单击浏览器的后退按钮时,回到之前的URL。
```js
router.push('/goods') // 字符串
router.push({path: '/goods'}) // 对象

// 自定义网址,携带查询参数
router.push({ path: "/goods", query: { id: 1 } }) // -> /goods?id=1

// 命名路由,携带params参数(废弃,详情查看官网)
router.push({ name: "goods", params: { id: 1 } }) // -> /goods/1


### router.replace
>`router.replace(location)`: ***`router.replace`与`router.push`很像,唯一的不同是它不会向`history`栈添加新记录,而是跟它的方法名一样只替换掉当前的history 记录。***`router.replace(...)`等价于`<router-link :to="..." replace>`。
```js
  router.replace('/goods') // 字符串
  router.replace({path: '/goods'}) // 对象

  // 自定义网址,携带查询参数
  router.replace({ path: "/goods", query: { id: 1 } }) // -> /goods?id=1

  // 命名路由,携带params参数(废弃)
  router.replace({ name: "goods", params: { id: 1 } }) // -> /goods/1

router.go

router.go(n): 参数是一个整数,表示在history记录中向前进多少步或向后退多少步

  // 在浏览器记录中前进一步,等同于history.forward()
  router.go(1)
  // 后退一步,等同于history.back()
  router.go(-1)
  // 前进三步
  router.go(3)
  // 如果history记录不够,就会失败
  router.go(-100)
  router.go(100)

2. 路由对象属性

route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query

$route.path

$route.path: 字符串,对应当前路由的路径,总是解析为绝对路径,如"/goods"

var current_url = this.$route.path
console.log(current_url)

$route.params

$route.params: 一个key/value对象, 包含了动态片段和全匹配片段,如果没有路由参数,就为空对象。

var params = this.$route.params
console.log(params)

$route.query

$route.query: 一个key/value对象, 表示URL查询参数。
例如: 对于路径/goods?cate_id=1,则有$route.query.cate_id == 1;如果没有查询参数,则为空对象

var query = this.$route.query
console.log(query)

$route.fullPath

$route.ful1Path: 完成解析后的URL,包含查询参数和hash的完整路径。

var ful1Path = this.$route.ful1Path
console.log(ful1Path)

3. 路由钩子

路由钩子的介绍和案例讲解

全局路由钩子:router.beforeEach 注册一个全局前置守卫

我们可以直接在路由配置文件(/src/main.js)中写钩子函数,但是在路由文件中我们只能写一个。

router.beforeEach((to, from, next) => {
   
   
    //会在任意路由跳转前执行,next一定要记着执行,不然路由不能跳转了
  console.log('beforeEach')
  console.log(to,from)
  //
  next()
})
//
router.afterEach((to, from) => {
   
   
    //会在任意路由跳转后执行
  console.log('afterEach')
})

上述代码中的三个参数:

  • to:路由将要跳转的路径信息,信息是包含在对像里边的。
  • from:路径跳转前的路径信息,也是一个对象的形式。
  • next:路由的控制参数,常用的有next(true)next(false)

写在模板中的钩子函数

在配置文件中的钩子函数,只有一个钩子-beforeEnter,如果我们写在模板中就可以有两个钩子函数可以使用:

  • beforeRouteEnter:在路由进入前的钩子函数。
  • beforeRouteLeave:在路由离开前的钩子函数。
<script>
export default {
   
   
  name: 'params',
  data () {
   
   
    return {
   
   
      msg: 'params page'
    }
  },
  beforeRouteEnter:(to,from,next)=>{
   
   
    console.log("准备进入路由模板");
    next();
  },
  beforeRouteLeave: (to, from, next) => {
   
   
    console.log("准备离开路由模板");
    next();
  }
}
</script>

    这是我们写在params.vue模板里的路由钩子函数。它可以监控到路由的进入和路由的离开,也可以轻易的读出to和from的值。


相关文章
|
2月前
|
开发框架 供应链 监控
并行开发模型详解:类型、步骤及其应用解析
在现代研发环境中,企业需要在有限时间内推出高质量的产品,以满足客户不断变化的需求。传统的线性开发模式往往拖慢进度,导致资源浪费和延迟交付。并行开发模型通过允许多个开发阶段同时进行,极大提高了产品开发的效率和响应能力。本文将深入解析并行开发模型,涵盖其类型、步骤及如何通过辅助工具优化团队协作和管理工作流。
62 3
|
1天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
1月前
|
监控 安全 Serverless
"揭秘D2终端大会热点技术:Serverless架构最佳实践全解析,让你的开发效率翻倍,迈向技术新高峰!"
【10月更文挑战第23天】D2终端大会汇聚了众多前沿技术,其中Serverless架构备受瞩目。它让开发者无需关注服务器管理,专注于业务逻辑,提高开发效率。本文介绍了选择合适平台、设计合理函数架构、优化性能及安全监控的最佳实践,助力开发者充分挖掘Serverless潜力,推动技术发展。
58 1
|
1月前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
34 1
|
2月前
|
机器学习/深度学习 安全 搜索推荐
中国CRM市场深度解析:本土化定制开发的领军厂商与未来趋势
国内CRM软件企业正面临日益增长的本土定制需求,这不仅考验服务商的综合水平,也推动了市场的快速发展。本文将深入解析中国CRM市场的现状,探讨领军厂商的优势,并预测未来趋势,包括智能化、集成化、本土化与国际化并行及云服务模式的普及。
|
2月前
|
存储 JavaScript 前端开发
Vue3权限控制全攻略:路由与组件层面的用户角色与权限管理方法深度解析
Vue3权限控制全攻略:路由与组件层面的用户角色与权限管理方法深度解析
141 2
|
21天前
|
开发工具 Android开发 数据安全/隐私保护
探索移动应用的世界:从开发到操作系统的全面解析
【10月更文挑战第33天】在数字化时代,移动应用已成为我们日常生活中不可或缺的一部分。本文将深入探讨移动应用的开发过程,包括编程语言、开发工具和框架的选择,以及如何构建用户友好的界面。同时,我们还将分析移动操作系统的核心功能和安全性,以帮助读者更好地理解这些应用程序是如何在各种设备上运行的。无论你是开发者还是普通用户,这篇文章都将为你揭示移动应用背后的奥秘。
|
26天前
|
机器学习/深度学习 自然语言处理 数据管理
GraphRAG核心组件解析:图结构与检索增强生成
【10月更文挑战第28天】在当今数据科学领域,自然语言处理(NLP)和图数据管理技术的发展日新月异。GraphRAG(Graph Retrieval-Augmented Generation)作为一种结合了图结构和检索增强生成的创新方法,已经在多个应用场景中展现出巨大的潜力。作为一名数据科学家,我对GraphRAG的核心组件进行了深入研究,并在此分享我的理解和实践经验。
50 0
|
28天前
|
机器学习/深度学习 Android开发 UED
移动应用与系统:从开发到优化的全面解析
【10月更文挑战第25天】 在数字化时代,移动应用已成为我们生活的重要组成部分。本文将深入探讨移动应用的开发过程、移动操作系统的角色,以及如何对移动应用进行优化以提高用户体验和性能。我们将通过分析具体案例,揭示移动应用成功的关键因素,并提供实用的开发和优化策略。
|
2月前
|
JavaScript
深入解析:JS与Vue中事件委托(事件代理)的高效实现方法
深入解析:JS与Vue中事件委托(事件代理)的高效实现方法
45 0