用React.js写法改写Vue写法的教程(一)

AI 概述
数据 data,在 react 中叫 stateVue2.0 中的用法Vue3 中的用法基础用法响应数据修改React 中的用法侦听器 watchVue2.0 中的写法Vue3.0 中的写法React 中的写法计算属性,在 React 中我也找到的踪迹Vue2.0 中的写法Vue3.0 中的写法React 中的写法结语 我在日常工作中使用的最多的是 Vue,对于 React 只...
目录
文章目录隐藏
  1. 数据 data,在 react 中叫 state
  2. 侦听器 watch
  3. 计算属性,在 React 中我也找到的踪迹
  4. 结语

用 React.js 写法改写 Vue 写法的教程(一)

我在日常工作中使用的最多的是 Vue,对于 React 只是做过简单的了解,并没有做过深入学习。最近工作不算太忙,于是乎决定好好学一学 React,今天这篇文章就是我在学习 React 之后,将 React 与 Vue 的用法做的一个对比,通过这个对比,方便使用 Vue 的小伙伴可以快速将 Vue 中的写法转换为 React 的写法。好了,废话不多说,一起看看吧!

数据 data,在 react 中叫 state

熟悉vue的小伙伴一定对Vue中的data不会感到陌生的,反正天天写Bug的时候都要用,但是对于data来说,在Vue2.0,Vue3.0,React中用法是不同的,我们下面依次举例说明。

Vue2.0 中的用法

如下代码是一个比较简单的Vue2.0data用法

<template>
  <div>{{ name }}</div>
</template>
<script>
export default {
  data() {
    return {
      name: '码云笔记',
      mybj: 'mybj123.com'
    }
  }
}
</script>

通过上面的代码我们可以看到data是一个函数,然后函数中返回了一个对象,那么为什么data是一个函数呢?比如我们有时候也会在App.vue文件中看到data不是函数的情况。

<template>
    <div id="app">
    <router-view />
  </div>
</template>
<script>
export default {
  data:{
    name: '码云笔记',
    sex: '男'
  }
}
</script>

那么为什么我们在普通组件里面还要将data声明为函数呢?Vue 官网是这样解释的:当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。

App.vue可以将data声明为一个普通对象是因为整个系统中App.vue只会被使用到一次,所以不存在上述的问题。

Vue3 中的用法

Vue3中,我们依然可以像Vue2那样去使用data,当然Vue3提供了新的Composition API,在后续文章中,如果没有特殊说明,我们提到Vue3就默认指的是使用Composition API

Composition API提供了响应式API,分别是refreactive,通过这两个API可以生成响应式的数据

基础用法

<template>
  <div class="home">
    <div>姓名:{{ state.name }}</div>
    <div>域名:{{ state.mybj }}</div>
    <div>统计:{{ count }}</div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, ref } from "vue";

export default defineComponent({
  name: "Home",
  setup() {
    const state = reactive({
      name: "码云笔记",
      mybj: "mybj123.com"
    });
    const count = ref(0);
    return {
      state,
      count
    };
  }
});
</script>

响应数据修改

Vue2.0中,我们修改data的方式一般会使用this.name = '张三'这种赋值的方式,但是对于Composition API中因为提供了两种api,所以用法稍有区别

<template>
  <div class="home" @click="handleClick">
    <div>姓名:{{ state.name }}</div>
    <div>域名:{{ state.mybj }}</div>
    <div>统计:{{ count }}</div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, ref } from "vue";

export default defineComponent({
  setup() {
    const state = reactive({
      name: "码云笔记",
      mybj: "mybj123.com"
    });
    
    const count = ref(0);
    
    function handleClick() {
      state.name = "张三";
      count.value++;
    }
    
    return {
      state,
      count,
      handleClick
    };
  }
});
</script>

如上代码所示:

  • 对于reactive声明的数据对于reactive,我们可以通过state.name来获取数据,然后通过state.name='张三'来修改数据
  • 对于ref声明的数据对于ref声明的数据,ref接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value。所以我们在代码中获取ref对象的数据需要使用count.value的方式,修改值的方式也需要通过count.value++的方式。但是这里有一个特殊的点就是在template,ref对象会自动解套,意思就是对于<div>统计:{{ count }}</div>,代码里面可以直接使用count,而不需要写成count.valueVue自己就会将其解套为count.value

React 中的用法

React16.8新增了Hook特性,现在许多团队已经大规模使用了,所以本文的内容更多的是以Hook为主。

Vue3.0中提供了Composition API,其实这个和Reacthook用法是很相似的,接下来我们将上文中我们写的Vue3.0代码修改为React版本

import React, { useState } from 'react'

export default function() {
  // useState 传入要初始化的状态数据,然后会返回一个数组
  // 数组第一项为声明的数据,而第二个参数是一个方法,用于调用
  // 修改数据
 const [name, setName] =  useState('码云笔记')
 const [gzh] = useState('码云笔记')

 function handleClick() {
   // 在 react 修改数据需要调用 useState 返回的方法
   setName('张三')
 }

  return (
    <div onClick={handleClick}>
      <div>姓名:{name}</div>
      <div>公众号: {gzh}</div>
    </div>
  );
}

在这段代码中我们使用到了useState声明了一个state变量,useState返回的值是一个数组,然后我们通过数组解构获取到了两个变量, const [name, setName] = useState('码云笔记'), 其中name对应声明的state变量,而setName是一个函数,调用setName可以修改变量的值,比如setName('张三'),这时候name的值就会变成了张三

侦听器 watch

我在平常开发中是比较常用watch的,使用watch可以去监听数据的变化,然后在变化之后做一系列的操作。比如有一个列表页,我们希望用户在输入搜索关键字的时候,可以自动触发搜索。此时除了监听输入框的input事件之外,还可以通过 vue 的watch来监听关键字的变化

Vue2.0 中的写法

在 vue2.0 中,watch常用的写法包含了两种,下面我们分别使用不同的写法来进行上述功能的实现

1.常规实现

<template>
  <div>
    <div>
      <span>搜索</span>
      <input v-model="searchValue" />
    </div>
    <!--列表,代码省略-->
  </div>
</template>
<script>
export default {
  data() {
    return {
      searchValue: ''
    }
  },
  watch: {
    // 在值发生变化之后,重新加载数据
    searchValue(newValue, oldValue) {
      // 判断搜索
      if (newValue !== oldValue) {
        // 在这里处理搜索逻辑
      }
    }
  }
}
</script>

2.使用$watch 实现

<template>
  <div>
    <div>
      <span>搜索</span>
      <input v-model="searchValue" />
    </div>
    <!--列表,代码省略-->
  </div>
</template>
<script>
export default {
  data() {
    return {
      searchValue: ''
    }
  },
  created() {
    // $watch 会返回一个 unwatch 函数,如果需求上需要在某些场景取消 watch,可以执行`unwatch`
    const unwatch = this.$watch('searchValue', (newValue, oldValue) => {
      // 判断搜索
      if (newValue !== oldValue) {
        // 在这里处理搜索逻辑
      }
    })
  }
}
</script>

在调用$watch的时候,会有一个返回值unwatch,然后如果需要取消 watch 监听,我们可以通过调用unwatch来进行,比如有一个表单,表单上面的保存按钮平常是置灰的,但是假如用户对表单进行了修改,就需要将表单的置灰状态修改为启用状态。但是如果表单已经启用了,就没必要继续watch了,这时候就需要使用unwatch

Vue3.0 中的写法

Vue3.0中除了Vue2.0中的写法外,还在Composition API提供了watchwatchEffect两个API,用于监听数据的变化,下面我们将上面搜索分别使用watchwatchEffect来实现

1.watch 实现方式

<template>
  <div>
    <span>搜索</span>
    <input v-model="state.searchValue" />
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, watch } from "vue";

export default defineComponent({
  setup() {
    const state = reactive({
      searchValue: ""
    });
    // 通过 watch 来监听 searchValue 的变化
    const unwatch = watch(
      () => state.searchValue,
      (value, oldValue) => {
        if (value !== oldValue) {
          // 在这里处理搜索逻辑
        }
      }
    );
    return {
      state
    };
  }
});
</script>

watch APIVue2.0中的this.$watch用法基本是一致的,包括使用的参数等,同时watch API返回了unwatch函数用于取消watch

同时watch还可以侦听多个属性的变化,就像下面这样

watch([a,b,c], ([a,b,c],[oldA,oldB,oldC]) => {

})

2.watchEffect 实现

watchEffect参数是一个函数,在代码执行时,会立即执行watchEffect传入的函数,然后响应式追踪其依赖,并在其中某些依赖发生变化时重新运行该函数。我们将上述搜索代码使用watchEffect来实现。

export default defineComponent({
  setup() {
    const state = reactive({
      searchValue: ""
    });
    // 加载数据
    function loadData(searchValue){
      
    }
    // 通过 watchEffect 来监听 searchValue 的变化
    const unwatch = watchEffect(() => {
      // 当代码执行到 watchEffect 时,会立即调用此函数,同时会收集到存在
      //`state.searchValue`的依赖,然后当`state.searchValue`发生
      //变化时会在此调用 watchEffect,已实现数据监听
      loadData(state.searchValue)
    });
    return {
      state
    };
  }
})

React 中的写法

React中与watch比较相似的功能是Effect Hook,使用它可以让你在函数组件中执行副作用操作,先来看一下代码:

import React, { useEffect, useState } from 'react'

export default function() {
  // useState 传入要初始化的状态数据,然后会返回一个数组
  // 数组第一项为声明的数据,而第二个参数是一个方法,用于调用
  // 修改数据
 const [searchValue, setSearchValue] =  useState('')

 function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
   // 在 react 修改数据需要调用 useState 返回的方法
   setSearchValue(e.target.value);
 }

 // useEffect 接受两个参数,第一个是回调函数,第二个是要监听变化的属性,是一个数组
 useEffect(() => {
   // 当代码首次调用 useEffect 会进入这个回调函数,然后
  // 当 serchValue 发生变化时,会再次进入到这里
  console.log(111)
 },[searchValue])
  return (
    <div>
      <input value={searchValue} onChange={handleChange}></input>
      
    </div>
  );
}

如上代码我们使用useEffect来监听searchValue的变化,然后触发新的逻辑,但是看到上面代码,我们并没有发现取消effect的方法,那么如何取消呢?

useEffect第二个参数是一个数组,通过给数组传入要监听的变量来实现数据监听,但是却没有办法去取消这个监听,所以我们需要曲线救国,就像下面代码这样:

 const [isWatch] = useState(true)

 useEffect(() => {
  // 通过 isWatch 来判断是否进行监听逻辑变化   
  if(isWatch) {
    // 监听数据变化
    console.log(searchValue)
  }
 },[isWatch, searchValue])

计算属性,在 React 中我也找到的踪迹

Vue中的计算属性,相信大家都很熟悉,通常我们会使用计算属性来对template中的复杂逻辑计算进行简化,比如许多英文网站输入用户名的时候会输入firstNamelastName,然后在界面上面又会将firstNamelastName连在一起显示,这时候就可以使用到了计算属性对显示进行处理

Vue2.0 中的写法

<template>
  <div>
    <div>
      <label>firstName</label>
      <input v-model="firstName" />
      <label>lastName</label>
      <input v-model="lastName" />
    </div>
    <div>用户名:{{ name }}</div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      firstName: '',
      lastName: ''
    }
  },
  computed: {
    name() {
      return this.firstName + '·' + this.lastName
    }
  }
}
</script>

Vue3.0 中的写法

Vue3.0Composition API也提供了computed API,用于生成计算属性,用法与Vue2.0用法基本是一致的

import { computed, defineComponent, reactive } from "vue";

export default defineComponent({
  setup() {
    const state = reactive({
      firstName: "",
      lastName: ""
    });
    const name = computed(() => state.firstName + "·" + state.lastName);
    return {
      state,
      name
    };
  }
});

React 中的写法

在说到在React中模拟计算属性之前,我们先要了解一些React Hook的规则。

  1. 只能在最顶层使用Hook
  2. 只能在React函数中调用Hook

当我们在React函数中使用useState之后,如果我们通过setState修改了state,那么这时候react会做什么呢?React会将这个函数式组件重新执行一遍,但是对于里面的useState,useEffect等等不会重新初始化,而是使用已经记录的状态进行处理。那么React是怎么知道哪个state对应哪个useState呢?答案是React靠的是Hook调用的顺序。所以我们不能在非顶层比如if里面使用Hook

同时呢?因为state的变化会引起整个函数重新执行,那么假如我们在代码里面写了这样一段逻辑

const [firstName, setFirstName] = useState('')
const [lastName, setLastName ] = useState('')
const [other,setOther] = useState('')

// 使用 useMemo 可以模仿 Vue 中的计算属性
const name = firstName + "·" + lastName;

上面代码里面我们的name是通过firstNamelastName计算而来的,那么当firstName或者lastName发生变化时,都会重新计算name,这个逻辑是正确的。但是实际上other如果发生了变化,也会导致name重新计算,这是我们不愿意看到的。假如name的计算逻辑很复杂,那么就会引起不必要的性能开支。所以React提供了useMemo,用于避免非相关属性变化引起计算逻辑发生变化,而我们正好可以利用useMemo来模拟计算属性,如下代码:

import React, {  useMemo, useState } from 'react'

export default function() {
  const [firstName, setFirstName] = useState('')
  const [lastName, setLastName ] = useState('')

  // 使用 useMemo 可以模仿 Vue 中的计算属性,当 firstName 与`lastName`任何一个发生变化
  //都会触发`name`重新计算,但是对于其他属性变化,并不会引起重新计算
  const name = useMemo(() => firstName + '·' + lastName,[firstName,lastName])

  const handleChange = (method: Function, e: React.ChangeEvent<HTMLInputElement> ) => {
    method(e.target.value)
  }

  return (
    <div>
      <div>
        <label>firstName</label>
        <input
          value={firstName}
          onChange={(e) => handleChange(setFirstName, e)}
        />
        <label>lastName</label>
        <input
          value={lastName}
          onChange={(e) => handleChange(setLastName, e)}
        />
      </div>
      <div>用户名:{name}</div>
    </div>
  );
}

但是呢,在Vue中计算属性既可以get,也可以set,这一点我们是无法使用useMemo来模拟的,当然如果有小伙伴知道如何模拟,麻烦下方评论区告诉我,谢谢。

结语

前端技术发展日新月异,我表示已经学不动了,可是不学怎么赚钱吃饭,所以还是要学。作为前端主流三大框架之二的 Vue 和 React,在日常工作中还是很常用的,通过这种对比的学习,可以比较好的将两者联合在一起,方便记忆。

以上关于用React.js写法改写Vue写法的教程(一)的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 用React.js写法改写Vue写法的教程(一)

发表回复