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

简介: 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的值。


相关文章
|
9月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
775 2
|
8月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
639 137
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
1216 0
|
11月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
790 1
|
11月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
554 0
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
557 2
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
922 140
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1480 29
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
581 4
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

热门文章

最新文章

推荐镜像

更多
  • DNS