【VUE】学习笔记(下-组件高级)

声明:本文基于黑马程序员VUE课程学习,文中大量引用了公开资料中的图片及代码,如有侵权请联系本人

1.watch 监听器

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

watch 节点下,定义自己的侦听器:
在这里插入图片描述

1.2 使用 watch 检测用户名是否可用

(axios 发起 Ajax 请求)

在这里插入图片描述
这时候返回的是一个promise对象,我们可以用await去简化,与之对应的该方法前要加上async关键字。
在这里插入图片描述
此时,res返回的就是一个data对象
在这里插入图片描述
{ }解构赋值,赋值出data属性,并通过对解构出的数据进行重命名
在这里插入图片描述
打印值:
在这里插入图片描述

1.3 immediate 选项

默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。
在这里插入图片描述

1.4 deep 选项

当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项
在这里插入图片描述

1.5 监听对象单个属性的变化

在这里插入图片描述

1.6 计算属性 vs 侦听器

计算属性和侦听器侧重的应用场景不同:

  • 计算属性侧重于监听多个值的变化,最终计算并返回一个新值
  • 侦听器侧重于监听单个数据的变化,最终执行特定的业务处理不需要有任何返回值

2. 生命周期

2.1 组件运行的过程

在这里插入图片描述
组件的生命周期指的是:组件从创建 -> 运行(渲染) -> 销毁的整个过程,强调的是一个时间段

vue 框架为组件内置了不同时刻的生命周期函数,生命周期函数会伴随着组件的运行而自动调用,例如

  1. 当组件在内存中被创建完毕之后,会自动调用 created 函数
  2. 当组件被成功的渲染到页面上之后,会自动调用 mounted 函数
  3. 当组件被销毁完毕之后,会自动调用 unmounted 函数

2.2 如何监听组件的更新

当组件的 data 数据更新之后,vue 会自动重新渲染组件的 DOM 结构,从而保证 View 视图展示的数据和Model 数据源保持一致。
当组件被重新渲染完毕之后,会自动调用 updated 生命周期函数。

2.3 组件中主要的生命周期函数

在这里插入图片描述

2.4 组件中全部的生命周期函数

在这里插入图片描述
因为beforeCreate的过程中是无法访问到date() 的,发送ajax申请获取到的数据无法存到date()里供组件渲染或后续使用的。

2.5 完整的生命周期函数

官方介绍:生命周期图示

3.组件之间的数据共享

在项目开发中,组件之间的关系分为如下 3 种:
在这里插入图片描述

  • ① 父子关系 AB AC
  • ② 兄弟关系 BC BE BF BI
  • ③ 后代关系 AD AG AH

3.1 父子之间的数据共享

父子组件之间的数据共享又分为:

  • 父 -> 子共享数据
  • 子 -> 父共享数据
  • 父 <-> 子双向数据同步

3.1.1 父传子 v-bind 和 props

父组件通过 v-bind 属性绑定向子组件共享数据。
同时,子组件需要使用 props 接收数据。
在这里插入图片描述
字符串数组形式列出的 prop:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

但是,通常你希望每个 prop 都有指定的值类型。这时,你可以以对象形式列出 prop,这些属性的名称和值分别是 prop 各自的名称和类型:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object
}

3.1.2 子传父 $emit自定义事件

子组件通过自定义事件的方式向父组件共享数据。
在这里插入图片描述

3.1.3 父子共享 v-model

父组件在使用子组件期间,可以使用 v-model 指令维护组件内外数据的双向同步
在这里插入图片描述

3.2 兄弟组件之间的数据共享 EventBus

兄弟组件之间实现数据共享的方案是 EventBus。可以借助于第三方的包 mitt 来创建 eventBus 对象,从而实现兄弟组件之间的数据共享。
在这里插入图片描述

3.2.1 安装 mitt 依赖包

npm install mitt@2.1.0

3.2.2 创建公共的 EventBus 模块

在这里插入图片描述

3.2.3 在数据接收方自定义事件

数据接收方,调用 bus.on('事件名称', 事件处理函数) 方法注册一个自定义事件
在这里插入图片描述

3.2.4 在数据接发送方触发事件

数据发送方,调用 bus.emit('事件名称', 要发送的数据) 方法触发自定义事件
在这里插入图片描述

3.3 后代组件之间的数据共享 provide 和 inject

后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,可以使用 provideinject 实现后代关系组件之间的数据共享。
在这里插入图片描述
如果两个组件之间没有直接或间接的嵌套关系,则不能使用 provide和inject方法实现数据共享的。比如 B E 就不行

3.3.1 父节点通过 provide 共享数据

父节点的组件可以通过 provide 方法,对其子孙组件共享数据
在这里插入图片描述

3.3.2 子孙节点通过 inject 接收数据

子孙节点可以使用 inject 数组接收父级节点向下共享的数据
在这里插入图片描述
如果还接收一个count 就是

inject:["color","count"],

3.3.3 父节点对外共享响应式的数据

  • 什么是相应式数据?
  • 就是 data 中的数据发生改变,provide return的值也随之改变。

父节点使用 provide 向下共享数据时,可以结合 computed 函数向下共享响应式的数据。注意在一开始导入computed
在这里插入图片描述

3.3.4 子节点使用响应式的数据

如果父级节点共享的是响应式的数据,则子孙节点必须以 .value 的形式进行使用。
在这里插入图片描述

3.4 vuex

vuex 是终极的组件之间的数据共享方案。

在企业级的 vue 项目开发中,vuex 可以让组件之间的数据共享变得高效、清晰、且易于维护
在这里插入图片描述

4. 全局配置 axios

4.1 为什么要全局配置 axios

在实际项目开发中,几乎每个组件中都会用到 axios 发起数据请求。此时会遇到如下两个问题:

  • 每个组件中都需要导入 axios(代码臃肿)
  • 每次发请求都需要填写完整的请求路径(不利于后期的维护)
    在这里插入图片描述

4.2 如何全局配置 axios

首先安装axios

npm install axios -g

main.js 入口文件中,通过 app.config.globalProperties 全局挂载 axios,
在这里插入图片描述

$http 是自定义属性的名称,随便写保持一致即可

在这里插入图片描述

5. ref 引用

5.1 what is ref?

ref 用来辅助开发者在不依赖于 jQuery 的情况下,获取 DOM 元素或组件的引用。
每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的DOM 元素或组件的引用。默认情况下,组件的 $refs 指向一个空对象

5.2 ref 引用 DOM 元素

如果想要使用 ref 引用页面上的 DOM 元素,则可以按照如下的方式进行操作:
在这里插入图片描述

console.log(this.$refs)

打印结果:
在这里插入图片描述

5.3 ref 引用组件实例

如果想要使用 ref 引用页面上的组件实例,则可以按照如下的方式进行操作:
实现功能: 点击父组件的button,重置子组件的counter值。
App 组件

<template>
  <div>
    <h1 ref="myh11">App 根组件</h1>
    <hr />
    <button type="button" class="btn btn-primary" @click="getRefs">获取 $refs 引用</button>
    <my-counter ref="counterRef"></my-counter>
  </div>
</template>

<script>
// 导入组件
import MyCounter from './Counter.vue'

export default {
  name: 'MyApp',
    // 注册组件
  components: {
    MyCounter,
  },
  methods: {
    getRefs() {
      // console.log(this.$refs.counterRef)
      this.$refs.counterRef.reset()
    },
  },
}
</script>

MyCounter组件:

<template>
  <div class="counter-container">
    <h3>Counter 组件 --- {{ count }}</h3>
    <button type="button" class="btn btn-info" @click="count += 1">+1</button>
  </div>
</template>

<script>
export default {
  name: 'MyCounter',
  data() {
    return {
      count: 0,
    }
  },
  methods: {
    reset() {
      this.count = 0
    },
  },
}
</script>

5.4 文本框和按钮的按需切换并让自动获得焦点

## 5.5
这样会报错:Cannot read property 'focus' of undefined
原因:此时ipt 还未定义
DOM 元素的更新是异步的,当赋值inputVisible = true后,会立即执行this.$ref.ipt.focus() ,从而希望拿到 ipt 对象,但是此时DOM还未更新,页面上还只有botton 没有input ,拿不到 ipt 对象的。

5.5 this.$nextTick(cb) 方法

组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行。
通俗的理解是:等组件的DOM 异步地重新渲染完成后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。
在这里插入图片描述

6. 动态组件

动态组件指的是动态切换组件的显示与隐藏。vue 提供了一个内置的 <component> 组件,专门用来实现组件的动态渲染

<component> 是组件的占位符

②	通过 is 属性动态指定要渲染的组件名称

③	<component is="要渲染的组件的名称"></component>

在这里插入图片描述

6.2 保持动态组件的状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组件的状态。
在这里插入图片描述

7. 插槽 Slot

7.1 what is

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

可以把插槽认为是组件封装期间,为用户预留的内容的占位符

7.2 use

7.2.1 基础用法

在封装组件时,可以通过 <slot> 元素定义插槽,从而为用户预留内容占位符。

//定义
<template>
<p>Mycom1的第一个标签</p>
//为用户预留占位符
<slot></slot>
<p>Mycom1的最后一个标签</p>
</template>

//使用
<Mycom1>
//使用组件的时候用户自定义内容
<p>用户自定义的内容</p>
</Mycom1>

7.2.2 没有预留插槽的内容会被丢弃

如果在封装组件时没有预留任何 <slot> 插槽,则用户提供的任何自定义内容都会被丢弃

7.2.3 后备内容

封装组件时,可以为预留的 插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效。

//定义
<template>
<p>Mycom1的第一个标签</p>
//为用户预留占位符 如果用户使用过程中提供插槽内容,则会覆盖后备内容
<slot>这里是后备内容</slot>
<p>Mycom1的最后一个标签</p>
</template>

7.2.4 具名插槽

如果在封装组件时需要预留多个插槽节点,则需要为每个 插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。
在这里插入图片描述
注意:没有指定 name 名称的插槽,会有隐含的名称叫做 “default”。

在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。

只有默认插槽在使用过程中可以省略template标签包裹
在这里插入图片描述
简写形式:
跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header可以被重写为 #header

<template #header>
<h1>滕王阁序</h1>
</template>

7.2.5 作用域插槽(带props数据)

在封装组件的过程中,可以为预留的 <slot> 插槽绑定 props 数据,这种带有 props 数据的 叫做“作用域插槽”。

<template>
  <div>
    <h3>这是 TEST 组件</h3>
    <slot :info="infomation" :msg="message"></slot>
  </div>
</template>

<script>
export default {
  name: 'MyTest',
  data() {
    return {
      // 信息数据
      infomation: {
        phone: '138xxxx6666',
        address: '中国北京',
      },
      message: 'abc'
    }
  },
}
</script>
<template>
  <div>
    <h1>App 根组件</h1>
    <hr />

    <!-- 使用自定义组件 -->
    <my-test>
    
     <template #default="scope">
     <p>{{ scope }}</p>
     </template>
     //渲染出来是一个大对象
    // { infomation:{phone: '138xxxx6666',address: '中国北京',}, message: 'abc'}
    
   // 作用域插槽对外提供的数据对象,可以使用解构赋值简化数据的接收过程
      <template #default="{ msg, info }">
        <p>{{ msg }}</p>
        <p>{{ info.address }}</p>
      </template>
      
    </my-test>
    </template>

声明作用域插槽:

在封装 MyTable 组件的过程中,可以通过作用域插槽把表格每一行的数据传递给组件的使用者。

<template>
  <table class="table table-bordered table-striped table-dark table-hover">
    <!-- 表头区域 -->
    <thead>
      <tr>
        <th>Id</th>
        <th>Name</th>
        <th>State</th>
      </tr>
    </thead>
    <!-- 表格主体区域 -->
    <tbody>
      <!-- 循环渲染表格数据 -->
      <tr v-for="item in list" :key="item.id">
        <slot :user="item"></slot>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  name: 'MyTable',
  data() {
    return {
      // 列表的数据
      list: [
        { id: 1, name: '张三', state: true },
        { id: 2, name: '李四', state: false },
        { id: 3, name: '赵六', state: false },
      ],
    }
  },
}
</script>

在使用 MyTable 组件时,自定义单元格的渲染方式,并接收作用域插槽对外提供的数据

<my-table>
  <template #default="{ user }">
    <td>{{ user.id }}</td>
    <td>{{ user.name }}</td>
    <td>
      <input type="checkbox" :checked="user.state" />
    </td>
  </template>
</my-table>

8. 自定义指令

8.1

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值