Vue3中使用hooks,hooks究竟是个啥?如何理解

news2025/1/21 12:09:04

1.前言

最近被hooks这个词老是被提出,我经常听到但是又不会用,于是乎抽时间认真学习一下。

2.vue3 hooks

2.1 为什么vue3 可以使用hooks

因为vue2由选项式Api转为组合式Api。底层源码改了好多。
组合式API的好处;
就是在函数内可以使用声明周期。

2.2使用hooks的好处与优点

无论是 vue 还是 react, 通过 Hooks 写法都能做到,将“分散在各种声明周期里的代码块”,通过 Hooks 的方式将相关的内容聚合到一起。
这句话让我豁然开朗。
因为以前vue2 选项式api把各个生命周期的东西分散开来,在写小项目的时候肯定是比较规范的。但是当项目大的时候,很多相似的业务确因为声明周期放在不同的模块里面。
使用了函数式API就我没有这个问题了。
在这里插入图片描述

将相同的功能卸载一起。并且每一个代码块里面可以使用声明周期函数。代码复用性直线提升。

3.hooks的起源

3.1区别函数式组件与类组件

最开始是react的东西;react之前的写法都是类组件。然后函数式组件是不能有状态的。不能调用声明周期函数。

//1.创建函数式组件
		function MyComponent(){
			console.log(this); 
    //此处的this是undefined,因为babel编译后开启了严格模式,严格模式最大的特点就是禁止自定义的函数中this指向window
			return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
		}
		//2.渲染组件到页面,如果第一个参数直接传入函数名会报函数类型不能作为React的节点错误,必须以标签的形式传入而且如果名字是小写的话会报当前这个标准在浏览器中不被允许,因为如果是小写的标签会被转成html标签,但是html中并没有此标签,还要注意标签必须要闭合
		ReactDOM.render(<MyComponent/>,document.getElementById('test'))

函数式组件

//1.创建类式组件,1、必须要继承React.Component,2、必须要有render函数,3、render函数中必须要返回值 
		class MyComponent extends React.Component {
			render(){
				//render是放在哪里的?—— MyComponent的原型对象上,供实例使用。但是有个问题就是我们并没有手动去new MyComponent这个实例,但是下面的ReactDOM.render函数中写了组件标签后React会自动的帮我们创建实例
				
				//render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。
				console.log('render中的this:',this);
				return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
			}
		}
		//2.渲染组件到页面
		ReactDOM.render(<MyComponent/>,document.getElementById('test'))

类组件

3.2 useState 与useEffect

useState: 函数式组件里面的通过这个钩子函数调用state(等同与vue2里面的data,就是挂载的数据)。完成状态改变的操作

import React, { useState } from 'react';
 
function CounterWithHooks(props) {
	const [count, setCount] = useState(props.initialValue);
 
	return (
		<div>
			<h2>This is a counter using hooks</h2>
			<h1>{count}</h1>
			<button onClick={() => setCount(count + 1)}>Click to Increment</button>
		</div>
	);
}
 
export default CounterWithHooks;

useEffect 声明周期了 相当于声明周期钩子,不太懂;对react了解少。

import React, { Component } from 'react';
 
class App extends Component {
	componentDidMount() {
		console.log('I have just mounted!');
	}
 
	render() {
		return <div>Insert JSX here</div>;
	}
}

function App() {
	useEffect(() => {
		console.log('I have just mounted!');
	});
 
	return <div>Insert JSX here</div>;
}

4.vue 3中的组合式函数

从vue3 官网上面取例子。在 Vue 应用的概念中,“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。
鼠标跟踪器示例

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const x = ref(0)
const y = ref(0)

function update(event) {
  x.value = event.pageX
  y.value = event.pageY
}

onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

但是,如果我们想在多个组件中复用这个相同的逻辑呢?我们可以把这个逻辑以一个组合式函数的形式提取到外部文件中:

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 通过返回值暴露所管理的状态
  return { x, y }
}

在组件中的使用

<script setup>
import { useMouse } from './mouse.js'

const { x, y } = useMouse()
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

5.开源项目中vue3 中hook的应用;

开源项目地址 https://github.com/fect-org/fect

5.1 vue3 使用useState

该作者在vue3 中使用hooks的实践

import { ref, readonly } from 'vue'
import type { UnwrapRef, Ref, DeepReadonly } from 'vue'

export type SetStateAction<S> = S | ((prevState: S) => S)

export type Dispatch<T> = (val: SetStateAction<T>) => void

const useState = <T>(initial?: T) => {
  const state = ref<T | undefined>(initial)
  const dispatch = (next: SetStateAction<T>) => {
    const draft = typeof next === 'function' ? (next as (prevState: T) => T)(state.value as T) : next
    state.value = draft as UnwrapRef<T>
  }
  return [readonly(state), dispatch] as [DeepReadonly<Ref<T>>, Dispatch<T>]
}

export { useState }

具体使用

import { useEventListener, useState } from '@fect-ui/vue-hooks'
  //===============
  setup(props, { slots, emit }) {
    const affixRef = ref<HTMLElement>()

    const [fixed, setFixed] = useState<boolean>(false)
    const [style, setStyle] = useState<AffixLayout>({ width: 0, height: 0 })

    const offset = computed(() => convertUnitToPx(props.offset))

    const scrollHandler = () => {
      if (!affixRef.value || isHidden(affixRef)) return
      const { position } = props
      const affixRect = getDomRect(affixRef)
      const scrollTop = getScrollTop(window)
      setStyle({
        width: affixRect.width,
        height: affixRect.height
      })
      if (position === 'top') {
        setFixed(() => offset.value > affixRect.top)
      }
      if (position === 'bottom') {
        const { clientHeight } = document.documentElement
        setFixed(() => clientHeight - offset.value < affixRect.bottom)
      }

5.2思考我们应用如何应用
当项目小的时候我们大概率是用不上了 。比如一个简单的登录和注册。大概率是应用不上了。

import { reactive, toRefs } from 'vue'
import { login, register } from '@/service/user'
import { setLocal } from '@/common/js/utils'
import { Toast } from 'vant'

export default {
  setup() {
    
    const state = reactive({
      username: '',
      password: '',
      email1: '',
      username1: '',
      password1: '',
      type: 'login',
      verify: ''
    })

    // 切换登录和注册两种模式
    const toggle = (v) => {
      state.type = v
      state.verify = ''
    }
  
    // 提交登录或注册表单
    const onSubmit = async (values) => {
   
      if (state.type == 'login') {
        const  data  = await login({
          "email": values.username,
          "password": values.password
        })
        console.log("token",data)
        setLocal('token', data.content)
        
        // 需要刷新页面,否则 axios.js 文件里的 token 不会被重置
        window.location.href = '/'
        
      } else {
        await register({
          "username": values.username1,
          "password": values.password1,
          "email":values.email1
        })
        Toast.success('注册成功')
        state.type = 'login'
        state.verify = ''
      }
    }
    return {
      ...toRefs(state),
      toggle,
      onSubmit,
  
    }
  }

}
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/408557.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用pynecone开发python web应用

环境•windows 10 64bit•python 3.8.15•pynecone 0.1.14简介Pynecone 是一个基于纯 python 的用于开发 web app 的开源框架&#xff0c;它依赖于 nodejs&#xff0c;不过不需要另外编写前端代码&#xff0c;这对于没有接触过前端的朋友是非常友好的。安装第一步&#xff0c;安…

Vue项目常见的错误以及解决办法

错误分类 vue项目中遇到的问题大体上分为两类&#xff1a;一类是基础的语法错误&#xff0c;另一类就是其它错误 这里简单分享以下我在项目中遇到的错误和解决办法&#xff0c;如果你也有&#xff0c;希望对你会有帮助 GET http://dida100.com:8888/api/cart 401 (Unauthoriz…

【前端修炼场】 — HTML常用的标志语言

此文为【前端修炼场】第三篇&#xff0c;上一篇文章链接&#xff1a;上一篇 文章目录前言标志语言基本结构介绍声明介绍标签修饰编码形式常用HTML标签标题标签段落标签换行标识水平线标识加粗标识倾斜标识删除线标识下划线标识上标 / 下标标识总结前言 之前我们使用过的那些标…

React 面向组件编程(上)

目录前言&#xff1a;一、组件的基本理解和使用1. 函数式组件2. 类式组件3. 注意事项4. 渲染函数式组件标签的基本流程5. 渲染类组件标签的基本流程二、组件三大核心属性 1&#xff1a;state1. 代码示例2. 效果展示3. 注意4. 设置状态:setState三、 组件三大核心属性 2&#xf…

小程序问题:封装公共组件的onLoad方法不生效

素材编辑 | 宋大狮 排版运营 | 小唐狮 ONE 问题描述 因为许久没有接触小程序项目&#xff0c;今天在做小程序项目时&#xff0c;为了节省时间&#xff0c;将要修改的页面组件直接拿出来封装成了公共组件&#xff0c;同时也没多想就直接使用了。于是就出现了页面数据不能加载的…

模板字符串基本使用

模板字符串是ES6添加的一个新的字符串编写形式。 1.【模板字符串】之拼接 在ES6之前&#xff0c;如果我们想要将字符串和一些动态的变量拼接到一起&#xff0c;是很麻烦的。 const name "aaa" const age 18console.log("my name is "name".Im &q…

三个案例掌握this.$nextTick()方法的使用/Vue中的$nextTick()

this.$nextTick() 解释为在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的DOM. 也就是说&#xff0c;当dom元素发生改变&#xff0c;重新渲染dom树后&#xff0c;再执行vue.$nextTick()里面的内容。 其实用方法一般为 this.$n…

讲讲vue3下会造成响应式丢失的情况

题引&#xff1a; 在我们从vue2过渡到vue3的时候&#xff0c;对于数据响应式的变化其实是懵懵懂懂的。从以往直接在data函数里面定义变量到每一次都要使用ref/reactive时&#xff0c;是有些不适应的。但问题不大&#xff0c;毕竟在大前端时代中&#xff0c;如果不及时跟上时代…

TS中快速定义一个对象数组以及处理async await的异常

定义一个对象数组&#xff08;即数组成员为对象&#xff0c;对象的属性为我们所约束&#xff09; 方法一&#xff1a;接口字面量形式 export type Resource {_id: string,personID: {_id: stringage: stringidentifier: stringname: stringnation: stringgrade: stringscheme…

contentEditable属性

前言 我们最常用的输入文本内容便是input与textarea&#xff0c;但是有一个属性&#xff0c;可以让我们在很多标签中&#xff0c;如div,table,p,span,body等&#xff0c;可以像input输入框一样&#xff0c;实现文本编辑&#xff0c;这便是contentEditable属性 contentEditabl…

【vue2】近期bug收集与整理01

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;记录博主在vue2中遇到过的坑&#xff0c;本文是博主的学习使用总结 目录 1登陆token的问…

【学姐面试宝典】前端基础篇Ⅴ——JS深浅拷贝、箭头函数、事件监听等

前言 博主主页&#x1f449;&#x1f3fb;蜡笔雏田学代码 专栏链接&#x1f449;&#x1f3fb;【前端面试专栏】 今天继续学习前端面试题相关的知识&#xff01; 感兴趣的小伙伴一起来看看吧~&#x1f91e; 文章目录什么是事件监听事件委托以及冒泡原理介绍一下 promise&#x…

uniapp 小程序嵌套H5开发总结

项目需求是在uniapp小程序项目中嵌套H5页面&#xff0c;H5返回小程序需要传值给小程序进行通信。 好,百度一查确实可以实现 用的uniapp提供的web-view&#xff08;https://uniapp.dcloud.io/component/web-view.html#web-view经验证实&#xff0c;做功能之前先看官网&#xff…

一天时间迅速准备前端面试|JavaScript——异步进阶

&#x1f308;本系列文章是博主精心整理的面试热点问题&#xff0c;吸收了大量的技术博客与面试文章&#xff0c;总结多年的面试经历&#xff0c;带你快速建立前端面试知识体系。抓住每一场面试的机会&#xff0c;知己知彼才能百战百胜&#xff01; 上期回顾 JS基础–异步 本系…

【中秋快乐】如何用three.js实现我的太空遐想3D网页

目录 创作背景 功能分解 创建3d地球 创建3d月球 创建3d小火箭

解决element-ui动态加载级联选择器默认选中问题(Cascader)

前言 最近在开发任务中碰到需要在新增和修改时使用动态加载级联选择器&#xff0c;但是当在修改时设置默认选中项&#xff0c;出现了后端数据返回较慢&#xff0c;导致无法选中和级联框选中了但input框不显示的问题&#xff0c;网上找到的方法也不是很有效&#xff0c;还得使用…

Vue - v-for 循环渲染多个 “重复“ 子组件(仅 ref 不同,this.$refs.xx 使用时依然能准确找到子组件)将子组件 ref 设为动态,这样每个子组件都是 “独立“ 的!详细教程

前言 本教程更多版本:uni-app | 微信小程序 我们会通过给组件绑定 ref 值,然后通过 this.$refs.xx 来获取这个组件上的方法和变量。 如果 在 v-for 中循环渲染组件(绑定固定 ref),那么这个 ref 就会 “一摸一样”,导致根本无法找到(this.$refs.xx 谁?), 要解决这个问…

【前端】vue模板语法知识了解一下,是不是只知道用element-ui组件?

vue写在前面Vue模板语法文本原始HTML属性开源Vue模板和主题框架集合BootstrapVueelement-ui最后总结写在前面 上一篇总结了在实操过程中如果遇到了nodejs版本的问题&#xff0c;我们该如何去解决的&#xff0c;还有就是总结了vue2和vue3生命周期的区别&#xff0c;如果感兴趣的…

【JavaScript】JS实用案例分享:动态生成分页组件 | 通过按键实现移动控制

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 &#x1f5a5;️ NodeJS专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ 博主的前端之路&#xff08;源创征文一等奖作品&#xff09;&#xff1a;前端之行&#xff0c;任重道远&#xff08;来自大三学长的万字自述&am…

React 路由v6 - 超全详解

React router v6 路由 已经习惯了 v5 版本的路由 &#xff0c;那么 v6 版本的路由 该怎么应用呢&#xff1f; 文章目录React router v6 路由Ⅰ、路由 v6 (两种形式)Ⅱ、 动态路由Ⅲ、路由重定向Ⅳ、路由跳转 (两种形式)Ⅴ、路由懒加载Ⅰ、路由 v6 (两种形式) 方案一 &#xff…