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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 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的值。


相关文章
|
18天前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
19天前
|
Kubernetes API 调度
Kubernetes 架构解析:理解其核心组件
【8月更文第29天】Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。它提供了一个可移植、可扩展的环境来运行分布式系统。本文将深入探讨 Kubernetes 的架构设计,包括其核心组件如何协同工作以实现这些功能。
38 0
|
7天前
|
开发工具
Flutter-AnimatedWidget组件源码解析
Flutter-AnimatedWidget组件源码解析
|
17天前
|
项目管理 敏捷开发 开发框架
敏捷与瀑布的对决:解析Xamarin项目管理中如何运用敏捷方法提升开发效率并应对市场变化
【8月更文挑战第31天】在数字化时代,项目管理对软件开发至关重要,尤其是在跨平台框架 Xamarin 中。本文《Xamarin 项目管理:敏捷方法的应用》通过对比传统瀑布方法与敏捷方法,揭示敏捷在 Xamarin 项目中的优势。瀑布方法按线性顺序推进,适用于需求固定的小型项目;而敏捷方法如 Scrum 则强调迭代和增量开发,更适合需求多变、竞争激烈的环境。通过详细分析两种方法在 Xamarin 项目中的实际应用,本文展示了敏捷方法如何提高灵活性、适应性和开发效率,使其成为 Xamarin 项目成功的利器。
34 1
|
16天前
|
JavaScript 前端开发 API
探索移动应用的世界:从开发到操作系统的深入解析
【8月更文挑战第31天】本文将带你走进移动应用的世界,从开发到操作系统,深入探讨移动应用的开发过程、移动操作系统的工作原理以及它们之间的交互。我们将通过代码示例,让你更好地理解移动应用的开发和运行机制。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和知识。
|
16天前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
68 0
|
17天前
|
区块链 C# 存储
链动未来:WPF与区块链的创新融合——从智能合约到去中心化应用,全方位解析开发安全可靠DApp的最佳路径
【8月更文挑战第31天】本文以问答形式详细介绍了区块链技术的特点及其在Windows Presentation Foundation(WPF)中的集成方法。通过示例代码展示了如何选择合适的区块链平台、创建智能合约,并在WPF应用中与其交互,实现安全可靠的消息存储和检索功能。希望这能为WPF开发者提供区块链技术应用的参考与灵感。
30 0
|
17天前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
44 0
|
17天前
|
开发者 云计算 数据库
从桌面跃升至云端的华丽转身:深入解析如何运用WinForms与Azure的强大组合,解锁传统应用向现代化分布式系统演变的秘密,实现性能与安全性的双重飞跃——你不可不知的开发新模式
【8月更文挑战第31天】在数字化转型浪潮中,传统桌面应用面临新挑战。本文探讨如何融合Windows Forms(WinForms)与Microsoft Azure,助力应用向云端转型。通过Azure的虚拟机、容器及无服务器计算,可轻松解决性能瓶颈,满足全球用户需求。文中还提供了连接Azure数据库的示例代码,并介绍了集成Azure Storage和Functions的方法。尽管存在安全性、网络延迟及成本等问题,但合理设计架构可有效应对,帮助开发者构建高效可靠的现代应用。
14 0
|
17天前
|
C# Windows 开发者
超越选择焦虑:深入解析WinForms、WPF与UWP——谁才是打造顶级.NET桌面应用的终极利器?从开发效率到视觉享受,全面解读三大框架优劣,助你精准匹配项目需求,构建完美桌面应用生态系统
【8月更文挑战第31天】.NET框架为开发者提供了多种桌面应用开发选项,包括WinForms、WPF和UWP。WinForms简单易用,适合快速开发基本应用;WPF提供强大的UI设计工具和丰富的视觉体验,支持XAML,易于实现复杂布局;UWP专为Windows 10设计,支持多设备,充分利用现代硬件特性。本文通过示例代码详细介绍这三种框架的特点,帮助读者根据项目需求做出明智选择。以下是各框架的简单示例代码,便于理解其基本用法。
55 0

热门文章

最新文章

推荐镜像

更多