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=>{ })
相关推荐
GUIQU.1 分钟前
【Vue】单元测试(Jest/Vue Test Utils)
前端·vue.js
暮乘白帝过重山17 分钟前
Ollama 在本地分析文件夹中的文件
前端·chrome·ollama
一只小风华~31 分钟前
Web前端开发:CSS Float(浮动)与 Positioning(定位)
前端·css·html·html5·web
前端张三34 分钟前
vue3中ref在js中为什么需要.value才能获取/修改值?
前端·javascript·vue.js
moyu8435 分钟前
前端从后端获取数据的流程与指南
前端
爱的叹息1 小时前
解决 Dart Sass 的旧 JS API 弃用警告 的详细步骤和解决方案
javascript·rust·sass
涛哥码咖1 小时前
Rule.resourceQuery(通过路径参数指定loader匹配规则)
前端·webpack
努力奋斗的小杨1 小时前
学习MySQL的第十二天
数据库·笔记·学习·mysql·navicat
夕水1 小时前
这个提升效率宝藏级工具一定要收藏使用
前端·javascript·trae
会飞的鱼先生2 小时前
vue3 内置组件KeepAlive的使用
前端·javascript·vue.js