[Vue3学习笔记]Vue3生命周期和自定义hook函数

Vue3学习笔记

  • Vue2和Vue3生命周期的区别
  • 自定义hook函数
    • 获取鼠标位置
    • 封装axios的hook
      • 如果我们要加一个监听呢?

Vue2和Vue3生命周期的区别

  • 两变:最直观的是两个名称的改变
Vue2 Vue3
beforeDestory beforeUnmount
Destoryed unmounted
  • 两删:created和beforeCreate被删掉了,因为有setup了
  • 加一个on:其他的都是加上了一个on,比如mounted---> onMounted,当然这些加on的也可以用原来的,在这里2.x和3.x是兼容的
    注意:3.x里面的生命周期都是组合API,不用像2.x中一样写成option,3.x直接写回调,很爽的!
    简称221,还有就是,3.x的生命周期比2.x要快!

自定义hook函数

  • 自定义hook的作用类似于vue2中的mixin技术
  • 自定义Hook的优势:很清楚复用功能代码的来源,更清楚易懂

获取鼠标位置

  • 举个例子:用户在页面中点击页面,把点击得位置得横纵坐标收集起来并展示出来(我们写成一个hook)
    我们写一个hook useMousePosition.ts
    [Vue3学习笔记]Vue3生命周期和自定义hook函数_第1张图片
/*
 * @Author: 41
 * @Date: 2021-12-15 20:49:45
 * @LastEditors: 41
 * @LastEditTime: 2021-12-15 21:00:01
 * @Description: 
 */
import { onBeforeUnmount, onMounted, ref} from 'vue'
export default ():any=>{
    const x=ref(-1)
    const y=ref(-1)
    const clickHandler= (event:MouseEvent)=>{
      x.value=event.pageX
      y.value=event.pageY
    }
    onMounted(()=>{
      window.addEventListener('click',clickHandler)
    })
    onBeforeUnmount(()=>{
      window.removeEventListener('click',clickHandler)
    })
    return {
      x,
      y
    } 
}


  • 然后在需要用的时候直接引入就好了
<!--
 * @Author: 41
 * @Date: 2021-12-07 17:12:43
 * @LastEditors: 41
 * @LastEditTime: 2021-12-15 20:54:21
 * @Description: 
-->
<template>
  <h2>自定义hook</h2>
  <h2>x:{{x}},y:{{y}}</h2>
</template>

<script lang="ts">
import {defineComponent} from 'vue'
import useMousePosition from './hooks/useMousePosition'
export default defineComponent({
  name:'App',
  // 需求1:用户在页面中点击页面,把点击得位置得横纵坐标收集起来并展示出来
  setup(){
    const {x,y}=useMousePosition()
    return {
      x,
      y
    }
  }
})
</script>

封装axios的hook

  • 准备数据如下:
    [Vue3学习笔记]Vue3生命周期和自定义hook函数_第2张图片
// a.json
   {
        "id":1,
        "address":"华为手机30",
        "distance":"1000m"
    }

// b.json
[
    {
        "id":"001",
        "title":"华为手机30",
        "price":3219
    },
    {
        "id":"002",
        "title":"小米手机30",
        "price":1982
    }
]
  • < T>根据数据改变参数类型,但不能是null 取的时候也要是泛型
  • 我们先写一个useRequest.ts的hook如下
/*
 * @Author: 41
 * @Date: 2021-12-15 21:08:35
 * @LastEditors: 41
 * @LastEditTime: 2021-12-15 22:25:52
 * @Description: 
 */
// 引入axios
import {ref} from 'vue'
import axios from 'axios'
export default function <T>(url:string){
    const loading=ref(true)
    const data=ref<T|null>(null)
    const errorMsg=ref('')
    axios.get(url).then(response=>{
        loading.value=false
        data.value=response.data
    }).catch(error=>{
        loading.value=false
        errorMsg.value=error.message || '未知错误'
    })
    return {
        loading,
        data,
        errorMsg
    }
}

  • 在父组件使用,注意,对象和数组的使用方法不一样
<!--
 * @Author: 41
 * @Date: 2021-12-07 17:12:43
 * @LastEditors: 41
 * @LastEditTime: 2021-12-15 22:24:19
 * @Description: 
-->
<template>
  <h2>自定义hook</h2>
  <h2>x:{{x}},y:{{y}}</h2>
  <h3 v-if="loading">正在加载中...</h3>
  <h3 v-else-if="errorMsg">错误信息:{{errorMsg}}</h3>
  <!-- 这里查询结果是对象 -->
  <ul v-else>
    <li>id:{{data.id}}</li>
    <li>address:{{data.address}}</li>
    <li>distance:{{data.distance}}</li>
  </ul>
  <!-- 查询结果是数组 -->
  <ul v-for="item in data" :key="item.id">
    <li>id:{{item.id}}</li>
    <li>address:{{item.title}}</li>
    <li>distance:{{item.price}}</li>
  </ul>
</template>

<script lang="ts">
import {defineComponent} from 'vue'
import useMousePosition from './hooks/useMousePosition'
import useRequest from './hooks/useRequest'
export default defineComponent({
  name:'App',
  // 需求1:用户在页面中点击页面,把点击得位置得横纵坐标收集起来并展示出来
  setup(){
    const {x,y}=useMousePosition()
    // const {loading,data,errorMsg}=useRequest('/data/a.json')
    const {loading,data,errorMsg}=useRequest('/data/b.json')
    return {
      x,
      y,
      loading,
      data,
      errorMsg
    }
  }
})
</script>

如果我们要加一个监听呢?

  • 在setup中加一个监听,会有报错!
   watch(data,()=>{
      if(data.value){
        console.log(data.value.length);
        
      }
    })

我们在使用hook请求的时候,要指定接口的数据类型

interface ProdictsData{
  id:string;
  title:string;
  price:number;
}
 const {loading,data,errorMsg}=useRequest<ProdictsData[]>('/data/b.json')

这样就可以了


完整代码如下:

<!--
 * @Author: 41
 * @Date: 2021-12-07 17:12:43
 * @LastEditors: 41
 * @LastEditTime: 2021-12-15 22:40:03
 * @Description: 
-->
<template>
  <h2>自定义hook</h2>
  <h2>x:{{x}},y:{{y}}</h2>
  <h3 v-if="loading">正在加载中...</h3>
  <h3 v-else-if="errorMsg">错误信息:{{errorMsg}}</h3>
  <!-- 这里查询结果是对象 -->
  <ul v-else>
    <li>id:{{data.id}}</li>
    <li>address:{{data.address}}</li>
    <li>distance:{{data.distance}}</li>
  </ul>
  <!-- 查询结果是数组 -->
  <ul v-for="item in data" :key="item.id">
    <li>id:{{item.id}}</li>
    <li>address:{{item.title}}</li>
    <li>distance:{{item.price}}</li>
  </ul>
</template>

<script lang="ts">
import {defineComponent, watch} from 'vue'
import useMousePosition from './hooks/useMousePosition'
import useRequest from './hooks/useRequest'

// 定义接口,约束对象的类型
interface IAddressData{
  id:number;
  address:string;
  distance:string;
}
interface ProdictsData{
  id:string;
  title:string;
  price:number;
}
export default defineComponent({
  name:'App',
  // 需求1:用户在页面中点击页面,把点击得位置得横纵坐标收集起来并展示出来
  setup(){
    const {x,y}=useMousePosition()
    // const {loading,data,errorMsg}=useRequest('/data/a.json')
    const {loading,data,errorMsg}=useRequest<ProdictsData[]>('/data/b.json')
    watch(data,()=>{
      if(data.value){
        console.log(data.value.length);
        
      }
    })
    return {
      x,
      y,
      loading,
      data,
      errorMsg
    }
  }
})
</script>

[Vue3学习笔记]Vue3生命周期和自定义hook函数_第3张图片

你可能感兴趣的:(VUE框架学习笔记,vue.js,javascript,前端)