一幅长文细学Vue(五)——组件高级(上)
5 组件高级(上)
摘要
在本文中,我们会详细讨论watch侦听器的基本使用,并且了解vue中常用的生命周期函数、实现组件之间的数据共享,最后学习如何在vue3.x项目中全局配置axios。
声明:为了文章的清爽性,在文章内部的代码演示中只会附上部分演示代码,main.js文件的代码通常不贴出,如果感兴趣可以前往代码仓库获取
作者:来自ArimaMisaki创作
5.1 watch侦听器
5.1.1 watch侦听器概述
说明:watch侦听器允许开发者监视数据的变化
,从而针对数据的变化做特定的操作。例如,监视用户名的变化并发起请求,判断用户名是否可用。
本质:监听器的本质也是一个函数,它允许接收两个参数,即新数据
和老数据
。
使用:在选项式API中,我们可以使用watch选项来定义所需的侦听器。
5.1.2 watch的使用场景
场景:检测用户名是否可用
说明:监听username值的变化,并使用axios发起Ajax请求,检测当前输入的用户名是否可用。要完成这个场景,需先安装axios包。
<template>
<div>
<h3>watch 侦听器的用法</h3>
<input type="text" class="form-control" v-model.trim="username">
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'MyWatch',
data() {
return {
username: 'admin',
}
},
watch: {
async username(newVal, oldVal) {
console.log(newVal, oldVal);
const { data: res } = axios.get('https://www.escook.cn/api/finduser' + newVal)
console.log(res);
}
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
<template>
<div>
<h1>App根组件</h1>
<hr>
<my-watch></my-watch>
</div>
</template>
<script>
import MyWatch from "./MyWatch.vue"
export default {
name: 'MyWatch',
components: {
MyWatch
},
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
5.1.3 侦听器选项
immediate选项:watch是懒执行的。默认情况下,组件在初次加载完毕后不会调用watch侦听器,仅当数据源发生改变时,侦听器才会触发。如果想让watch侦听器立即被调用,需要使用immediate选项
。需要额外注意的是,当我们第一次使用侦听器时,旧值为undefined。
deep选项:如果我们侦听的源是对象
或数组
,在不使用选项的情况下我们无法使用侦听器来侦听它们的变化。使用deep选项
可以强制深度遍历源,以便源在进行变更的时候触发回调。
info: {
async handler(newVal) {
const { data: res } = await axios.get('https://www.escook.cn/api/finduser' + newVal.username)
console.log(res);
},
deep:true
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5.1.4 监听对象单个属性的变化
说明:使用deep选项
会遍历数组或对象中的所有属性,如果想要监听单个属性,我们可以采用.
的形式指定获取数组或对象的单个属性作为监听源。不过需要注意的是,由于使用了.
的缘故,作为键的一方需要加上单引号
或双引号
。
5.1.5 计算属性和侦听器
说明:有很多人会搞混计算属性和侦听器。实际上,计算属性侧重于监听多个值得变化,并最终计算返回一个新值,而侦听器侧重于监听单个数据源的变化,最终执行特定的业务处理,不需要有任何返回值。
5.2 生命周期
5.2.1 组件运行的过程
组件的生命周期:组件的生命周期指的是组件从创建到湮灭的整个过程,该术语强调的是这个时间段。
5.2.2 如何监听组件的不同时刻
说明:Vue框架为组件内置了不同时刻的生命周期函数,生命周期函数会伴随着组件的运行而自动调用。另外,生命周期函数常被称为生命周期钩子
。
- 当组件在内存中被创建完毕之后,会自动调用created函数
- 当组件被成功的渲染到页面上之后,会自动调用mounted函数
- 当组件被销毁完毕之后,会自动调用unmounted函数。
<template>
<div>
<h3>LifeCycle 组件</h3>
</div>
</template>
<script>
export default {
name:'LifeCycle',
// 组件在内存中被创建完毕了
created(){
console.log(`created:组件在内存中被创建完毕了`);
},
// 组件第一次被渲染到页面上
mounted(){
console.log(`mounted:组件第一次被渲染到了页面上`);
},
// 组件被销毁完毕了
unmounted(){
console.log(`unmounted:组件被销毁完毕了`);
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
<template>
<div>
<h1>App根组件</h1>
<hr>
<button @click="flag = !flag">toggle</button>
<life-cycle v-if="flag"></life-cycle>
</div>
</template>
<script>
import LifeCycle from "./life-cycle.vue"
export default {
name: 'MyApp',
data(){
return{
flag:true
}
},
components: {
LifeCycle
}
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
5.2.3 如何监听组件的更新
说明:一旦组件中的data数据源发生变化,vue会自动重新渲染组件的DOM结构,从而保证View视图展示的数据和Model数据源保持一致。当组件被重新渲染完毕后,会自动调用updated生命周期函数。
5.2.4 组件生命周期函数
说明:在之前学习的四个周期函数之前加上before,即可出现另外四个生命周期函数。
5.3 数据共享
5.3.1 组件之间的关系
说明:在项目开发中,组件之间的关系分为如下三种:
- 父子关系
- 兄弟关系
- 后代关系
5.3.2 父子组件
父组件向子组件共享数据:父组件使用v-bind指令来向子组件共享数据,子组件需要使用props选项来接收数据。
子组件向父组件共享数据:子组件可以通过自定义事件的方式向父组件共享数据。
父子组件之间数据双向同步:通过v-model指令来维护组件内外数据的双向同步。
5.3.3 兄弟组件
说明:兄弟组件之间实现数据共享的方案是EventBus。可以借助于第三方的包mitt来创建eventBus对象,从而实现兄弟组件之间的数据共享。
示意图:
安装mitt依赖包:npm install mitt
使用步骤:
- 新建一个EventBus.js文件,在里面创建mitt实例,并默认导出
- 在数据接收方的created生命周期钩子中调用
mitt实例对象.on('事件名称',要接收的数据)
自定义一个事件,通过事件处理函数的形参来接收数据。 - 在数据发送方,调用
bus.emit('事件名称',要发送的数据)
方法触发自定义事件。
5.3.4 Prop逐级透传问题
说明:通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props
。想象一下这样的结构:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:
如上图在传递的过程中,可能Footer组件根本不关心这些props,但为了DeepChild的使用,它必须接收并且继续往下传递,如果组件的链路非常长,可能会影响到这条路上更多的组件,这一问题被称为prop逐级透传,我们希望避免这种情况。
5.3.5 后代组件
说明:如果仅仅只是父子关系,那么使用props和v-bind或许是一种不错的策略,但如果要接收数据的组件离发送数据的组件很远(链路很长),使用props就会导致逐级透传问题,这时候我们可以使用provide
和inject
来解决这一问题。
provide选项:provide是一个函数,和data一样返回一个共享的数据对象。对于provide对象上的每一个属性,后代组件都会用其key为注入名查找期望注入的值,属性的值就是要提供的数据。
inject选项:inject是一个数组,用于接收provide提供的共享数据,根据provide返回的对象中属性的键进行查找。
5.3.6 基于Provide向下共享响应式的数据
5.3.7 vuex
说明:vuex是终极的组件之间的共享方案。在企业级的vue项目开发中,vuex可以让组件之间的数据共享变得高效、清晰、且易于维护。
5.4 全局配置axios
引入:在实际项目中,几乎每个组件都会使用axios发起数据请求,此时会遇到两个问题:
- 每个组件中都需要导入axios
- 每次发请求都需要填写完整的请求路径
说明:想要全局配置axios可以在main.js入口文件中,通过app.config.globalProperties全局挂载axios。
格式:app.config.globalProperties.$http
文章来源: blog.csdn.net,作者:ArimaMisaki,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/chengyuhaomei520/article/details/126567820
- 点赞
- 收藏
- 关注作者
评论(0)