【Vue3+Ts】—— Composition API综合练习

目录

useCounter

useTitle

useScrollPosition


前面我们已经学习了setup、reactive、ref、computed、watchEffect、watch、provide、inject等等Composition API,那下面将通过一个Composition API的综合练习来巩固一下组合API的使用以及代码逻辑的封装(即Hook函数的封装)。其中该综合练习包含以下功能:

  • 计数器案例的实现。

  • 修改网页的标题。

  • 完成一个监听界面滚动位置。

在使用Composition API之前,我们先看看用Options API是如何实现该功能。

代码如下所示:

<template>
  <div>
    <!--1.计数器案例  -->
    <div>当前计数: {{counter}}</div>
    <div>当前计数*2: {{doubleCounter}}</div>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>
  </div>
</template>

<script>
  export default {
     data() {
       return{
         // 1.2计数器案例的逻辑代码   
         counter:100
       }
     },
     computed: {
       // 1.3计数器案例的逻辑代码 
       doubleCounter() {
          return this.counter * 2 
       }
     },
     methods: {
        // 1.4计数器案例的逻辑代码
        increment() {
           this.counter++;
        },
        decrement() {
           this.counter--;
        }
     }
  }
</script>

运行在浏览器的效果

下面我们再用Composition API来实现该功能。

代码如下所示

<template>
  <div>
    <!-- 1.计数器案例 -->
    <div>当前计数: {{counter}}</div>
    <div>当前计数*2: {{doubleCounter}}</div>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>
  </div>
</template>
<script>
  import { ref, computed } from 'vue';
  export default {
    setup() {
      // 1.1计数器案例的逻辑代码
      const counter = ref(100);
      const doubleCounter = computed(() => counter.value * 2);

      const increment = () => counter.value++;
      const decrement = () => counter.value--;
      return {
        counter,
        doubleCounter,
        increment,
        decrement
      }
    }
  }
</script>

保存代码,运行在浏览器的效果和Options API实现的效果一模一样。通过这两个案例,可以发现:

  • Options API的特点就是在对应的属性中编写对应的功能模块

  • 但Options API有一个很大的弊端是对应的代码逻辑被拆分到各个属性中,当组件变得更大、复杂时,同一个功能的逻辑会被拆分的很分散(如上面的计数器功能逻辑被拆分到各个选项中),不利于代码的阅读和理解。

  • Composition API的特点是能将同一个逻辑关注点相关的代码收集在一起,方便代码的封装和复用,也更利于代码的阅读和理解。

  • Composition API用了比较多的函数,用起来稍微比Options API复杂一点,但是函数式编程对TS支持更友好。

对比完Options API和Composition API编写计数器案例的优缺点之后,下面来看看如何对Composition API编写的代码逻辑进行封装和复用。在Options API编写方式中,我们已知道代码逻辑的封装和复用可以使用Mixin混入,那在Composition API中我们可以将关注点相关的代码逻辑封装到一个函数中,该函数我们一般会使用useXx来命名,并且以useXx开头的函数我们称之为自定义  Hook函数 

useCounter

认识Hook函数之后,下面我们来把上面计数器案例的代码逻辑封装到一个useCounter的Hook函数中。

封装useCounter Hook函数,代码如下所示:

import { ref, computed } from 'vue';

export default function useCounter() {
  // 1.1计数器案例的逻辑代码
  const counter = ref(100);
  const doubleCounter = computed(() => counter.value * 2);

  const increment = () => counter.value++;
  const decrement = () => counter.value--;

  return {
    counter, 
    doubleCounter, 
    increment, 
    decrement
  }
}

可以看到,我们在该文件中默认导出一个函数(也支持匿名函数),在该函数中我们把CompositionAPIExample组件实现计数器案例的代码逻辑全部抽取过来了。

接着修改CompositionAPIExample组件,代码如下所示:

<script>
  import useCounter from './hooks/useCounter'
  export default {
    setup() {
      // 1.计数器案例的代码逻辑抽取到useCounter hook 中了
      const {counter, doubleCounter, increment, decrement} = useCounter()

      return {counter, doubleCounter, increment, decrement}
    }
  }
</script>

可以看到,该组件之前实现计数器案例的逻辑代码已经抽取到了useCounter函数中,这时我们只要导入useCounter函数,并在setup中调用该函数便可以拿到返回的响应式数据和事件函数,然后直接返回给模板使用。保存代码,运行在浏览器的效果和没抽取前一模一样

useTitle

实现完计数器案例之后,在CompositionAPIExample组件中来实现修改网页标题的功能。修改CompositionAPIExample组件,代码如下所示:

<script>
  export default {
    setup() {
      // 修改网页的标题案例
      const titleRef = ref("coder");
      document.title = titleRef.value// 更新网页标题
  }
</script>

可以看到,只在CompositionAPIExample中的setup函数中添加两行代码即可以。保存代码,运行在浏览器的效果,已经将网页的标题修改为coder。

像这种修改网页标题的代码逻辑可能在其它组件中还会再次使用到,那么我们就可以将该功能封装到一个Hook函数中。

建立一个useTitle.js文件封装useTitle Hook函数,代码如下所示:

import { ref, watch } from 'vue';
// 使用匿名函数,并该函数需接收一个参数
export default function(title = "默认的title") {
  const titleRef = ref(title);
  // 侦听titleRef变化,一旦被修改就更新 
  watch(titleRef, (newValue) => {
    document.title = newValue 
  }, {
    immediate: true // 侦听的回调函数先执行一次
  })
  return titleRef
}

修改CompositionAPIExample组件,代码如下所示:

<script>
  import useTitle from './hooks/useTitle'
  export default {
    setup() {
     	
      // 修改网页的标题案例
      const titleRef = useTitle("coder");
      setTimeout(() => {
        //3秒后修改titleRef的值,useTitle函数的watch侦听到会修改标题    
        titleRef.value = "why" 
      }, 3000);
      
    }
  }
</script>

可以看到,我们先导入useTitle函数,接着在setup中调用useTitle函数初始化标题为coder,然后过了2秒之后将标题修改为why。保存代码,运行在浏览器后。网页的标题在3秒后有coder修改为why。

useScrollPosition

实现完修改网页的标题之后,我们接着继续再CompositionAPIExample组件中来实现监听页面滚动位置的功能。修改CompositionAPIExample组件,代码如下所示:

<template>
  <div>
    <!-- 显示页面滚动位置 -->
    <p style="width: 3000px;height: 5000px;">
      width:3000px  height:5000px的,模拟页面滚动
    </p>
    <div style="position: fixed;top:20px;right:20px">
      <div >scrollX: {{scrollX}}</div>
      <div >scrollY: {{scrollY}}</div>
    </div>
  </div>
</template>

<script>
 
  export default {
    setup() {
    
      // 监听页面滚动
      const scrollX = ref(0);
      const scrollY = ref(0);
      document.addEventListener("scroll", () => {
          scrollX.value = window.scrollX;
          scrollY.value = window.scrollY;
      });
      return {scrollX, scrollY}
    }
  }
</script>

可以看到,我们先在template中编写宽和高超出屏幕大小的p元素(模拟页面可滚动),接着在setup函数监听了页面的滚动,并在该回调函数中给scrollX和scrollY变量赋当前滚动的值。最后在return函数中返回scrollX和scrollY变量给temlpate来显示当前滚动的位置。保存代码,运行在浏览器的效果,上下滚动页面的时候,页面的右上角上能显示当前滚动位置值。

那如果该功能也会被再次使用到,我们依然可以将该功能封装到一个Hook函数中。

建立一个useScrollPosition.js文件封装useScrollPosition Hook函数,代码如下所示:


import { ref } from 'vue';
// 自定义 useScrollPosition Hook函数
export default function useScrollPosition() {
  const scrollX = ref(0);
  const scrollY = ref(0);

  document.addEventListener("scroll", () => {
    scrollX.value = window.scrollX;
    scrollY.value = window.scrollY;
  });

  return {scrollX, scrollY} // 返回ref响应式数据
}

修改CompositionAPIExample组件,代码如下所示:

<script>
  import useCounter from './hooks/useCounter'
  import useTitle from './hooks/useTitle'
  import useScrollPosition from './hooks/useScrollPosition'
  export default {
    setup() {
      // 1.计数器案例(可直接解构,如果返回的是reactive对象则不能直接解构使用)
      const {counter, doubleCounter, increment, decrement} = useCounter()
      // 2.修改网页标题案例
      const titleRef = useTitle("coder");
      setTimeout(() => {
        titleRef.value = "why"
      }, 3000);
        
      // 3.监听页面滚动位置案例 (可直接解构,因为Hook函数返回对象属性是ref对象)
      const { scrollX, scrollY } = useScrollPosition();
      return {counter, doubleCounter, increment, decrement, scrollX, scrollY}
    }
  }
</script>

可以看到,我们先导入useScrollPosition函数,接着在setup中调用useScrollPosition函数来获取到当前滚动的值。如果滚动页面了,useScrollPosition函数里会监听到并修改scrollX和scrollY响应式变量的值,同时更新页面。保存代码,运行在浏览器后。滚动网页时可以发现页面上右上角的scrollX和scrollY能显示当前滚动的位置。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值