vue3与react、 react hooks

一、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)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容