Vue2组件通信

本节目标

  • 相关概念
  • 父子通信
  • 非父子通信
  • v-model
  • .sync修饰符
  • ref / $refs
  • $nextTick

相关概念

组件通信就是指组件与组件之间的数据传递

组件的数据是独立的, 无法直接访问其他组件的数据,

想要其他组件的数据, 就要使用组件通信技术

组件关系

总体来说, 组件分为父子关系 和 非父子关系

通信方案

父与子关系: props & $emit (自定义属性/自定义事件)

非父子关系: provide & inject 或者 eventbus (事件总线)

全局方案: Vuex

父子通信

步骤

  1. 通过自定义属性/自定义事件完成父子通信
  2. 父组件给子组件添加自定义属性并传值
  3. 子组件通过props接收数据
  1. 子组件通过$emit触发父组件的自定义事件
  2. 父组件通过事件参数接收数据

prop详解

prop就是组件上注册的一些自定义属性, 作用就是向子组件传递数据, 组件可以传递任意类型和数量的prop

不同的prop写法有不同的特点, 数组写法最简单, 基础写法可以限制数据类型, 完整写法可以有更多限制规则

1,组组写法:

2,基础写法:

3,完整写法

说明:

  1. 自定校验规则是一个函数, 返回true则通过校验, false则未通过
  2. 未通过教研室, 建议通过console.err() 返回原因, 便于排查

单向数据流

  1. 父级prop的数据更新, 会向下流动, 影响子组件, 这个数据流动是单向的
  2. data的数据是自己的, 可以随便改
  3. pop的数据是外部的, 不能直接改, 要遵循单向数据流
  4. 口诀: 谁的数据谁负责

非父子通信

1>兄弟组件通信

eventbus方案可以在非父子组件之间, 进行消息传递, 核心是利用Vue实例的事件机制

步骤

  1. 创建事件总线 (空的Vue实例) (utils/EventBus.js)
  1. A组件(接收方), 监听Bus实例的事件
  1. B组件(发送方), 触发Bus实例的事件

2>子孙组件通信

provide & inject 可以实现跨层级的数据共享

步骤

  1. 父组件通过peovide属性提供数据
  1. 子孙组件通过inject属性获取数据

v-model

v-model本质上是一个语法糖, 例如应用在输入框上, 就是value属性 和 input事件的合写

除了进行表单的双向数据绑定, 也可以实现父子组件通信 (简化表单组件的封装)

1>v-model原理

  1. 实现表单数据双向绑定,

  2. 数据变, 视图跟着变 :value

  3. 视图变, 数据跟着变 @input

  4. 在模版中获取事件对象的形参, 使用$evnet

2>封装表单组件

表单类组件封装, 最直接的方式就是使用父子组件通信技术

  1. 父传子: 数据应该是父组件 props 传递过来的
  2. 子传父: 监听输入, 子组件传值给父组件修改数据
  3. 最终实现了父子组件的数据双向绑定
  4. 右侧为效果图 ->_->

示例

复制代码
<template>
  <div class="app">
    <!--@change可以写行内, 便于理解这里不再简化 -->
    <BaseSelect :cityId="selectId" @change="handleChange"></BaseSelect>
  </div>
</template>

<script>
import BaseSelect from './components/BaseSelect.vue'
export default {
  data() {
    return {
      selectId: '102',
    }
  },
  components: {
    BaseSelect,
  },
  methods: {
    handleChange(e) {
      console.log('父组件拿到子组件选中的值', e);
      this.selectId = e
    }
  }
}
</script>

<template>
  <div>
    <!--这里不能使用v-model, 因为prop是只读的 -->
    <!--@change可以写行内, 便于理解这里不再简化 -->
    <select :value="cityId" @change="hander">
      <option value="101">北京</option>
      <option value="102">上海</option>
      <option value="103">武汉</option>
      <option value="104">广州</option>
      <option value="105">深圳</option>
    </select>
  </div>
</template>

<script>
export default {
  props: {
    cityId: String
  },
  methods: {
    hander(e) {
      console.log('子组件选中的值', e.target.value);
      this.$emit('change', e.target.value)
    }
  }
}
</script>

3>简化表单组件

使用v-model简化表单组件的封装

  1. 改造子组件: props必须使用value接收, 事件触发必须使用input

  2. 简化父组件: 可以使用 v-model 给组件直接绑定数据

  3. 组件的封装步骤不变, 只是子组件的参数命名有了限制, 但是简化了组件的使用, 非常推荐

.sync修饰符

使用**.sync**实现父子组件的双向绑定, 简化代码

  1. 特点: prop属性名, 可以自定义, 非固定value

  2. 场景: 封装弹框类的基础组件, visible属性 true显示 false隐藏

  3. 本质: 就是 :属性名 和 @update:属性名 合写

  4. 对比: 相比如v-model简化代码, .sync简化代码时属性名更灵活

  5. 表单类的组件使用v-model简化, 弹窗类的组件使用.sync简化

ref / $refs

利用ref 和 $refs 可以用于获取DOM元素 或 组件实例

  1. 使用 document.querySelector() 等方法获取DOM, 是在整个HTML页面查找
  2. 使用 $refs 获取DOM, 只在当前组件内查找, 更加精准和稳定
  3. 获取DOM: <div ref="boxRef">我是容器</div>
  4. 获取DOM: this.$refs.BoxRef
  5. 获取组件实例: <sum ref="sumRef"><sum>
  6. 调用组件方法: this.$refs.sumRef.组件方法()
  7. 通过组件实例获取组件数据, 组件的方法要将数据return返回

$nextTick

Vue采用异步更新DOM的方案 (提升性能), 如果要保证本轮DOM更新后, 操作最新的DOM, 使用$nextTick

语法: this.$nextTick(函数体)

相比延时器更加准确可靠

相关推荐
自动化监测Learner5 分钟前
主流 Web 端地图引擎对比:选型指南与优劣分析
javascript
console.log('npc')22 分钟前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
爱学堂IT分享1 小时前
Cesium可视化系统实战课程-Cesium教程学习
前端
糖墨夕2 小时前
理解大语言模型:Agent 的“大脑”
前端·agent
Rain的Java大神之路2 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
cpolar技术支持2 小时前
浏览器也能跑本地 AI:用 Transformers.js + WebGPU 做一个最小推理 Demo,cpolar 给同事远程体验
前端·ai·cpolar·webgpu·transformers.js
计算机毕设定制辅导-无忧学长2 小时前
《基于SpringBoot青年公寓出租管理系统的设计与实现》
java·vue.js·spring boot·青年公寓出租管理系统
计算机魔术师4 小时前
OpenAI 发布 GPT-6 Astra:多项基准刷新纪录, cybersecurity 能力达 Critical 阈值
前端
xy34534 小时前
Axure9.0中继器遮罩实现方法
前端·ui·html·axure·原型·产品设计
风骏时光牛马4 小时前
智能任务自动化协同AI工作流
前端