vue3学习之模块化(三)结合ts、泛型改造

我爱海鲸 2023-01-15 16:31:37 ts、vue、前端

简介模块化、ts、泛型、catapi、猫接口

链接上一篇文章:vue3学习之模块化(二)

1、使用泛型将useURLLoader.ts进行改造,如下:

import { ref } from 'vue'
import axios from 'axios'

function useURLLoader<T>(url: string) {
  const result = ref<T | null>(null)
  const loading = ref(true)
  const loaded = ref(false)
  const error = ref(null)

  axios.get(url).then((rawData) => {
    loading.value = false
    loaded.value = true
    result.value = rawData.data
  }).catch(e => {
    error.value = e
    loading.value = false
  })

  return {
    result,
    loading,
    error,
    loaded
  }
}

export default useURLLoader

2、app.vue代码:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <h1>{{count}}</h1>
    <h1>{{double}}</h1>
    <h1>x:{{x}}</h1>
    <h1>y:{{y}}</h1>
    <ul>
      <li v-for="number in numbers" :key="number">
        <h1>{{number}}</h1>
      </li>
    </ul>
    <h1>{{person.name}}</h1>
    <h1 v-if="loading">Loading!...</h1>
    <img v-if="loaded" :src="result.message" style="width: 100px;height: 100px"  alt="">
    <button @click="increase">赞+1</button><br/>
    <button @click="updateGreeting">Update Title</button>
  </div>
</template>

<script lang="ts">
  // 响应式对象引入,计算函数引入
import { ref,computed,reactive,toRefs,onMounted,onUpdated,watch,onUnmounted } from 'vue'
import useMousePosition from './hooks/useMousePosition'
import useURLLoader from './hooks/useURLLoader'

interface DataProps {
  count: number;
  double: number;
  increase: () => void;
  numbers: Array<number>,
  person: {name ? :string}
}

  interface DogResult {
    message: string;
    status: string;
  }

export default{
  name: 'App',
  setup() {

    onUpdated(() => {
      console.log('onUpdated');
    })
    // onRenderTracked((event) => {
    //   console.log(event);
    // })

    const data: DataProps  = reactive({
      count: 0,
      increase: () => { data.count++},
      double: computed(() => data.count * 2),
      numbers: [0,1,2],
      person: {}
    })
    const { x, y } = useMousePosition()
    const { result, loading, loaded } = useURLLoader<DogResult>('https://dog.ceo/api/breeds/image/random')
    const greetings = ref('')
    const updateGreeting = () => {
      greetings.value += 'Hello! '
    }
    watch(result, () => {
      if (result.value) {
        console.log('value', result.value.message)
      }
    })

    data.numbers[0] = 5;
    data.person.name = 'haijin';
    const refData = toRefs(data)
    return {
      ...refData,
      greetings,
      updateGreeting,
      x,
      y,
      result,
      loading,
      loaded
    }
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

现在我们该看不出引入ts的具体好处

现在我们换一个api试试:catapi:https://api.thecatapi.com/v1/images/search?limit=1  这个api会返回一个猫的图片地址

https://thecatapi.com/

返回的格式如下:

[{
	"id": "MTg2NTIyMg",
	"url": "https://cdn2.thecatapi.com/images/MTg2NTIyMg.jpg",
	"width": 640,
	"height": 480
}]

当api的返回比较复杂的时候,这个时候泛型的作用就凸显出来了

app.vue代码如下:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <h1>{{count}}</h1>
    <h1>{{double}}</h1>
    <h1>x:{{x}}</h1>
    <h1>y:{{y}}</h1>
    <ul>
      <li v-for="number in numbers" :key="number">
        <h1>{{number}}</h1>
      </li>
    </ul>
    <h1>{{person.name}}</h1>
    <h1 v-if="loading">Loading!...</h1>
    <img v-if="loaded" :src="result[0].url" style="width: 100px;height: 100px"  alt="">
    <button @click="increase">赞+1</button><br/>
    <button @click="updateGreeting">Update Title</button>
  </div>
</template>

<script lang="ts">
  // 响应式对象引入,计算函数引入
import { ref,computed,reactive,toRefs,onMounted,onUpdated,watch,onUnmounted } from 'vue'
import useMousePosition from './hooks/useMousePosition'
import useURLLoader from './hooks/useURLLoader'

interface DataProps {
  count: number;
  double: number;
  increase: () => void;
  numbers: Array<number>,
  person: {name ? :string}
}

  interface DogResult {
    message: string;
    status: string;
  }

  interface CatResult {
    id: string;
    url: string;
    width: number;
    height: number;
  }
export default{
  name: 'App',
  setup() {

    onUpdated(() => {
      console.log('onUpdated');
    })
    // onRenderTracked((event) => {
    //   console.log(event);
    // })

    const data: DataProps  = reactive({
      count: 0,
      increase: () => { data.count++},
      double: computed(() => data.count * 2),
      numbers: [0,1,2],
      person: {}
    })
    const { x, y } = useMousePosition()
    const { result, loading, loaded } = useURLLoader<CatResult[]>('https://api.thecatapi.com/v1/images/search?limit=1')
    const greetings = ref('')
    const updateGreeting = () => {
      greetings.value += 'Hello! '
    }
    watch(result, () => {
      if (result.value) {
        console.log('value', result.value)
      }
    })

    data.numbers[0] = 5;
    data.person.name = 'haijin';
    const refData = toRefs(data)
    return {
      ...refData,
      greetings,
      updateGreeting,
      x,
      y,
      result,
      loading,
      loaded
    }
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

 

 

你好:我的2025