【每日一题】vue Hooks 有哪些?

前端印记

共 5862字,需浏览 12分钟

 · 2021-08-24

人生苦短,总需要一点仪式感。比如学前端~

什么是 Hooks

hooks 字面意思就是钩子函数,那么钩子函数的定义是什么呢?

钩子函数:在一个事件触发的时候,在系统级捕获到了它,然后做一些操作。一段用以处理系统消息的程序。钩子就是在某个阶段给你一个做某些处理操作的机会-----类似回调函数。

钩子函数:

  • 一个函数/方法,在系统消息触发时被系统调用,例如onclick的函数值,当click事件触发的时候,函数会被调用。

  • 不是用户自己触发的,例如发布订阅者模式的方法的实现

  • 钩子函数的名称是确定的,当系统消息触发后,自动会调用

  • 例如Vue的watch()函数,用户只需要编写watch()的函数体里面的函数,当页面元素发生变化的时候,系统就会先调用watch()

  • 例如react的componentWillUpdate函数,用户只需要编写componentWillUpdate的函数体,当组件状态发生改变更新的时候,系统就会调用componentWillComponent

Vue Hooks 就是一些 vue 提供的内置函数,这些函数可以让 Function Component 和 Class Component 一样能够拥有组件状态(state)以及进行副作用(side effect)

为什么使用 Vue Hooks?

首先从 Class-component/Vue-options 开始说起

  • 跨组件代码难以复用

  • 大组件,维护困难,颗粒度不好控制,细粒度划分时,组件嵌套层次太深会影响性能

  • 类组件,this 不可控,逻辑分散,不容易理解

  • mixins 具有副作用,逻辑互相嵌套,数据来源不明,且不能互相消费

当一个模板依赖很多 mixin 的时候,很容易出现数据来源不清或者命名冲突的问题,而且开发 mixins 的时候,逻辑以及逻辑依赖的属性互相分散且 mixins 之间不可互相消费。这些都是开发中令人痛苦的点,因此 vue3.0 中引入 hooks 相关的特性非常明智

常用的 hooks 讲解

withHooks

const Foo = withHooks((h) => {
  // state
  const [count, setCount] = useState(0);

  // effect
  useEffect(() => {
    document.title = "count is " + count;
  });

  return h("div", [
    h("span"`count is: ${count}`),
    h(
      "button",
      {
        on: {
          click() => setCount(count + 1),
        },
      },
      "+"
    ),
  ]);
});

withHooks 是一个高阶函数,传入一个函数,这个函数内部返回一个 vnode,withHooks 方法返回的是一个 vue 的选项对象

Foo = {
  created() {},
  data() {},
  render() {},
};

这个选项对象可以直接调用 Vue.component 方法生成全局组件,或者在 render 方法中生成 vnode

useState

useState 理解起来很简单,和 Class Component 的 vuex 中 state 是一样的,都是用来管理组件状态的。

因为 Function Component 每次执行的时候都会生成新的函数作用域,所以同一组件的不同渲染(render)之间是不能够共用状态的。因此开发者一旦需要在组件中引入状态就需要将原来的 Funtion Component 改为 Class Component,这使得开发者的体验十分不好。

useState 就是用来解决这个问题的,它允许 Function Component 将自己的状态持久化到 vue 运行时的某个地方,这样在组件每次渲染的时候都可以从这个地方拿到该状态,而且当该状态被更新的时候,组件也会重渲染。

//声明
const [count, setcount] = useState(0)
const [state, setState] = useState({
    status'pending',
    datanull,
    errornull
})
const handleTextChange(value) => {
    setText({
        status'changed',
        data: value,
        errornull
    })
}
//引用
<div>{count}</div>
< ... onClick= setcount(count + 1) ... >
<div>{state}</
div>
onChange=handleTextChange(count)

useState 接收一个 initial 变量作为状态的初始值,返回值是一个数组。

  • 返回数组的第一个元素代表当前 state 的最新值
  • 第二个元素是一个用来更新 state 的函数。

这里要注意的是 state 和 setState 这两个变量的命名不是固定的,应该根据你业务的实际情况选择不同的名字,可以是 setA 或 setB,需要注意的是 setState 这个是全量替代

我们在实际开发中,一个组件可能不止一个 state,如果组件有多个 state,则在组件内部多次调用 useState,这些使用类似 Vuex 里面的 state 的使用方式

useEffect

useEffect 用于添加组件状态更新后,需要执行的副作用逻辑

// 语法
useEffect(() => {}, deps)

useEffect 指定的副作用逻辑,也就是其第一个参数(回调函数)的执行逻辑如下:

  • 会在组件挂载后执行一次
  • 在每次组件渲染后根据指定的依赖有选择地执行
  • 并在组件卸载时执行清理事件的逻辑

第二个参数 (deps)表示依赖项,若deps内的数据发生变化,则执行回调函数

import { withHooks, useState, useEffect } from "vue-hooks";

const Foo = withHooks((h) => {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = "count is " + count;
  });
  return h("div", [
    h("span", `count is: ${count}`),
    h("button", { on: { click: () => setCount(count + 1) } }, "+"),
  ]);
});

代码中,通过 useEffect 时,每当 count 的状态值发生变化时,都会重置 document.title。

这里没有指定 useEffect 的第二个参数 deps,表示只要组件重新渲染都会执行 useEffect 指定的逻辑,不限制必须是 count 变化时

useRef

useRef 是用来在组件不同渲染之间共用的一些数据的,它的作用和我们在 Vue Class Component 里面为$refs.xxx 赋值是一样的。那么它的一些特性就跟 refs 是类似:

  • 组件更新之后,可以获取最新的状态、值
  • 值不需要响应式处理
  • 独立于其他作用域之外,不污染其他作用域

useRef 返回的是对象,对象有一个current属性表示当前最新的状态、值

const [count, setcount] = useState(0);
const num = useRef(count);
const addCount = () => {
  let sum = count++;
  setcount(sum);
  num.current = sum;
  console.log(count, num.current);
};
//得到的结果是
// 0 1
// 1 2
// 2 3
// ...

useData

useData 可以理解为 Vue Class Funtion 里面的$data

也可以认为与 useState 类似。不同的是:它没有提供更新器,对外返回的数据发生变化时,有可能会丢失响应式监听。只是作为数据变量的声明、修改、调用

//声明
const data = useData({
  count0,
});
//调用
console.log(data.count);

官网的例子:只用来调用、生成新值用了。

useMounted

useMounted 需要在 mounted 事件中执行的逻辑

useMounted(() => {
  console.log("mounted!");
});

useDestroyed

useDestroyed 需要在 destroyed 事件中执行的逻辑

useDestroyed(() => {
  console.log("destroyed!");
});

最后贴一个在线测试地址:https://codesandbox.io/s/optimistic-river-rdv22?file=/src/index.js

点击“阅读原文”跳转到vue-hook仓库。



END
愿你历尽千帆,归来仍是少年。


让我们一起携手同走前端路!

长按下图识别二维码 关注公众号回复【加群】即可

● 工作中常见页面布局的n种实现方法

● 三栏响应式布局(左右固宽中间自适应)的5种方法

● 两栏自适应布局的n种实现方法汇总

● 工作中常见的两栏布局案例及分析

● 垂直居中布局的一百种实现方式

● 常用九宫格布局的几大方法汇总

● 为什么操作DOM会影响WEB应用的性能?

● 移动端滚动穿透的6种解决方案

● Vue + TypeScript 踩坑总结

浏览 108
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报