软件教程 2025年08月6日
0 收藏 0 点赞 370 浏览 7337 个字
摘要 :

文章目录 父组件传子组件【props】 子组件传父组件【$emit】 父组件直接访问子组件【ref + $refs】 子组件直接访问父组件【$parent】 跨级通信【provide + inject】 动……




  • 组件传子组件【props】
  • 子组件传父组件【$emit】
  • 父组件直接访问子组件【ref + $refs】
  • 子组件直接访问父组件【$parent】
  • 跨级通信【provide + inject】
  • 动态组件【component + is】
  • 异步组件 【defineAsyncComponent】
  • v-model使用在组件上

本文主要讲解关于vue如何实现父子组件通信相关内容,包括父组件传值给子组件,子组件传值给父组件,父组件直接访问子组件、子组件直接访问父组件、跨级通信、动态组件和异步组件之间的通信,每个主题都结合详细的代码案例来深入讲解,更容易理解与掌握。让我们来一起学习下吧!

父组件传子组件【props】

  • props 遵循着单向绑定原则
    • 每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,
  • 子组件不能修改父组件传递过来的数据,若是子组件修改了,控制台会抛出警告
// 父组件
<comp-child mytitle=\"标题11111\" :isShowLogo=\"true\" />
<comp-child mytitle=\"标题222222\" />

// 子组件
<template>
  <header>
    <div v-if=\"isShowLogo\">logo</div>
    <<h2>{{ mytitle }}</h2>
  </header>
</template>

<script>
export default {
  // 子组件接收父组件传递的内容用:props
  // props: [\"mytitle\", \"isShowLogo\"],

  // 防止父组件传入的属性类型不对,使用props的type属性
  props: {
    mytitle: {
      type: String,
    },
    isShowLogo: {
      type: Boolean,
      default: false, // 设置默认值
      // required: true, // 必须传值
    },
  },
};
</script>

子组件传父组件【$emit】

  • 父组件通过v-on事件(简写@事件)来监听子组件中的传值
  • 子组件通过$emit触发事件,并传值
  • 例:
    • 父组件:@myevent=”事件处理函数”
    • 子组件:this.$emit(“myevent”,”传递的值”)
    • 【注】子组件中监听的事件名称 == 父组件中v-on绑定的事件

父组件

  • 组件监听子组件,方法不加(),默认会传一个事件对象e
  • 事件对象e就是子组件传递过来的值
<template>
  <!-- 父组件监听子组件,方法不加(),默认会传一个事件对象e -->
  <comp-childMenu @myevent=\"changeEvent\" />
  <ul v-if=\"isShow\">
    <li v-for=\"data in list\" :key=\"data\">
      {{ data }}
    </li>
  </ul>
</template>

<script>
import compChildMenu from \"./comp-childMenu.vue\";
export default {
  data() {
    return {
      list: [\"首页\", \"用户管理\", \"商品管理\", \"订单管理\"],
      isShow: true,
    };
  },
  components: {
    compChildMenu,
  },
  methods: {
    changeEvent(e) {
      this.isShow = !this.isShow;
      console.log(\"父组件\", e);
    },
  },
};
</script>

<style>
* {padding: 0px;margin: 0px;}
ul,li {list-style: none;}
ul {width: 180px;border-right: 1px solid #ccc;}
li {line-height: 50px;border-bottom: 1px solid #ccc;text-align: center;}
</style>

子组件代码实现

<template>
  <!-- 父组件监听子组件,方法不加(),默认会传一个事件对象e -->
  <comp-childMenu @myevent=\"changeEvent\" />
  <ul v-if=\"isShow\">
    <li v-for=\"data in list\" :key=\"data\">
      {{ data }}
    </li>
  </ul>
</template>

<script>
import compChildMenu from \"./comp-childMenu.vue\";
export default {
  data() {
    return {
      list: [\"首页\", \"用户管理\", \"商品管理\", \"订单管理\"],
      isShow: true,
    };
  },
  components: {
    compChildMenu,
  },
  methods: {
    changeEvent(e) {
      this.isShow = !this.isShow;
      console.log(\"父组件\", e);
    },
  },
};
</script>

<style>
* {padding: 0px;margin: 0px;}
ul,li {list-style: none;}
ul {width: 180px;border-right: 1px solid #ccc;}
li {line-height: 50px;border-bottom: 1px solid #ccc;text-align: center;}
</style>

效果图

  • 模拟菜单显示隐藏效果

vue如何实现父子组件通信、跨级通信、动态组件和异步组件通信

父组件直接访问子组件【ref + $refs】

  • ref如果绑定在dom节点上,拿到的就是 原生dom节点
  • ref如果绑定在组件上,拿到的就是 组件对象,可以实现通信功能

父组件

  • 步骤:
    1. 在子组件标签上添加ref属性,值为自定义的
    2. 父组件中通过【this.$refs.ref属性名.子组件中的属性名】来获取或修改子组件中的值
      • 【注】this.$refs.ref属性名:获取的是子组件的实例对象(proxy)
<template>
  <compChild title=\"用户名\" type=\"text\" ref=\"username\" />
  <!-- 自定义ref的属性名 -->
  <compChild title=\"密码\" type=\"password\" ref=\"password\" />
  <button @click=\"login()\">登录</button>
  <button @click=\"reset()\">重置</button>
</template>

<script>
import compChild from \"./compChild.vue\";
export default {
  components: {
    compChild,
  },
  methods: {
    login() {
      // 通过$refs获取子组件的值
      // mytext是子组件中双向绑定input框的data状态
      console.log(
        `提交给后端的数据:用户名:${this.$refs.username.mytext};密码:${this.$refs.password.mytext}`
      );
    },
    reset() {
        // 通过$refs直接给子组件赋值
      this.$refs.username.mytext = this.$refs.password.mytext = \"\";
      console.log(\"清空数据成功!\");
    },
  },
};
</script>

<style>
button {padding: 0px 10px;margin: 0px 20px;}
</style>

子组件代码实现

<template>
  <div>
    <label>{{ title }}:</label>
    <input :type=\"type\" v-model=\"mytext\" />
  </div>
</template>
    
<script>
export default {
  props: [\"title\", \"type\"],
  data() {
    return {
      mytext: \"\",
    };
  },
};
</script>

效果图vue如何实现父子组件通信、跨级通信、动态组件和异步组件通信

子组件直接访问父组件【$parent】

  • $parent 子组件直接访问父组件(亲父亲)
  • $root 直接访问根组件

父组件代码实现

<template>
  <compChild />
  <ul v-if=\"isShow\">
    <h2>父组件内列表</h2>
    <li>用户管理</li>
    <li>商品管理</li>
    <li>订单管理</li>
  </ul>
</template>

<script>
import compChild from \"./compChild.vue\";
export default {
  components: {
    compChild,
  },
  data() {
    return {
      isShow: true,
    };
  },
};
</script>

子组件代码实现

<template>
  <div>
    <h3>compChild -- 子组件</h3>
    <button @click=\"clickShow()\">显示 / 隐藏</button>
  </div>
</template>

<script>
export default {
  methods: {
    clickShow() {
      this.$parent.isShow = !this.$parent.isShow; //直接获取到父组件的属性,并修改
    },
  },
};
</script>

<style scoped>
div {background: wheat;padding: 10px;}
</style>

跨级通信【provide + inject】

  • 主组件:使用provide暴露自己
  • 要用主组件的其他组件:要先使用inject接收

主组件代码实现

<template>
  <div class=\"box\">
    <compHeader></compHeader>
    <compNav></compNav>
  </div>
</template>

<script>
import compHeader from \"./compHeader.vue\";
import compNav from \"./compNav.vue\";
export default {
  components: {
    compHeader,
    compNav,
  },
  data() {
    return {
      title: \"首页\",
    };
  },
  provide() {
    return {
      app: this, // 提供数据,this表示当前组件实例对象
    };
  },
};
</script>

<style>
* {padding: 0px;margin: 0px;}
ul,li {list-style: none;}
</style>

组件 – 头部代码实现

<template>
  <!-- 显示数据 -->
  <h2>{{ app.title }}</h2>
</template>

<script>
export default {
  inject: [\"app\"], // 接收父组件传递过来的数据
};
</script>

<style>
h2 {text-align: center;line-height: 80px;  border-bottom: 1px solid #ccc;}
</style>

组件 – 底部导航代码实现

<template>
  <div>
    <ul>
      <li v-for=\"item in nav\" :key=\"item\" @click=\"clickTitle(item)\">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  inject: [\"app\"], // 接收父组件传过来的数据
  data() {
    return {
      nav: [\"首页\", \"影院\", \"资讯\", \"我的\"],
    };
  },
  methods: {
    clickTitle(title) {
      this.app.title = title; // 修改父组件的数据
    },
  },
};
</script>

<style>
ul {display: flex;justify-content: space-around;background: wheat;position: fixed;width: 100%;bottom: -1px;}
li {line-height: 50px;padding: 0px 20px;}
</style>

效果图

  • 单页面切换App

vue如何实现父子组件通信、跨级通信、动态组件和异步组件通信

动态组件【component + is】

  • component 动态组件
  • :is=”组件名” 渲染对应的组件

父组件代码实现

  • 案例是是跨级通信案例的加强版
<template>
  <div class=\"box\">
    <!-- 头部 -->
    <compHeader></compHeader>
    <!-- 内容区 -->
    <component :is=\"obj[title]\"></component>
    <!-- 底部导航 -->
    <compNav></compNav>
  </div>
</template>

<script>
import compHeader from \"./compHeader.vue\";
import compNav from \"./compNav.vue\";
import Home from \"./components/Home.vue\";
import Cinema from \"./components/Cinema.vue\";
import Info from \"./components/Info.vue\";
import Mine from \"./components/Mine.vue\";
export default {
  components: {
    compHeader,  // 头部
    compNav,  // 底部导航
    Home,  // 首页
    Cinema,  // 影院
    Info,  // 资讯
    Mine,  // 我的
  },
  data() {
    return {
      title: \"首页\",
      obj: {
        首页: \"Home\",
        影院: \"Cinema\",
        资讯: \"Info\",
        我的: \"Mine\",
      },
    };
  },
  provide() {
    return {
      app: this, // 提供数据,this表示当前组件实例对象
    };
  },
};
</script>

 

异步组件 【defineAsyncComponent】

  • 在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。
  • Vue 提供了 defineAsyncComponent 方法来实现此功能

简单版代码实现

// 导入异步组件工具
import { defineAsyncComponent } from \"vue\";
// 异步导入组件
AsyncComp: defineAsyncComponent(() => import(\'./Foo.vue\')), 

加载与错误提示(加强版)

  • 这里还需要创建两个组件,加载中(LoadingComponent)和加载失败(ErrorComponent)页面
const AsyncComp = defineAsyncComponent({
  // 加载函数
  loader: () => import(\'./Foo.vue\'),
  
  // 加载异步组件时使用的组件
  loadingComponent: LoadingComponent,
  // 展示加载组件前的延迟时间,默认为 200ms
  delay: 200,

  // 加载失败后展示的组件
  errorComponent: ErrorComponent,
  // 如果提供了一个 timeout 时间限制,并超时了
  // 也会显示这里配置的报错组件,默认值是:Infinity
  timeout: 3000
})

v-model使用在组件上

  • 父组件:
    • 在组件上绑定了v-model,就相当于做了以下两个步骤
      1. 组件上绑定modelValue属性
      2. 组件上绑定update:modelValue事件
  • 子组件:
    1. 获取到父组件传递过来的值 modelValue值
    2. 在修改输入框中的值的时候触发@input事件,然后通过$emit方法将值传递给父组件

父组件代码实现

<template>
  <!-- <Child type=\"text\" v-model=\"username\" /> -->

  <!-- 原理 -->
  <Child :modelValue=\"username\" @update:modelValue=\"(e) => (username = e)\" />
</template>

<script>
import Child from \"./Child.vue\";
export default {
  components: {
    Child,
  },
  data() {
    return {
      username: \"\",
    };
  },
};
</script>

子组件代码实现

<!-- 
<template>
  <input :type=\"type\" @input=\"ChangeInput\" :value=\"modelValue\" />
</template>

<script>
export default {
  props: [\"type\", \"modelValue\"],
  data() {
    return {};
  },
  methods: {
    ChangeInput(e) {
      console.log(e.target.value);
      this.$emit(\"update:modelValue\", e.target.value);
    },
  },
};
</script> 
-->

<!-- 原理 -->
<!-- 
子组件:
  获取到父组件传递过来的值 modelValue值
  在修改输入框中的值的时候触发@input事件,然后通过emit方法将值传递给父组件
 -->
<template>
  <input :type=\"type\" @input=\"ChangeInput\" :value=\"modelValue\" />
</template>

<script>
export default {
  props: [\"type\", \"modelValue\"],
  methods: {
    ChangeInput(e) {
      console.log(e.target.value);
      this.$emit(\"update:modelValue\", e.target.value);
    },
  },
};
</script>

以上就是关于vue如何实现父子组件通信、跨级通信、动态组件和异步组件通信相关的全部内容,希望对你有帮助。欢迎持续关注潘子夜个人博客,学习愉快哦!

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6388.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号