Vue组件的嵌套关系;父组件传递子组件props;子组件传递给父组件$emit;自定义事件;案例

news2025/2/25 11:31:49

目录

  • 1_Vue组件的嵌套关系
    • 1.1_认识组件的嵌套
    • 1.2_组件的拆分
    • 1.3_组件的通信
  • 2_父组件传递子组件props
    • 2.1_父子组件之间通信的方式
    • 2.2_父组件传递给子组件
    • 2.3_Props的对象用法
  • 3_子组件传递给父组件$emit
  • 4_自定义事件(了解)
  • 5_小案例
  • 6_补充

1_Vue组件的嵌套关系

1.1_认识组件的嵌套

前面将所有的逻辑放到一个App.vue中:

  • 在之前的案例中,只是创建了一个组件App;

  • 如果一个应用程序将所有的逻辑都放在一个组件中,那么这个组件就会变成非常的臃
    肿和难以维护;

  • 所以组件化的核心思想应该是对组件进行拆分,拆分成一个个小的组件;

  • 再将这些组件组合嵌套在一起,最终形成的应用程序;

假如将所有的代码逻辑都放到一个App.vue组件中,会发现

  • 代码是非常的臃肿和难以维护的。

  • 在真实开发中,会有更多的内容和代码逻辑,对于扩展性和可维护性来说都是非
    常差的。

  • 所以,在真实的开发中,会对组件进行拆分,拆分成一个个功能的小组件。


1.2_组件的拆分

在这里插入图片描述

按照如上的拆分方式后,开发对应的逻辑只需要去对应的组件编写就可


1.3_组件的通信

上图的嵌套逻辑如下,它们存在如下关系:

  • App组件是Header、Main、Footer组件的父组件;
  • Main组件是Banner、ProductList组件的父组件;

在开发过程中,会经常遇到需要组件之间相互进行通信:

  • 比如App可能使用了多个Header,每个地方的Header展示的内容不同,那么就需要使用者传递给Header一些数据,让其进行展示;
  • 又比如在Main中一次性请求了Banner数据和ProductList数据,那么就需要传递给它们来进行展示;
  • 也可能是子组件中发生了事件,需要由父组件来完成某些操作,那就需要子组件向父组件传递事件;

总之,在一个Vue项目中,组件之间的通信是非常重要的环节

demo:

App.vue

<template>
  <div class="app">
    <app-header></app-header>
    <app-content></app-content>
    <app-footer></app-footer>
  </div>
</template>

<script>
  import AppHeader from './components/AppHeader.vue'
  import AppContent from './components/AppContent.vue'
  import AppFooter from './components/AppFooter.vue'

  export default {
    // 注册局部组件
    components: {
      AppHeader,
      AppContent,
      AppFooter
    }
  }
</script>

<style scoped>
</style>

文件目录如下

在这里插入图片描述

AppCotent.vue嵌套了AppCotentList.vue

AppContent.vue代码如下

<template>
  <div class="content">
    <div class="banner">banner</div>
      <!-- 使用局部组件 --> 
    <app-content-list></app-content-list>
  </div>
</template>

<script>
  import AppContentList from './AppContentList'
  // 通过注册局部组件,嵌套 AppContentLis
  export default {
    components: {
      AppContentList
    }
  }
</script>

<style scoped>
  .content {
    background-color: blue;
    color: white;
  }
</style>

AppContentList.vue代码如下

<template>
  <ul>
    <li>商品列表1</li>
    <li>商品列表2</li>
    <li>商品列表3</li>
    <li>商品列表4</li>
  </ul>
</template>

<script>
  export default {

  }
</script>

<style scoped>
</style>

2_父组件传递子组件props

2.1_父子组件之间通信的方式

父子组件之间如何进行通信呢?

  • 父组件传递给子组件:通过props属性;
  • 子组件传递给父组件:通过$emit触发事件;

在这里插入图片描述


2.2_父组件传递给子组件

在开发中很常见的就是父子组件之间通信,比如父组件有一些数据,需要子组件来进行展示, 这时可通过props来完成组件之间的通信;

Props ?

  • Props是你可以在组件上注册一些自定义的attribute;
  • 父组件给这些attribute赋值,子组件通过attribute的名称获取到对应的值;

Props有两种常见的用法:

  • 方式一:字符串数组,数组中的字符串就是attribute的名称;
  • 方式二:对象类型,对象类型可以在指定attribute名称的同时,指定它需要传递的类型、是否是必须的、默认值等等;

Props的数组用法

如下图所示。但是一般不用数组

在这里插入图片描述


2.3_Props的对象用法

.props数组语法的弊端: 不能对类型进行验证 ;没有默认值的。

而对象的写法可以让的props变得更加完善。

当使用对象语法的时候,可以对传入的内容限制更多:

  • 比如指定传入的attribute的类型;
  • 比如指定传入的attribute是否是必传的;
  • 比如指定没有传入时,attribute的默认值;
    props: {
    //props: ["name","message"]  原来数组的写法
      name: {
        type: String,
        required:true,
        default: "我是默认name"
      },
      age: {
        type: Number,
        required: true,
        default: 0
      }
    }  

type的类型有哪些?

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

对象类型的其他写法

在这里插入图片描述


Prop 的大小写命名

HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符;

也就是说,当使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名;


非Prop的Attribute

什么是非Prop的Attribute呢?

  • 当传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits时,就称之为 非Prop的Attribute;
  • 常见的包括class、style、id属性等;

Attribute继承:- 当组件有单个根节点时,非Prop的Attribute将自动添加到根节点的Attribute中:


禁用Attribute继承和多根节点

如果不希望组件的根元素继承attribute,可以在组件中设置 inheritAttrs: false

  • 禁用attribute继承的常见情况是需要将attribute应用于根元素之外的其他元素;
  • 可以通过 $attrs来访问所有的 非props的attribute;

在这里插入图片描述

多个根节点的attribute: 多个根节点的attribute如果没有显示的绑定,那么会报警告,必须手动的指定要绑定到哪一个属性上:

在这里插入图片描述


3_子组件传递给父组件$emit

什么情况下子组件需要传递内容到父组件呢?

  • 当子组件有一些事件发生的时候,比如在组件中发生了点击,父组件需要切换内容;
  • 子组件有一些内容想要传递给父组件的时候;

如何完成子传父呢?

  • 首先,需要在子组件中定义好在某些情况下触发的事件名称;
  • 其次,在父组件中以v-on的方式传入要监听的事件名称,并且绑定到对应的方法中;
  • 最后,在子组件中发生某个事件的时候,根据事件名称触发对应的事件;

demo:

子组件AddCounter.vue

<template>
  <div class="add">
    <button @click="btnClick(1)">+1</button>
    <button @click="btnClick(5)">+5</button>
    <button @click="btnClick(10)">+10</button>
  </div>
</template>

<script>
  export default {
    // 1.emits数组语法
    emits: ["add"],
    // 2.emmits对象语法> 
    // emits: {
    //   add: function(count) {  //验证参数
    //     if (count <= 10) {
    //       return true
    //     }
    //     return false
    //   }
    // },
    methods: {
      btnClick(count) {
        console.log("btnClick:", count)
        // 让子组件发出去一个自定义事件
        // 第一个参数自定义的事件名称
        // 第二个参数是传递的参数
        this.$emit("add", 100)
      }
    }
  }
</script>

<style scoped>
</style>

父组件App.vue

<template>
  <div class="app">
    <h2>当前计数: {{ counter }}</h2>

    <!-- 1.自定义add-counter, 并且监听内部的add事件 -->
    <add-counter @add="addBtnClick"></add-counter>

    <!-- 2.自定义sub-counter, 并且监听内部的sub事件 -->
    <sub-counter @sub="subBtnClick"></sub-counter>
  </div>
</template>

<script>
  import AddCounter from './AddCounter.vue'
  import SubCounter from './SubCounter.vue'

  export default {
    components: {
      AddCounter,
      SubCounter
    },
    data() {
      return {
        counter: 0
      }
    },
    methods: {
      addBtnClick(count) {
        this.counter += count
      },
      subBtnClick(count) {
        this.counter -= count
      }
    }
  }
</script>

<style scoped>
</style>

4_自定义事件(了解)

比如,封装一个CounterOperation.vue的组件, 内部其实是监听两个按钮的点击,点击之后通过 this.$emit的方式发出去事件;

在这里插入图片描述


自定义事件的参数和验证

自定义事件的时候,可以传递一些参数给父组件。

increnmentTen(){
  this.$emit("addTen",10)
}

在vue3当中,还可以对传递的参数进行验证。

emits:{
   addOne: null,
   subOne: null,
   addTen: function( payload ){
       if( payload === 10){
    	return true;
       }
       return false
  }
}

5_小案例

在这里插入图片描述

App.vue代码

<template>
  <div class="app">
    <!-- 1.tab-control -->
    <tab-control :titles="['衣服', '鞋子', '裤子']" 
                 @tab-item-click="tabItemClick"/>
    <!-- 2.展示内容 -->
    <h1>{{ pageContents[currentIndex] }}</h1>
  </div>
</template>

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

  export default {
    components: {
      TabControl
    },
    data() {
      return {
        pageContents: [ "衣服列表", "鞋子列表", "裤子列表" ],
        currentIndex: 0
      }
    },
    methods: {
      tabItemClick(index) {
        console.log("app:", index)
        this.currentIndex = index
      }
    }
  }
</script>

<style scoped>
</style>

TabControl.vue

<template>
  <div class="tab-control">
    <template v-for="(item, index) in titles" :key="item">
      <div class="tab-control-item"
           :class="{ active: index === currentIndex }"
           @click="itemClick(index)">
        <span>{{ item }}</span>
      </div>
    </template>
  </div>
</template>

<script>
  export default {
    // 父组件传子组件。
    props: {
      titles: {
        type: Array,
        default: () => []
      }
    },
    data() {
      return {
        currentIndex: 0
      }
    },
    // 子组件传递给父组件。事件参数传递
    emits: ["tabItemClick"],
    methods: {
      itemClick(index) {
        this.currentIndex = index
        this.$emit("tabItemClick", index)
      }
    }
  }
</script>

<style scoped>
  .tab-control {
    display: flex;
    height: 44px;
    line-height: 44px;
    text-align: center;
  }

  .tab-control-item {
    flex: 1;
  }

  .tab-control-item.active {
    color: red;
    font-weight: 700;
  }

  .tab-control-item.active span {
    border-bottom: 3px solid red;
    padding: 8px;
  }
</style>

6_补充

css的scoped :当 <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。

用npm init vue@latest创建项目时,使用vite打包

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java 11 新特效解读(2)

目录 全新的HTTP 客户端API 更简化的编译运行程序 废弃Nashorn引擎 ZGC 优势&#xff1a; ZGC的设计目标是&#xff1a; 在当前JDK中看不到什么&#xff1f; 一个标准化和轻量级的JSON API 新的货币API 展望 全新的HTTP 客户端API HTTP&#xff0c;用于传输网页的…

C++实现俄罗斯方块(源码+详解)

&#x1f442; Take me Hand Acoustic - Ccile Corbel - 单曲 - 网易云音乐 源码Debug工具 &#xff08;1&#xff09;cppreference.com &#xff08;主&#xff09; &#xff08;2&#xff09;必应 (bing.com) &#xff08;3&#xff09;GPT&#xff08;主&#xff09; &#…

Java多线程(3)---锁策略、CAS和JUC

目录 前言 一.锁策略 1.1乐观锁和悲观锁 ⭐ 两者的概念 ⭐实现方法 1.2读写锁 ⭐概念 ⭐实现方法 1.3重量级锁和轻量级锁 1.4自旋锁和挂起等待锁 ⭐概念 ⭐代码实现 1.5公平锁和非公平锁 1.6可重入锁和不可重入锁 二.CAS 2.1为什么需要CAS 2.2CAS是什么 ⭐CAS…

那些年的golang开发经验记录

goland 问题CreateProcess error216, 该版本的 %1 与你运行的 Windows 版本不兼容。请查看计算机的系统信息&#xff0c;然后联系软件发布者 Cannot run program "......" (in directory "D:\project\go\awesomeProject\src\test"): CreateProcess error2…

c语言内存管理

1、局部变量&静态局部变量 1、局部变量 a、作用域&#xff1a;在定义变量的{}之内有效 b、声明周期&#xff1a;程序运行至变量定义处开辟内存空间&#xff0c;所在函数运行结束之后释放空间 c、未初始化的变量值&#xff1a;随机 2、静态局部变量 a、作用域&#xff1…

AI人工智能简史

最近学习AI&#xff0c;顺便整理了一份AI人工智能简史&#xff0c;大家参考&#xff1a; 1951年 第一台神经网络机&#xff0c;称为SNARC&#xff1b;1956年 达特茅斯学院会议&#xff0c;正式确立了人工智能的研究领域&#xff1b;1966年 MIT发明ELIZA人机心理治疗对话程序&a…

Python测试框架pytest:常用参数、查找子集、参数化、跳过

Pytest是一个基于python的测试框架&#xff0c;用于编写和执行测试代码。pytest主要用于API测试&#xff0c;可以编写代码来测试API、数据库、UI等。 pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要有以下几个优点&#xff1a; 简单灵活&#xff0c;容易上手。…

检测ChatGPT生成内容的工具经常误报,怪不得OpenAI停用它

​近日&#xff0c;加利福尼亚大学戴维斯分校的学生被指控使用ChaGPT作弊。他的老师指控他在历史考试中使用了ChatGPT&#xff0c;这一指控得到了某生成式内容检测工具的支持。然而&#xff0c;该名学生坚决否认这一指控&#xff0c;他通过提供在线文档的编辑日志为自己洗清了嫌…

时序预测 | MATLAB实现EEMD-GRU、GRU集合经验模态分解结合门控循环单元时间序列预测对比

时序预测 | MATLAB实现EEMD-GRU、GRU集合经验模态分解结合门控循环单元时间序列预测对比 目录 时序预测 | MATLAB实现EEMD-GRU、GRU集合经验模态分解结合门控循环单元时间序列预测对比效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 1.MATLAB实现EEMD-GRU、GRU时…

vue3多页面配置你一定会遇到的问题,踩坑指南

vue3实现多页面打包容易&#xff0c;关键是如何实现本地的开发和调试&#xff1f;我们接下来解决如下几个问题&#xff1a; 1 多页面项目的项目结构是怎样的&#xff1f; --public--src---App.vue---main.js---page1. ---App.vue---main.js----home.vue----list.vue---page2.…

Hadoop集群部署-完全分布式

文章目录 一、概述二、架构三、部署1. 基础环境配置2. 创建hadoop用户并且生成密钥3. 配置三台服务器免密登录4. Zookeeper安装5. JDK与Hadoop安装6. 配置环境变量7. 启动Zookeeper8. 配置HDFS9. 启动journalnode10. master节点格式化11. 配置YARN12. Hadoop开启Histotryserver…

无涯教程-Perl - lc函数

描述 此函数返回小写版本的EXPR,如果省略EXPR,则返回$_。 语法 以下是此函数的简单语法- lc EXPRlc返回值 此函数返回小写版本的EXPR,如果省略EXPR,则返回$_。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl$orig_string"This is Test and CAPITAL"; …

腾讯云服务器租用价格表_轻量_CVM_GPU(2023更新)

腾讯云服务器租用费用表新鲜出炉2023年更新&#xff0c;轻量应用服务器2核2G4M带宽112元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、云服务器CVM S5实例2核2G配置280.8元一年、GPU服务器GN10Xp实例145元7天&#xff0c;腾讯云服务器网…

黑马程序员Vue全套视频

Vue 2 创建vue实例 示例: <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><script src"https://cdn.jsdelivr.net/npm/vue2.…

全网最全ChatGPT/AIGC报告分析(365份)

本星球整理了365份ChatGPT/AIGC重磅专业报告&#xff08;更新中…&#xff09;&#xff0c;部分目录如下&#xff0c;请读者搜索关键字&#xff0c;获取报告&#xff0c;学习参阅。 https://mp.weixin.qq.com/s/hvI2Hupjx_mnPh3YGyobww 1、计算机研究报告&#xff1a;ChatCPT…

vscode里面报:‘xxx‘ is assigned a value but never used.解决办法

const setCurPage: React.Dispatch<React.SetStateAction<number>> 已声明“setCurPage”&#xff0c;但从未读取其值。ts(6133) setCurPage is assigned a value but never used.eslinttypescript-eslint/no-unused-vars 出现这个报错是eslint导致的&#xff0…

竞赛项目 车位识别车道线检测 - python opencv

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 车位识别车道线检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) …

基于Containerd容器引擎和kubeadm工具部署K8sv1.26.3

kubernetes master节点及node节点各核心组件的功能概述 master节点主要组件概述 master节点主要是k8s的控制节点&#xff0c;在master节点上主要有三个组件必不可少&#xff0c;apiserver、scheduler和controllermanager&#xff1b;etcd是集群的数据库&#xff0c;是非常核心的…

探索美颜SDK技术:实现精准人脸美化的算法与挑战

在现代社交媒体和直播平台的兴起中&#xff0c;美颜技术已成为一种不可或缺的元素&#xff0c;让用户能够在镜头前展现出最佳的自己。这种技术的背后有着复杂而精密的算法&#xff0c;由美颜SDK驱动&#xff0c;以实现精准人脸美化。本文将探讨这些算法的核心原理、应用领域以及…

代码随想录 - 链表

总结概述 链表理论基础 链表是一种通过指针串联的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域一个是指针域&#xff08;存放指向下一个节点的指针&#xff09;&#xff0c;最后一个节点的指针域指向null&#xff08;空指针的意思&#xff09;。 链表的…