4.从零开始学会Vue--{{组件通信}}

1.组件的注意点

1.template只能有一个根元素

约束:.vue文件中的template中如果写了两个元素,则会报如下错误

**解决:**保证template中只有一个根元素即可

2.scoped解决样式冲突

1全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响

2局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件
默认情况 :写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。

**解决:**在组件style标签上增加scoped来解决

scoped原理

1当前组件内标签都被添加data-v-hash值 的属性 ,每个组件的hash值是不同的

2css选择器都被添加 [data-v-hash值 ] 的属性选择器

最终效果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到

3.data必须是一个函数

一个.vue组件的 data 选项必须是一个函数。否则会报错

这么要求的原因: 保证每个组件实例,维护独立的一份数据对象,保证组件实例之间的数据相互隔离不受影响

每次创建新的组件实例,都会新执行一次data 函数,得到一个新对象。

2.组件通信

1.父子之间通信

1.用法

父向子传值步骤:

  1. 准备一个父组件 App.vue,一个子组件Son.vue
  2. 在App.vue中使用Son.vue让它们构成一个父子组件关系,在使用子组件的同时
    1. 通过 :自定义名字="需要传递的值" 将父组件中的数据传给子组件
  1. 子组件内部通过props接收 props:['父组件中自定义名字']
  2. 子组件内部模板中直接使用 props接收的值 {``{ 父组件中自定义名字 }}

✨✨ 注意点:父组件中的响应式数据改变,会自动同步到子组件

子组件利用 $emit 将自己的数据传递给父组件

子向父传值步骤:

  1. $emit触发事件,给父组件发送消息通知
  2. 父组件监听$emit触发的事件
  3. 提供处理函数,在函数的形参中获取传过来的参数

注意:上面代码其实是一个 父子通信的双向数据绑定

2.props校验

**思考:**组件的props数据类型可以乱传吗?不能

  • 比如进度条百分数只能是数字

**props校验:**为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示 → 帮助开发者,快速发现错误

props校验的类型:

  • 类型校验**(常用)**
  • 非空校验
  • 默认值
  • 自定义校验

语法:

① 只校验类型【常用】

② 完整写法

// ✨✨✨注意点:属性的类型必须使用大写 Number,Boolean,String,Array,Object

  1. default和required一般不同时写(因为当时必填项时,肯定是有值的)
  2. default后面如果是简单类型的值,可以直接写默认。如果是复杂类型的值,则需要以函数的形式return一个默认值

3.props与data

**共同点:**一个组件中props和data,都可以给组件提供数据

区别:

  • data 的数据是自己的 → 随便改
  • prop 的数据是外部的 → 不能直接改,要遵循 单向数据流

**单向数据流:**父级props 的数据更新,会向下流动,影响子组件。这个数据流动是单向的

**特点:**子组件修改prop数据不会影响到父组件的数据

**约定:**谁的数据,谁负责修改

2.跨层级通信

1.事件总线-EventBus(传递事件)

**作用:**事件总线event bus可以用在非父子组件之间,进行简易消息传递 (复杂场景→ Vuex)

**需求:**B组件向C组件进行传递数据

使用步骤:(媒婆传话)

  1. 创建一个都能访问到的事件总线 (空 Vue 实例) → utils/EventBus.js
  1. C 组件(接收方),监听 Bus 实例的事件
  1. B 组件(发送方),触发 Bus 实例的事件

2.provide与inject(传递数据)

作用: provide&inject可以实现组件的跨层级共享数据

provide&inject传递数据使用步骤:

  1. 父组件 provide 提供数据
  1. 子/孙组件 inject 取值使用

注意:

  1. provide提供的简单类型的数据不是响应式的,复杂类型数据是响应式。(推荐提供复杂类型数据)
  2. 子/孙组件通过inject获取的数据,不能在自身组件内修改

3.v-model原理

思考: 默认情况下我们可以给组件用上 v-model进行双向数据绑定吗? 不能 -> 那么如何做?

解决方法:

  1. 用vue实现 v-model 的写法(原理)
  2. v-bind:属性.sync 修饰符

1.v-model

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

**作用:**v-model是双向数据绑定

① 数据变,视图跟着变 :value

② 视图变,数据跟着变 @input

说明:event 用于在模板中,获取事件的形参 (这里的event就是事件对象e)

说明:

不同的表单元素, v-model在底层的处理机制不一样。

  • 给文本框,文本域 -> Vue框架底层是拆解成 value属性 + input事件来实现
  • 下拉框 -> Vue框架底层是拆解成 value属性 + change事件来实现
  • 给复选框,单选框 使用v-model ->Vue框架底层是拆解成 checked属性和change事件 来实现
javascript 复制代码
<template>
  <div id="main">
    <input type="text" v-model="value1" />
    {{ value1 }}
    <hr />
    <input type="text" :value="value2" @input="value2 = $event.target.value" />
    {{ value2 }}
    <hr />
    <MyTable v-model="value3"></MyTable>
   
  </div>
</template>

<script>
import MyTable from "./components/MyTable.vue";

export default {
  components: {
    MyTable,
  },
  data() {
    return {
      value1: "",
      value2: "",
      value3: "",
    };
  },
};
</script>

<style>
</style>
javascript 复制代码
<template>
  <div class="box">
    <input type="text" @input="change" />
    {{ value }}
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
    },
  },
  methods: {
    change(e) {
      this.$emit("input", e.target.value);
    },
  },
};
</script>

<style  scoped>
.box {
  width: 200px;
  height: 200px;
  border: 1px solid pink;
}
</style>

2.sync修饰符

**作用:**可以实现 子组件 与 父组件数据 的 双向绑定

.sync修饰符原理: :属性名@update:属性名 的合写

本质上和v-model是一样的,也是一个父子组件通信的情况

3.ref与$refs

**作用:**利用 ref 和 $refs 可以用于 获取 dom 元素, 或 组件实例

**ref和$refs特点:**查找范围 → 当前组件内 (更精确稳定)

语法:

4.Vue异步更新 & $nextTick

Vue的异步更新特性

javascript 复制代码
<template>
  <div class="app">
    <span ref="span">{{ num }}</span>
    <button @click="addone">+1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      num: 1,
    };
  },
  methods: {
    addone() {
      this.num++;
      this.num++;
      console.log(this.num);//打印3
      console.log(this.$refs.span.innerHTML)  //❌还是拿到上一次的值1
    },
  },
};
</script>

<style>
</style>

Vue 在更新 DOM 时是异步执行的(异步渲染)

  • 只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更
  • 如果同一个 watcher 被多次触发,只会被推入到队列中一次。
  • 在下一个的事件循环中(nextTick),Vue 刷新队列并执行实际 (已去重的) 任务(先进先执行)

上面代码中,当num的值改变时,由于dom更新是异步的,所以通过

this.$refs.span.innerHTML拿到的结果是不准确的。

如何解决?使用 $nextTick

$nextTick

**$nextTick:**等 DOM 更新后, 才会触发执行此方法里的函数体

语法:

  1. 回调函数写法: this.$nextTick(()=>{ })
  2. Promise写法: this.$nextTick().then(res=>{ })
相关推荐
阿噜噜小栈8 分钟前
Cursor 无限续杯
经验分享·笔记
customer0824 分钟前
【开源免费】基于SpringBoot+Vue.JS个人博客系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
乐多_L40 分钟前
使用vue3框架vue-next-admin导出表格excel(带图片)
前端·javascript·vue.js
初尘屿风1 小时前
基于微信小程序的电影院订票选座系统的设计与实现,SSM+Vue+毕业论文+开题报告+任务书+指导搭建视频
vue.js·微信小程序·小程序
南望无一1 小时前
React Native 0.70.x如何从本地安卓源码(ReactAndroid)构建
前端·react native
Mike_188702783511 小时前
1688代采下单API接口使用指南:实现商品采集与自动化下单
前端·python·自动化
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS打卡健康评测系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
鲨鱼辣椒️面1 小时前
HTML视口动画
前端·html
一小路一1 小时前
Go Web 开发基础:从入门到实战
服务器·前端·后端·面试·golang
堇舟1 小时前
HTML第一节
前端·html