草庐IT

vue3与react、 react hooks

月光一族 2023-03-28 原文

一、Vue3新特性:setup、ref、reactive、computed、watch、watchEffect函数、生命周期钩子、自定义hooks函数、toRef和toRefs、shallowReactive 与 shallowRef、readonly 与 shallowReadonly、toRaw 与 markRaw、customRef、provide 与 inject、Fragment、Teleport、Suspense、data选项应始终被声明为一个函数

2、setup是所有composition  API(组合式api)展示的舞台, 返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用,setUp(props, contex)接受两个参数,props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性(其实就是vue2.0的props功能),context:上下文对象(其中可以获取到1、attrs组件外部传递过来,但没有在props配置中声明的属性。2、slots:插槽内容3、emit:分发自定义事件的函数,并且以后在setup中不能写this.$emit,要写context.emit)

3、ref一般用来定义一个基本类型的响应式数据, reactive定义一个响应式源对象,接收一个普通对象然后返回该普通对象的响应式代理器对象,响应式转换是“深层的”:会影响对象内部所有嵌套的属性,内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据都是响应式的;watch默认是惰性的,watchEffect默认立即执行;watch可以获取到当前值和之前值,watchEffect只能获取当前值;watch可以传递多个函数作为参数,watchEffect只需要传递一个回调函数

4、

(1)、vue2响应式原理:

核心:

对象: 通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)

数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持

(2)、Vue3的响应式原理:

核心:

通过Proxy(代理):拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等…

通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作

5、生命周期:

为什么要在生命周期前加"on"?

因为setup是围绕beforeCreate和created生命周期来运行的,所以不需要显式地定义它们,这些生命周期函数接受一个回调函数,当钩子被组件调用时将会被执行。

beforeCreate -> 使用 setup()

created -> 使用 setup()

beforeMount -> onBeforeMount

mounted -> onMounted

beforeUpdate -> onBeforeUpdate

updated -> onUpdated

beforeDestroy -> onBeforeUnmount

destroyed -> onUnmounted

errorCaptured -> onErrorCaptured

1.vue3中已经没有destroyed 和beforeDestroy 了

2.vue3也可以用vue2的生命周期,vue3生命周期比vue2快

6、自定义hook函数

什么是hook? ----本质是一个函数,把setup函数中使用的composition API进行了封装

类似于vue2中的mixin

自定义hook的优势:复用代码,让setup中的逻辑更清晰易懂

(1)、基础封装hooks

//定义的hooks

import {reactive,onMounted,onBeforeUnmount} from 'vue'

export default function(){

    let point=reactive(

        {

            x:0,

            y:0

        }

    )

    function sponk(event){

        console.log(point);

        point.x=event.pageX;

        point.y=event.pageY;

        console.log(event);

    }

    onMounted(()=>{

        console.log('onMounted');

        document.getElementById('HelloWorld').addEventListener('click',sponk)

    })

    onBeforeUnmount(()=>{

        console.log('onBeforeUnmount');

        document.getElementById('HelloWorld').removeEventListener('click',sponk)

    })

    return point;

}

//使用hooks的组件

<template>

  <div class="hello" id="HelloWorld">

    x轴位置:{{valz.x}}<br/>

    y轴位置:{{valz.y}}<br/>

  </div>

</template>

<script>

  //引入定义的hooks

  import point from './../hook/commonFirst'

  export default {

    name: 'HelloWorld',

    props: {

      msg: String

    },

    setup(){

      console.log('---setup---');

      //触发执行此方法即可

      let valz=point()

      return{

        valz

      }

    },

}

</script>

(2)、 封装发 axios 请求的 hook 函数

hooks/useRequest.ts

import { ref } from 'vue'

import axios from 'axios'

/*

使用axios发送异步ajax请求

*/

export default function useUrlLoader<T>(url: string) {

  const result = ref<T | null>(null)

  const loading = ref(true)

  const errorMsg = ref(null)

  axios

    .get(url)

    .then(response => {

      loading.value = false

      result.value = response.data

    })

    .catch(e => {

      loading.value = false

      errorMsg.value = e.message || '未知错误'

    })

  return {

    loading,

    result,

    errorMsg

  }

}

<template>

  <div class="about">

    <h2 v-if="loading">LOADING...</h2>

    <h2 v-else-if="errorMsg">{{ errorMsg }}</h2>

    <!-- <ul v-else>

    <li>id: {{result.id}}</li>

    <li>name: {{result.name}}</li>

    <li>distance: {{result.distance}}</li>

  </ul> -->

    <ul v-for="p in result" :key="p.id">

      <li>id: {{ p.id }}</li>

      <li>title: {{ p.title }}</li>

      <li>price: {{ p.price }}</li>

    </ul>

    <!-- <img v-if="result" :src="result[0].url" alt=""> -->

  </div>

</template>

<script lang="ts">

import { watch } from 'vue'

import useRequest from './hooks/useRequest'

// 地址数据接口

interface AddressResult {

  id: number

  name: string

  distance: string

}

// 产品数据接口

interface ProductResult {

  id: string

  title: string

  price: number

}

export default {

  setup() {

    // const {loading, result, errorMsg} = useRequest<AddressResult>('/data/address.json')

    const { loading, result, errorMsg } = useRequest<ProductResult[]>('/data/products.json')

    watch(result, () => {

      if (result.value) {

        console.log(result.value.length) // 有提示

      }

    })

    return {

      loading,

      result,

      errorMsg

    }

  }

}

</script>

其他可以查看从0到1学vue3_山竹回家了的博客-CSDN博客_vue3


下面写一下vue3、react hooks原理及其区别

vue3 带来的六大新特性

Performance:性能比vue2.x块1.2~2倍

Tree shaking support:支持按需编译,体积更小

Composition API:组合API,类似React Hooks

Custom Renderer API:暴露了自定义渲染API

Fragment,Teleport(Protal),Suspense:新增三个组件

Better TypeScript support:更好的支持TS

Performance

Vue3.0在性能方面比Vue2.x快了1.2~2倍。

重写虚拟DOM的实现

运行时编译

静态提升与事件侦听器缓存

SSR 速度提高

Three-shaking support

Vue3.x中的核心API都支持tree-shaking,这些API都是通过包引入的方式而不是直接在实例化时就注入,只会对使用到的功能或特性进行打包(按需打包),这意味着更多的功能和更小的体积。

Composition API

Vue2.x中,我们通常采用mixin来复用逻辑代码,使用起来虽然方便,但也存在一些问题:代码来源不清晰、方法属性可能出现冲突。因此,Vue3.x引入了Composition API(组合API),使用纯函数分割复用代码。和React Hooks的概念相似。

更好的逻辑复用和代码组织

更好的类型推导

Fragment、Teleport、Suspense

新增三个组件。

Fragment

在书写Vue2.x时,由于组件必须是一个根结点,很多时候会添加一些没有意义的节点用于包裹。Fragment组件就是用于解决这个问题的(这和React 中的Fragment组件是一样的)。

Teleport

Teleport其实就是React中的Portal。Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。

一个 portal 的典型用例是当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框。

Suspense

同样的,这和React中的Supense是一样的。

Suspense 让你的组件在渲染之前进行“等待”,并在等待时显示 fallback 的内容。

Vue3.0 是如何变快的

diff 算法优化

Vue2 中的虚拟dom 是进行全量对比

Vue3 新增静态标记,这和react的fiber类似,都是打tag

hoistStatic 静态提升

Vue2 中无论元素是否参与更新,每次都会重新创建,然后在渲染

Vue3 中对于不参与更新的元素,会做静态提升,只被创建一次,在渲染时直接复用即可

cacheHandlers 事件侦听器缓存

默认情况下默认情况下onClick会被视为动态绑定,所以每次都会去追踪它的变化,但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可

ssr 渲染

当有大量静态的内容的时候,这些内容会被当作纯字符串推进一个buffer里面,即使存在动态的绑定,会通过模版插值嵌入进去,这样会比通过虚拟dom来渲染的快上很多很多

当静态内容大到一定量级的时候,会用_createStaticVNode方法在客户端去生成一个static node。这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染。

vue3底层设计思想:

1.浏览器性能提升

  首先,随着ES6的发展已及广泛使用,浏览器对这些新的特性逐渐增加,性能不断优化,这就给vue3优化提供了一个机会,通过重写来优化提升vue的性能。

2、底层实现方法

在框架设计上,vue2.0 是采用Object.defineProperty来实现双向绑定原理,这个属性本身就存在一些不足的地方,比如:

1.Object.defineProperty无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。 为了解决这个问题,经过vue内部处理后可以使用以下几种方法来监听数组,push(),pop(),shift(),unshift(),splice(),sort(),reverse();由于只针对了以上八种方法进行了hack处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。

  2.Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择,新增的属性还行通过set方法来添加监听,有一定的局限性。

  vue3主要采用的Proxy特性,有以下优点:

  1.可以劫持整个对象,并返回一个新的对象

  2.有13种劫持操作,但同时Proxy作为ES6的新特性,有一定的兼容问题,最主要的是这个属性无法用polyfill来兼容,这个需要在vue3中需要解决的问题。

React原理分析:

实现和更新原理

React将每个节点转化为fiber对象,最终形成一个fiber树结构,来依次渲染。通过两个fiber的对比来实现更新。这里要说到几个diff算法,分别是tree diff,component diff和element diff。同时更新过程可能会被打断,让优先级更高的任务优先执行(例如浏览器渲染)

Tree diff

新旧两个DOM树,逐层对比的过程;当整个DOM树逐层对比完毕,则所有需要被更新的元素必然能被找到;

Component diff

在进行Tree Diff的时候,每一层中,组件级别的对比。如果对比前后,组件的类型相同,则暂时认为此组件不需要被更新;如果对比前后,组件类型不同,则需要移除旧组件,创建新组件,并追加到页面上;

Element diff

在进行组件对比的时候,如果两个组件类型相同,则需要进行元素级别的对比,叫做element diff;

React 原理分析(一) —— React 设计思想 - 掘金 (juejin.cn)

React 源码分析(二)—— Fiber 的 render 阶段 - 掘金 (juejin.cn)

React 原理分析(三)—— Fiber 的commit 阶段 - 掘金 (juejin.cn)

vue与react的区别:

1、Vue和React存在着很多的共同点:

数据驱动视图

组件化

都使用Virtual DOM

2、核心思想不同

vue的主要特点:灵活易用的渐进式框架,进行数据拦截/代理,它对侦测数据的变化更敏感、更精确。

Reactt推崇函数式编程(纯组件),数据不可变以及单向数据流,当然需要双向的地方也可以手动实现, 比如借助onChange和setState来实现。

由于两者核心思想的不同,所以导致Vue和React在后续设计产生了许多的差异。

3、组件写法差异

Vue 推荐的做法是 template 的单文件组件格式(简单易懂,从传统前端转过来易于理解),即 html,css,JS 写在同一个文件(vue也支持JSX写法)

React推荐的做法是JSX + inline style, 也就是把 HTML 和 CSS 全都写进 JavaScript 中,即 all in js

这个差异一定程度上也是由于二者核心思想不同而导致的。

4.、响应式原理不同

Vue依赖收集,自动优化,数据可变。Vue递归监听data的所有属性,直接修改。当数据改变时,自动找到引用组件重新渲染。

React基于状态机,手动优化,数据不可变,需要setState驱动新的state替换老的state。当数据改变时,以组件为根目录,默认全部重新渲染, 所以 React 中会需要 shouldComponentUpdate 这个生命周期函数方法来进行控制




vue3.2中的defineProps、defineEmits、defineExpose,方便使用

vue3.2中的defineProps、defineEmits、defineExpose - 简书 (jianshu.com)

有关vue3与react、 react hooks的更多相关文章

  1. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  2. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  3. (附源码)vue3.0+.NET6实现聊天室(实时聊天SignalR) - 2

    参考文章搭建文章gitte源码在线体验可以注册两个号来测试演示图:一.整体介绍  介绍SignalR一种通讯模型Hub(中心模型,或者叫集线器模型),调用这个模型写好的方法,去发送消息。  内容有:    ①:Hub模型的方法介绍    ②:服务器端代码介绍    ③:前端vue3安装并调用后端方法    ④:聊天室样例整体流程:1、进入网站->调用连接SignalR的方法2、与好友发送消息->调用SignalR的自定义方法 前端通过,signalR内置方法.invoke()  去请求接口3、监听接受方法(渲染消息)通过new signalR.HubConnectionBuilder().on

  4. ruby - 单个 EventMachine react 器中的多个服务器 - 2

    是否可以在单个事件机器中运行多个服务器?我的意思是,多个服务可以由一个客户端连接同时使用。例如,登录服务器对用户进行身份验证,然后用户可以同时使用聊天室和简单的游戏,例如带有单个客户端套接字的跳棋?或者我是否需要为每个服务使用多个事件机器react器? 最佳答案 我试过了,它正在工作:#!/usr/bin/envrubyrequire'eventmachine'moduleEchoServerdefpost_initputs"--someoneconnectedtotheechoserver!"enddefreceive_datad

  5. vue 实现内容超出两行显示展开更多功能,可依据需求自定义任意行数! - 2

    平时开发中我们经常会遇到这样的需求,在一个不限高度的盒子中会有很多内容,如果全部显示用户体验会非常不好,所以可以先折叠起来,当内容达到一定高度时,显示展开更多按钮,点击即可显示全部内容,先来看看效果图: 这样做用户体验瞬间得到提升,接下来看看具体细节。0">主要操作在内容这里{{item.username}},……展开更多样式大家可依据自己项目需求进行设计,这里就不贴了,主要说几个关键的。1、在data中定义三个属性isShowMore:false, //控制展开更多的显示与隐藏textHeight:null, //框中内容的高度status:false, //内容状态是否打开2.计算内容是否

  6. vue3.0 + vite2.0+如何兼容低版本浏览器 - 2

    这里写自定义目录标题一、问题二、解决三、解决方案四、打包预览一、问题在使用vue3.2和vite2开发一个移动端或者钉钉端H5微服务iosapp内置浏览器打开没问题安卓app内置浏览器打开空白页面vconsole打印出现报错globalthisundefind二、解决内置浏览器版本比较低打印出来是63vue3代码不兼容低版本浏览器三、解决方案步骤一:vite.config.ts里build.target配置项指定构建目标为es2015或者步骤二:安装@vitejs/plugin-legacy安装完报错也还在指定版本可以解决“@vitejs/plugin-legacy”:“1.8.0”,步骤三:

  7. Vue3的新特性 - 2

    Vue3的新特性包括:CompositionAPI:一种新的API风格,可将有关组件功能的代码逻辑封装在单独的函数中,从而更好地管理和重用代码。Teleport:可以让组件在DOM层次结构中的任何位置渲染。Suspense:一种新的异步渲染模式,可以优化应用程序的性能。更快的渲染速度:Vue3使用了新的虚拟DOM算法,并且对渲染过程进行了优化,因此在渲染大型应用时性能更高。更小的包大小:Vue3的打包大小比Vue2更小,因为它不再需要依赖像vue-template-compiler这样的工具。其他改进:Vue3还具有其他一些改进,例如更好的TypeScript支持、更好的错误提示和更好的调试工

  8. React通过classnames库添加类 - 2

    React添加Class的方式在vue中添加class是一件非常简单的事情:你可以通过传入一个对象,通过布尔值决定是否添加类:button:class="{active:isFlag,aaa:true}">按钮button>你也可以传入一个数组:h2:class="['aaa','bbb']">HelloVueh2>h2:class="[className1,className2]">HelloVueh2>甚至是对象和数组混合使用:h2:class="['aaa',{active:isFlag}]">HelloVueh2>而在React中就相对繁琐了,React在JSX给了我们开发者足够多的灵

  9. 如何使React Router V4路由与React Transition Group(低级API)一起使用 - 2

    从ReactRouterV3过渡到V4后,我再也无法使ReactTransition组低级API工作。React路由器的文档显示了与CSS动画相关的高级API的示例,这些示例与低水平的JS风味不起作用。任何人都设法或知道让这个工作?看答案已经一个月了,所以我想您找到了自己的出路,但可能会对他人有所帮助。我创建了这个:https://www.npmjs.com/package/reeact-router-v4-transition在我遇到同样的问题之后。它在开关组件中提供了一种过渡组。从将开关更改为TransitionSwitch的Appart,它不需要大幅度更改。我将在接下来的几天(可能是星期

  10. vue2+element-ui,el-aside侧边栏容器收缩与展开 - 2

    一、概览实现效果如下:二、项目环境1、nodejs版本node-vv16.16.02、npm版本npm-vnpmWARNconfigglobal`--global`,`--local`aredeprecated.Use`--location=global`instead.8.15.03、vue脚手架版本vue-V@vue/cli5.0.8三、创建vue项目1、创建名为vuetest的项目vuecreatevuetest选择Default([Vue2]babel,eslint)  2、切换到项目目录,启动项目cdvuetestnpmrunserve 3、使用浏览器预览 http://localh

随机推荐