Vue3 — 自定义hook函数

自定义hook函数

  • 使用Vue3的组合API封装的可复用的功能函数
  • 自定义hook的作用类似于vue2中的mixin技术
  • 自定义Hook的优势: 很清楚复用功能代码的来源, 更清楚易懂

需求1: 收集用户鼠标点击的页面坐标
  • 普通写法:只能在该组件中使用
<template>
  <h2>x:{{x}}, y:{{y}}</h2>
</template>

<script lang="ts">
import { defineComponent, onBeforeMount, onBeforeUnmount, onMounted, ref } from "vue";

export default defineComponent({
  name: "App",
  
  setup() {
    let x = ref(-1)
    let y = ref(-1)

    // 获取鼠标点击位置
    let clickHandle = (e:MouseEvent) => {
      x.value = e.pageX
      y.value = e.pageY
    }

    onMounted(() => {
      window.addEventListener("click", clickHandle)
    })

    onBeforeUnmount(() => {
      window.removeEventListener("click", clickHandle)
    })
    return {
      x, y
    };
  },
});
</script>
  • 使用自定义hooks实现
import { onMounted, onBeforeUnmount, ref } from "vue"
export default function () {
    let x = ref(-1)
    let y = ref(-1)

    // 获取鼠标点击位置
    let clickHandle = (e: MouseEvent) => {
        x.value = e.pageX
        y.value = e.pageY
    }

    onMounted(() => {
        window.addEventListener("click", clickHandle)
    })

    onBeforeUnmount(() => {
        window.removeEventListener("click", clickHandle)
    })
    return {
        x,
        y
    }
}
<template>
  <h2>x:{{x}}, y:{{y}}</h2>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import useMousePosition from "./hooks/useMousePosition"

export default defineComponent({
  name: "App",
  
  setup() {
    const {x, y} = useMousePosition()
    return {
      x, y
    };
  },
});
</script>

需求2: 发送AJAX请求

  • 获取对象中的数据
{
    "id": 1,
    "address": "黑龙省齐齐哈尔市",
    "distance": "1000米"
}
import axios from 'axios'
import { ref } from "vue";

// 发送ajax请求
export default function(url: string) {
    // 加载的状态
    const loading = ref(true)
    // 请求成功的数据
    const data = ref(null)
    // 错误信息
    const errorMsg = ref('')
    
    // 发送请求
    axios.get(url).then(response => {
        loading.value = false
        data.value = response.data
    }).catch(err => {
        loading.value = false
        errorMsg.value = err.message || '未知错误'
    })
    return {
        loading,
        data,
        errorMsg
    }
}
<template>
  <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>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import useRequest from "./hooks/useRequest";

export default defineComponent({
  name: "App",

  setup() {
    // 获取对象数据
    const { loading, data, errorMsg } = useRequest("/data/address.json");
    return {
      loading,
      data,
      errorMsg,
    };
  },
});
</script>

在这里插入图片描述

  • 获取数组中的数据
[
    {
        "id": "01",
        "title" :"arr1"
    },
    {
        "id": "02",
        "title" :"arr2"
    }
]
<template>
  <ul v-for="item in data" :key="item.id">
    <li>id: {{item.id}}</li>
    <li>title: {{item.title}}</li>
  </ul>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import useRequest from "./hooks/useRequest";

export default defineComponent({
  name: "App",

  setup() {
    // 获取数组数据
    const { loading, data, errorMsg } = useRequest("/data/list.json");
    return {
      loading,
      data,
      errorMsg,
    };
  },
});
</script>

在这里插入图片描述

  • 使用watch监听data数据
    在这里插入图片描述
    报错的原因是useRequest.ts中:
    在这里插入图片描述
  • 修改:
import axios from 'axios'
import { ref } from "vue";

// 发送ajax请求
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(err => {
        loading.value = false
        errorMsg.value = err.message || '未知错误'
    })
    return {
        loading,
        data,
        errorMsg
    }
}
<template>
  <ul v-for="item in data" :key="item.id">
    <li>id: {{item.id}}</li>
    <li>title: {{item.title}}</li>
  </ul>
</template>

<script lang="ts">
import { defineComponent, watch } from "vue";
import useRequest from "./hooks/useRequest";
// 定义接口,约束对象类型
interface AddressData {
  id: number,
  address: string,
  distance: string
}

interface ListData {
  id: string,
  title: string
}
export default defineComponent({
  name: "App",

  setup() {
    // 获取数组数据
    const { loading, data, errorMsg } = useRequest<ListData[]>("/data/list.json");
    watch(data, () => {
      if(data.value) {
        console.log(data.value.length);
      }
    })
    return {
      loading,
      data,
      errorMsg,
    };
  },
});
</script>

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值