【Vue2】04 - 组件通信

vue04-组件通信

一:组件通信

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

  • 组件的数据是独立的,无法直接访问其他组件的数据。
  • 想用其他组件的数据 -> 组件通信

组件分类关系

在这里插入图片描述

对于父子关系的组件:props & $emit

对于非父子关系的组件:provide & inject 或者使用 eventbus

通用的解决方式:Vuex -> 适合复杂的业务场景

在这里插入图片描述

1:父子组件通信

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

prop高级认知

在这里插入图片描述

props支持校验

  • 类型校验
props: {
	校验的属性名:类型 // Number, String, Boolean
}

// 例如
props: {
	weight: Number // weight这个属性必须是Number类型的
}
  • 非空校验 & 默认值 & 自定义校验
props: {
    type: Number, // 类型
    required: true, // 是否是必须传递的
    default: 0, // 默认值
    validator (value) {   // 自定义校验,参数是属性的值,然后如果返回true,说明校验成功,否则校验失败
    	if (value >= 0  && value <= 100) {
    		return true;
    	} else {
    		return false;
    	}
    }
}

在这里插入图片描述

2:非父子组件通信

eventbus 事件总线 - 了解

在这里插入图片描述

provide & inject -> 了解

在这里插入图片描述

二:v-model原理

1:语法糖v-model(基本了解)

v-model = :value + @input

  • 数据 -> :value -> 页面
  • 页面 -> @input + $event -> 数据

在这里插入图片描述

2:父子组件的通信-表单类组件封装

在这里插入图片描述

father.vue

  1. 定义数据 -> data() {return }
  2. 通过v-on的方式传递数据给子组件:子组件的属性名称='父组件的属性名称'
  3. 通过事件监听,监听子组件中数据的变化,然后传递给父组件@父事件名称="父组件的属性名称 = $event"
<template>
  <div>
    <!-- :value -> 数据到视图层 -->
    <!-- @change -> 视图层到数据层 -->
    <select :value="cityId" @change="handleChange">
      <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: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      city: ''
    }
  },
  watch: {
    value(val) {
      this.city = val
    }
  },
  methods: {
    handleChange(e) {
      // emit -> 发射
      // 发射事件,告诉father组件,修改的新值
      this.$emit('input', e.target.value)
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

son.vue

  1. export中指定props,完成父组件中的属性 -> 子组件属性的传递(单向流)
  2. 使用数据
  3. 定义监听事件,监听数据的变化@change=事件方法
  4. 定义事件方法,使用this.$emit('父事件名称', e.target.value)发送更改的结果给到父组件
<template>
  <div>
    <!-- :value -> 数据到视图层 -->
    <!-- @change -> 视图层到数据层 -->
    <select :value="cityId" @change="change">
      <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: {
      type: String,
      default: ''
    }
  },
 
  methods: {
    change(e) {
      // emit -> 发射
      // 发射事件,告诉father组件,修改的新值
      this.$emit('changeId', e.target.value)
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

3:父子通信中v-model的优化(重要)

因为v-model是:value + @input,所以在父组件中可以使用v-model进行简写操作

  • 注意在子组件中发射事件的时候,执行父组件的名称是input,同时子组件的属性名称是value
<template>
  <div>
    <!-- :value -> 数据到视图层 -->
    <!-- @change -> 视图层到数据层 -->
    <select :value="value" @change="handleChange">
      <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: {
    value: {
      type: String,
    }
  },
  methods: {
    handleChange(e) {
      // emit -> 发射
      // 发射事件,告诉father组件,修改的新值
      this.$emit('input', e.target.value)
    }
  }
}
</script>

<style lang="scss" scoped>

</style>
<template>
  <div class="son">
    <!-- 传递给子组件, 子组件的参数名是cityId, 对应父组件的参数是selectId -->
    <!-- 监听子组件的changeId事件,并把事件参数赋给selectId -->
    <!-- 因为:value + @input 所以直接用v-model简写 -->
    <Son v-model="selectId"></Son>
  </div>
</template>

<script>

import Son from "@/components/MySon.vue";
export default {
  components: {
    Son
  },
  data() {
    return {
      // 父组件传递给子组件的参数,定义数据
      selectId: '102'
    }
  },
  methods: {

  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

4:总结一下

在这里插入图片描述

三:.sync修饰符和@update

在这里插入图片描述

四:ref & this.$refs

1:获取dom

在这里插入图片描述

在这里插入图片描述

2:获取组件

在这里插入图片描述

五:vue异步更新$nextTick

在这里插入图片描述

<template>
  <div class="test">
    <!-- 是否在编辑状态 -->
    <div v-if="isEdit">
      <!-- ref -> 声明使用本组件的,和后面的this.$refs搭配 -->
      <input ref="inp" v-model="editValue" type="text">
      <button>确认</button>
    </div>
    <div v-else>
      <span>{{ title }}</span>
      <button @click="handlerEdit">编辑</button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'MyButton',
  data() {
    return {
      isEdit: false,
      editValue: '',
      title: "我是一个标题"
    }
  },

  methods: {
    handlerEdit() {
      // 1:显示输入框
      this.isEdit = true
      // 2:让输入框获取焦点
      console.log(this.$refs.inp) // undefined, 因为是异步的,所以需要在nextTick中获取
      // 所以使用Vue异步更新this.$nextTick(() => {xxxx})
      this.$nextTick(() => {
        this.$refs.inp.focus()
      })
    }
  },
}

</script>

<style scoped lang="less">

</style>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值