文章目录

  • 组件高级
  • 一、watch 监听器
  • 二、组件的生命周期
  • 2.1 组件运行的过程
  • 2.2 监听组件的不同时刻
  • 2.3 监听组件的更新
  • 2.4 主要生命周期函数
  • 三、组件之间的数据共享
  • 3.1 组件关系及数据共享
  • 3.2 父子组件数据共享
  • 3.3 兄弟组件数据共享
  • 3.4 后代组件数据共享
  • 3.5 vuex
  • 四、全局配置 axios



组件高级


一、watch 监听器

1、监听器概念

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。例如,监视用户名的变化并发起请求,判断用户名是否可用。


2、基本语法

通过watch节点定义需要监听数据的函数,第一个参数是变化后的新值,第二个参数是变化之前的旧值:

<script>
export default{
	data(){
		return { username:''}
	},
	watch:{
		username(newVal,oldVal) {
			console.log(newVal, oldVal)
		}
	}
}
</script>

创建新的两个组件:

【Vue】组件高级_ios

在MyWatch组件中声明数据项 username,并添加监听器检测值的变化,在页面中新增输入框,双向绑定 username,并且使用trim过滤前后空格:

【Vue】组件高级_javascript_02

我們設定初始 username 值为 admin,监听输入框中的数据值,每删除一个字符就会进行数据监听,控制台输出。


3、监测用户名是否可用

监听 username 的值变化,并使用 axios 发起 Ajax 请求,检测当前输入的用户名是否可用:

首先 npm install axios ,导入axios模块:

<script>
// 导入axios
import axios from 'axios'
    
export default {
  name: 'MyWatch',
  data() {
    return {
      username: 'admin',
    }
  },
  watch: {
   username(newVal,oldVal){
      // 解构:重命名
      async const { data:res} =await axios.get('https://www.escook.cn/api/finduser/${newVal}')
      console.log(res)
    }
  },
}
</script>

通过控制台可以看出res是 Promise 对象属性(异步),我们通过解构将data数据提取出来,并且使用 await 、async 修饰,async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。

【Vue】组件高级_数据_03

这部分服务器已经关闭了所以通过视屏讲解理解流程即可,最终效果类似是监听组件 username 的值,若为空则是用户名可用,若不为空存入第一次的值,此时用户名已被占用,再次修改用户名无效。

【Vue】组件高级_数据共享_04


4、默认情况下,组件在初次加载完毕后不会调用 watch 侦听器(如下图所示没有输出内容)。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。

【Vue】组件高级_数据共享_05

<script>
import axios from 'axios'

export default {
  name: 'MyWatch',
  data() {
    return {
      username: 'admin',
    }
  },
  watch: {
    async username(newVal, oldVal) {
      console.log("newVal:" + newVal, "oldVal" + oldVal)
      // 解构:重命名
      const {data:res} = axios.get("https://www.escook.cn/api/finduser/" + newVal)
      console.log(res)
    }
  },
  immediate:true // 组件加载完毕后立即调用一次当前的watch监听器
}
</script>

可以发现,程序一启动,控制台就输出了监听的信息:

【Vue】组件高级_数据_06


5、当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到,此时需要使用 deep 选项

【Vue】组件高级_数据_07

如果只想监听对象中单个属性的变化,则可以按照 watch:{ 对象.属性 {…}}的方式定义 watch 侦听器:

【Vue】组件高级_数据共享_08


6、计算属性 vs 侦听器

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

返回顶部


二、组件的生命周期

2.1 组件运行的过程

  • 组件的生命周期指的是:组件从创建 -> 运行(渲染) -> 销毁的整个过程,强调的是一个时间段。
  • 官网解析

2.2 监听组件的不同时刻

【Vue】组件高级_vue.js_09

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

① 当组件内存中被创建完毕之后,会自动调用 created 函数

② 当组件被成功的渲染到页面上之后,会自动调用 mounted 函数

③ 当组件被销毁完毕之后,会自动调用 unmounted 函数

首先创建两个新的组件,并在 Vue 组件中将 LifeCycle 组件导入进去:

【Vue】组件高级_数据_10

当我们创建几个基础生命周期函数后,启动vite创建程序,在控制台会出现 created、mounted 的自动调用:

【Vue】组件高级_ios_11

通过定义新的组件button,动态修改参数 flag 的值,从而动态的改变 lifr-cycle 组件的创建、渲染与销毁,可以看到默认组件显示,当我们点击按钮后,组件消失,即被销毁,调用对应的 unmounted 函数,控制台输出信息:

<template>
  <div>
    <h1>App 根组件</h1>
    <hr />
    <!-- 3. 以标签形式使用组件,v-if 当flag为true的时候显示该组件 -->
    <life-cycle v-if="flag"></life-cycle>
    <!-- 按钮点击事件动态改变组件的创建与销毁 -->
    <button @click="flag = !flag">Taggle</button>
  </div>
</template>

<script>
// 1. import 导入组件
import LifeCycle from './LifeCycle.vue'

export default {
  name: 'MyApp',
  data() {
    return {
      flag: true,
    }
  },
  // 2. components 注册组件
  components: {
    LifeCycle,
  },
}
</script>
<style lang="less" scoped></style>

【Vue】组件高级_ios_12


2.3 监听组件的更新

  • 当组件的 data 数据更新之后,vue 会自动重新渲染组件的 DOM 结构,从而保证 View 视图展示的数据和 Model 数据源保持一致。
  • 当组件被重新渲染完毕之后,会自动调用 updated 生命周期函数。
<template>
  <div>
    <h3>LifeCycle 组件 --- {{ count }}</h3>
    <button class="btn btn-primary" type="button" @click="count+=1">Taggle</button>
  </div>
</template>

<script>
export default {
  name: 'LifeCycle',
  data() {
    return {
      count: 0,
    }
  },
  // 组件在内存中被创建完毕了
  created() {
    console.log('created: 组件在内存中被创建完毕了')
  },
  // 组件第一次被渲染到了页面上
  mounted() {
    console.log('mounted: 组件第一次被渲染到了页面上')
  },
  // 组件被重新渲染完毕了
  updated() {
    console.log('updated: 组件被重新渲染完毕了')
  },
  // 组件被销毁完毕了
  unmounted() {
    console.log('unmounted: 组件被销毁完毕了')
  },
}
</script>
<style lang="less" scoped></style>

【Vue】组件高级_数据_13


2.4 主要生命周期函数

【Vue】组件高级_数据_14

注意:发起Ajax请求数据必须在created中,之所以不在 beforeCreate中是因为此时组件还未被创建,无法将数据挂载到data节点上(如下图所示,在控制台输出是count的值没有)!

【Vue】组件高级_javascript_15

返回顶部


三、组件之间的数据共享

这部分内容与props内容基本一致,可以参考!

3.1 组件关系及数据共享

在项目开发中,组件之间的关系分为如下 3 种:

  • 父子关系
  • 兄弟关系
  • 后代关系

【Vue】组件高级_vue.js_16


3.2 父子组件数据共享

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

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

3.3 兄弟组件数据共享

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

【Vue】组件高级_javascript_17

安装 mitt 依赖包:npm install mitt@2.1.0

新建组件:Vue 、Left 、Right ,在Vue中导入Left、Right组件:

【Vue】组件高级_ios_18

创建公共的 EventBus 模块:

// eventBus.js

// 导入 mitt 包
import mitt from 'mitt'
// 创建EventBus实例对象
const bus = mitt()
// 将 EventBus 对象共享出去
export default bus

在数据接收方自定义事件,调用 bus.on(‘事件名称’,事件处理函数) 方法注册一个自定义事件:

<template>
  <div>
    <h3>数据接收方 --- num 的值为:{{ num }}</h3>
  </div>
</template>

<script>
// 导入bus实例对象
import bus from './eventBus.js'

export default {
  name: 'MyRight',
  data() {
    return {
      num: 0,
    }
  },
  mounted(){
    // 接收发送方数据
    bus.on('countChange',(count)=>{
      this.num = count
    })
  }
}
</script>

<style lang="less" scoped></style>

在数据发送方,调用bus.emit(‘事件名称’, 要发送的数据) 方法触发自定义事件。

<template>
  <div>
    <h3>数据发送方 --- count 的值为:{{ count }}</h3>
    <button type="button" class="btn btn-primary" @click="add">+1</button>
  </div>
</template>

<script>
// 导入bus实例对象
import bus from './eventBus.js'

export default {
  name: 'MyLeft',
  data() {
    return {
      count: 0,
    }
  },
  methods: {
    add() {
      this.count++
      // 发送方发送数据
      bus.emit('countChange', this.count)
    },
  },
}
</script>

<style lang="less" scoped></style>

【Vue】组件高级_ios_19


3.4 后代组件数据共享

后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,可以使用 provideinject 实现后代关系组件之间的数据共享。

【Vue】组件高级_ios_20

创建新的组件:App、LevelTwo、LevelThree,并将三个组件连级引入(App中导入LevelTwo组件,LevelTwo中导入LevelThree组件):

【Vue】组件高级_数据共享_21

父节点的组件可以通过provide 方法,对其子孙组件共享数据:

<script>
import LevelTwo from './LevelTwo.vue'

export default {
  name: 'MyApp',
  data() {
    return {
      color: 'red',
    }
  },
  provide() {
    // 返回要共享的数据对象
    return {
      color: this.color,
    }
  },
  components: {
    LevelTwo,
  },
}
</script>

子孙节点可以使用inject数组,接收父级节点向下共享的数据:

<template>
  <div>
    <h5>Level Three 三级组件 - {{ color }}</h5>
  </div>
</template>

<script>
export default {
  name: 'LevelThree',
  inject: ['color'], // 接收数据
}
</script>

【Vue】组件高级_javascript_22

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

  • 父节点使用 provide 向下共享数据时,可以结合 computed 函数向下共享响应式的数据。
<template>
  <div>
    <h1>App 根组件 -- {{ color }}</h1>
    <hr />
    <level-two></level-two>
  </div>
</template>

<script>
import LevelTwo from './LevelTwo.vue'
import { computed } from 'vue'

export default {
  name: 'MyApp',
  data() {
    return {
      color: 'red',
    }
  },
  provide() {
    // 返回要共享的数据对象
    return {
      color: computed(() => this.color),
      count: 1,
    }
  },
  components: {
    LevelTwo,
  },
}
</script>
<style lang="less" scoped></style>
  • 如果父级节点共享的是响应式的数据,则子孙节点必须以 .value 的形式进行使用
<template>
  <div>
    <h5>Level Three 三级组件 --- {{ color.value }} --- {{ count }}</h5>
  </div>
</template>

<script>
export default {
  name: 'LevelThree',
  inject: ['color', 'count'],
}
</script>

<style lang="less" scoped></style>

【Vue】组件高级_javascript_23

**新增按钮,改变父组件中 color 的,可以观察到后代组件的 color 也跟着改变了: **

【Vue】组件高级_vue.js_24


3.5 vuex

vuex 是终极的组件之间的数据共享方案。在企业级的 vue 项目开发中,vuex 可以让组件之间的数据共享变得高效、清晰、且易于维护。

【Vue】组件高级_javascript_25

从上图中我们可以看到,使用传统的组件之间的数据共享方式,在父与子、子与父、兄弟组件之间每有一个数据的传递就需要使用对应的方式进行传值,显得十分繁琐;而 vuex 方案则可以将这些所有类型的绑定事件进行统一的管理,简化了开发。

返回顶部


四、全局配置 axios

参考文章:【Vue】 Axios请求库

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

① 每个组件中都需要导入 axios(代码臃肿)

② 每次发请求都需要填写完整的请求路径(不利于后期的维护)

【Vue】组件高级_数据共享_26

main.js 入口文件中,通过 app.config.globalProperties 全局挂载 axios :

【Vue】组件高级_javascript_27

创建三个新的组件:Vue、GetInfo、PostInfo,GetInfo、PostInfo组件中分别创建按钮,实现get、post的请求方法:

【Vue】组件高级_数据共享_28

【Vue】组件高级_ios_29


【Vue】组件高级_vue.js_30


返回顶部