VUE基础(四)

一、watch侦听器

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

 export default {
    name: 'MyWatch',
    data() {
      return {
        username: 'admin',
      }
    },
    // 需要在watch节点下,定义侦听器
    watch: {
     //监听userName的变化
     username(newVal,oldVal){
        console.log("变化后的新值", newVal);
        console.log("变化前的旧值", oldVal);
     }
    },
  }

 immediate选项

作用:组件在初次加载完毕后不会调用watch监听器,immediate选项可以让watch监听器立即被调用

 另username不在是一个方法了,而是指向一个对象

 export default {
    name: 'MyWatch',
    data() {
      return {
        username: 'admin',
      }
    },
    // 需要在watch节点下,定义侦听器
    watch: {
     //监听userName的变化
     username: {
      // handler属性是固定写法,当username变化时,调用handler
      async handler(newVal, oldVal) {
        const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal)
        console.log(res)
      },
      // 立即触发 watch 侦听器
      immediate: true,
    },
    },
  }

 deep选项

作用:如果监听的是对象,对象中的属性值发生了变化,则无法被监听到,此时需要使用deep选项

export default {
  name: 'MyWatch',
  data() {
    return {
      info: {
        username: 'zs',
        age: 20,
      },
    }
  },
  watch: {
    info: {
      async handler(newVal) {
        const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal.username)
        console.log(res)
      },
      deep: true,//需要使用deep节点,否则info中的username变化监听不到
    },
  },
}

 仅需监听对象中一个属性的变化

export default {
  name: 'MyWatch',
  data() {
    return {
      info: {
        username: 'zs',
        age: 20,
      },
    }
  },
  watch: {
   //仅监听info对象中username属性的变化
  'info.username': {
      async handler(newVal) {
        const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal)
        console.log(res)
      },
    },
  },
}

 计算属性和侦听器的区别

计算属性侧重于监听多个值的变化,最终计算并返回一个新值

侦听器侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值

二、组件生命周期

组件的运行过程

  1. 在内存中创建组价的实例对象
  2. 把创建的组件实例渲染到页面上
  3. 当组件中data数据更新后,vue会重新渲染组件的DOM结构
  4. 组件切换时销毁需要被隐藏的组件

 组件的声明周期:组件从创建到渲染到销毁的整个过程,强调的是一个时间段

 组价的声明周期函数:监听组件运行的不同时刻,会伴随着组件的运行而自动调用

生命周期函数

生命周期函数执行时机所属阶段执行次数应用场景
beforeCreate开始创建组件之前创建阶段唯一1次
created组件在内存中被创建完毕后调用创建阶段唯一1次发ajax请求数据
beforeMount组件初次渲染之前创建阶段唯一1次
mountde组件第一次被渲染到页面上后调用创建阶段唯一1次操作DOM元素
beforeUpdate组件重新渲染之前运行阶段0或多次
updated组件被重新渲染后调用运行阶段0或多次
beforeUnmount组件被销毁之前销毁阶段唯一1次
unmounted组件被销毁完毕后调用销毁阶段唯一1次

示例

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

三、组件间的数据共享

1、父子组件之间的数据共享

父传子

父组件通过v-bind属性绑定像子组件传递数据,同时子组件通过props接收数据。

<!-- 父组件 -->
<template>
  <div>
    <h1>App 根组件 -- {{ count }}</h1>
    <button type="button" class="btn btn-primary" @click="count += 1">+1</button>
    <hr />
    <!-- 3. 以v-bind的形式向子组件传递数据 -->
    <my-son :num="count"></my-son>
  </div>
</template>

<script>
// 1. 导入子组件
import MySon from './Son.vue'

export default {
  name: 'MyApp',
  data() {
    return {
      count: 0,
    }
  },
  // 2. 注册子组件
  components: {
    MySon,
  },
}
</script>

<!-- 子组件 -->
<template>
  <div>
    <h3>Son 子组件 --- {{ num }}</h3>
  </div>
</template>

<script>
export default {
  name: 'MySon',
  // 子组件接收父组件传来的num值
  props: ['num'],
}
</script>

子传父

子组件通过自定义事件的方式像父组件中共享数据

<!-- 子组件 -->
<template>
  <div>
    <h3>Son 子组件 --- {{ num }}</h3>
    <button type="button" class="btn btn-danger" @click="add">+1</button>
  </div>
</template>

<script>
export default {
  name: 'MySon',
   data(){
    return{
      num:0
    }
  }
  // 1.通过emits节点声明自定义事件
  emits: ['numchange'],
  methods: {
    add() {
      //2.在合适的时机通过$emit方法触发自定义事件
      this.$emit('numchange', this.num + 1)
    },
  },
}
</script>
<!-- 父组件 -->
<template>
  <div>
    <h1>App 根组件 -- {{ count }}</h1>
    <!-- v-on监听子组件的自定义事件getNum -->
    <my-son @numchange="getNum"></my-son>
  
  </div>
</template>

<script>
import MySon from './Son.vue'

export default {
  name: 'MyApp',
  data() {
    return {
      count: 0,
    }
  },
  methods: {
    getNum(num) {
    //通过形参接收子组件传来的数据
    this.count = num
   }
  },
  components: {
    MySon,
  },
}
</script>

父子双向数据同步

使用v-modal指令可维护父子组件的双向数据同步,在父组件中使用v-modal,在子组件中声明emits

<!-- 父组件 -->
<template>
  <div>
    <h1>App 根组件 -- {{ count }}</h1>
    <button type="button" class="btn btn-primary" @click="count += 1">+1</button>
    <hr />

    <!-- 以v-bind的形式向子组件传递数据 -->
    <my-son v-model:num="count"></my-son>
  </div>
</template>

<script>
import MySon from './Son.vue'

export default {
  name: 'MyApp',
  data() {
    return {
      count: 0,
    }
  },
  components: {
    MySon,
  },
}
</script>
<!-- 子组件 -->
<template>
  <div>
    <h3>Son 子组件 --- {{ num }}</h3>
    <button type="button" class="btn btn-danger" @click="add">+1</button>
  </div>
</template>

<script>
export default {
  name: 'MySon',
  // 子组件接收父组件传来的num值
  props: ['num'],
  //声明自定义事件,注意update固定写法
  emits: ['update:num'],
  methods: {
    add() {
      //触发自定义事件
      this.$emit('update:num', this.num + 1)
    },
  },
}
</script>

 2、兄弟组件之间的数据共享

兄弟组件之间通过EventBus实现数据共享

借助于第三方包mitt来创建eventBus对象

 使用步骤

  1. 安装mitt包
  2. 创建EventBus
  3. export EventBus

 数据发送方:

  1. 导入并得到EventBus实例对象
  2. 调用EventBus的emit()方法,向外发送数据
bus.emit('自定义事件', 要发送的数据)

数据接收方:

  1. 导入并得到EventBus实例对象
  2. 调用EventBus的on()方法,声明自定义事件,通过事件回调接收数据
 bus.on('自定义事件', (data) => {  })

 示例:

1.安装依赖包

npm install mitt@版本号 -S

2.创建公共的eventBus模块

// eventBus.js

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

3.使用eventBus

父组件:App.vue

<template>
  <div>
    <h1>App 根组件</h1>
    <hr />

    <div class="brother-box">
  
      <my-left></my-left>
      <my-right></my-right>
    </div>
  </div>
</template>

<script>

import MyLeft from './Left.vue'
import MyRight from './Right.vue'

export default {
  name: 'MyApp',
  components: {
    MyLeft,
    MyRight,
  },
}
</script>

数据接收方Right.vue

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

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

export default {
  name: 'MyRight',
  data() {
    return {
      num: 0,
    }
  },
  created() {
    // 调用EventBus的on()方法,声明自定义事件,通过事件回调接收数据
    bus.on('countChange', count => {
      this.num = count
    })
  },
}
</script>

数据发送方Left.vue

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

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

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

 3、后代组件间的数据共享

 父节点的组件向其子孙组件共享数据,可使用provide和inject实现后代关系组件之间的数据共享

提供数据使用provide,接收数据使用inject

  使用步骤

  1. 父节点中通过provide方法,对其子孙组件共享数据
  2. 子孙节点中使用inject数组,接收父级节点向下共享的数据
  3. 父组件可结合computed函数共享响应式数据,子组件以.value的形式使用响应式数据

  示例

  父节点

<!--  父组件  -->
<template>
  <div>
    <h1>App 根组件 -- {{ color }}</h1>
    <hr />

    <level-two></level-two>

  </div>
</template>

<script>
import LevelTwo from './LevelTwo.vue'
//从vue中导入computed函数
import { computed } from 'vue'

export default {
  name: 'MyApp',
  data() {
    return {
      color: 'red',
      count: 1,
    }
  },
  provide() {
    // provide函数return的对象中,包含了要向子孙组件中共享的数据
    return {
      color: this.color,
      //调用computed函数,进行响应式数据共享
      count: computed(() => this.count)
    }
  },
  components: {
    LevelTwo,
  },
}
</script>

   子节点

<template>
  <div>
    <h3>Level Two 二级组件</h3>

    <hr />

    <level-three></level-three>
  </div>
</template>

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

export default {
  name: 'LevelTwo',
  components: {
    LevelThree,
  },
}
</script>

   孙节点

<template>
  <div>
    <h5>Level Three 三级组件 --- {{ color }}</h5>
    <!-- 响应式数据,必须以 .value 的形式进行使用  -->
    <h5>Level Three 三级组件 --- {{ count.value }}</h5>
  </div>
</template>
 
<script>
export default {
  name: 'LevelThree',
  // 子孙组件使用inject接收父级组件向下共享的数据
  inject: ['color','count'],
}
</script>

四、全局配置axios

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

 步骤

  1. import安装axios包
  2. 在main.js入口文件中导入axios,并进行axios配置(根路径)
  3. 在main.js中将axios全局挂载至app上
  4. 在每个vue组件中,都可以通过this.$http发起get或post请求

 示例

main.js中

import { createApp } from 'vue'

import App from './components/App.vue'

import './assets/css/bootstrap.css'
import './index.css'

import axios from 'axios'

const app = createApp(App)
// 为axios配置请求根路径
axios.defaults.baseURL = 'https://api.com'
// 将axios挂载为自定义属性后,每个组件可通过this直接访问的全局挂载的自定义属性
// $后的自定义属性名可自定义,此处为http
app.config.globalProperties.$http = axios

app.mount('#app')

发起post请求 PostInfo.vue

<template>
  <div>
    <h3>Post Info 组件</h3>
    <hr />

    <button type="button" class="btn btn-success" @click="postInfo">发起 POST 请求</button>
  </div>
</template>

<script>
export default {
  name: 'PostInfo',
  methods: {
    async postInfo() {
      // 发起post请求this.$http.post(请求路径,请求数据)
      const { data: res } = await this.$http.post('/api/post', { name: 'zs', age: 20 })
      console.log(res)
    },
  },
}
</script>

发起get请求 GetInfo.vue

<template>
  <div>
    <h3>Get Info 组件</h3>
    <hr />

    <button type="button" class="btn btn-primary" @click="getInfo">发起 GET 请求</button>
  </div>
</template>

<script>
export default {
  name: 'GetInfo',
  methods: {
    async getInfo() {
      // 发起get请求this.$http.get(请求路径,{params:{请求数据}}})
      const { data: res } = await this.$http.get('/api/get', {
        params: {
          name: 'ls',
          age: 33,
        },
      })

      console.log(res)
    },
  },
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值