从Vue快速上手React(16.8+)

330 阅读4分钟

我的博客原文

@author: 郭瑞峰 @createTime: 2023/6/26 @updateTime: 2023/7/13

如果说可以的话,建议大家学的第一个前端框架为 React ,这样就不用看我这篇文章了

如果你在看,说明你跟我一样,都是先学的vue框架,那么有必要看一看我的文章了

废话到此,开始吹牛 ( ̄y▽, ̄)╭

温故旧识

vue开发无外乎涉及到一下几个方面:

  • 数据读写
  • 数据监听
  • 函数方法使用
  • dom事件绑定
  • 获取dom节点
  • 生命周期使用
  • 父子组件通信
  • 插槽

当然还有其他的,欢迎评论区补充

至于其他方面的什么 路由router全局状态管理storeUI组件库 啥的,都不是Vue自带的,不是因为我懒才忽略的(就是因为我懒才不写的)。

数据读写

vue提供了两种读写方法 react就直接简单了,只有一个读写方法

  • vue 数据读写
// vue3 + setup + ts
import { ref, reactive, computed } from 'vue'
// 方法一,通过 ref, reactive 实现数据双向绑定
const str = ref<string>('hello, this is Vue.js')
const obj = reactive<Record<string, string>>({
  name: 'vue',
  version: '3.3.4'
})
str.value = '123456789'
console.log(obj.name)
// 方法二,通过 computed 间接实现其他地方(如store)数据读写
const aaa = ref<string>('Hello world') // 这个就当作从其他地方获取的数据吧 ㄟ( ▔, ▔ )ㄏ
const msg = computed<string>({
  get () { return aaa.value },
  set (newVal) { aaa.value = newVal }
})
msg = '333333333333'
console.log(aaa.value)
// vue2 + js
export default {
  data () {
    return {
	  str: '123456',
	  aaa: 'hello world' // 这个也当作从其他地方获取的数据吧 ( ̄_, ̄ )
	}
  },
  computed: {
    msg: {
	  get () { return this.aaa },
	  set (newVal) { aaa.value = newVal }
	}
  },
  created () {
    this.str = '333'
	this.msg = '444'
	console.log(this.aaa)
  }
}
  • react 数据读写
import React, { useState } from 'react'

const Component: React.FC = function () {
  const [getCount, setCount] = useState<number>(0)
  return (
    <>
	  <div>{ getCount }</div>
	  <button onClick={() => setCount(count => count + 1)} />
	</>
  )
}

不过这里注意一下,vue2中一些配置代码(如列表)必须经过datacomputed注册,而vue3和react可以外部导入后直接调用

数据监听

vue提供了 watch 帮忙监听数据变化 react提供了 useEffect 帮忙监听数据变化,但请注意,useEffect还有其他用途,并不局限于此

注意:vue中的数据监听watch可以直接获取新旧值,而react中数据监听useEffect不支持直接获取新旧值

  • vue数据监听
// vue3 + setup + ts
import { watch, ref, reactive } from 'vue'
const aaa = ref<string>('123456')
const bbb = reactive<Record<string, string>>({
  name: 'vue',
  version: '3.3.4'
})
// 单个监听
watch(aaa, (val, oldVal) => {
  console.log(val)
  console.log(oldVal)
})
// 多个监听
watch([aaa, bbb], (val, oldVal) => {
  console.log(val)
  console.log(oldVal)
}, {
  deep: true,
  immediate: true
})
// vue2 + js
export default {
  data () {
    return {
	  aaa: '333',
	  bbb: {
		name: 'vue',
		version: '3.3.4'
	  }
	}
  },
  watch () {
  // 只支持单一监听
	aaa (val) {
	  // ......
	},
	bbb: {
	  deep: true,
	  immediate: true,
	  hand
	}
  }
}
  • react 数据监听
import React, { useState, useEffect } from 'react'

function app () {
  const [count, setCount] = useState<number>(0)
  const [aaa, setAaa] = useState<string>('123')

  useEffect(() => {
    // 监听count
	// 注意:这个初始化时会执行一次,类似于 watch 的 immediate = true
  }, [count])

  useEffect(() => {
	// 支持多个监听
  }, [count, aaa])
}

export default app
  • react 获取新旧值方法示例
import React, { useState, useEffect } from 'react'

function app () {
  const [aaa, setAaa] = useState<string>('')

  useEffect(() => {
	// 获取新值
	console.log(aaa)
	// 注意:这里面不要写 setAaa 方法,不然会陷入死循环!
  }, [aaa])

  useEffect(() => {
	setAaa(aaa => {
	  // 获取旧值
	  console.log(aaa)
	})
  }, [])
  return (<></>)
}

export default app

函数方法处理

vue3和react一样,都是直接写函数引用函数就行,vue2不管怎样,都要注册到 methods

  • vue 函数方法处理
// vue3 + setup + ts
import moment from 'moment'
import { computed } from 'vue'

const time = computed<string>(() => {
  return moment(new Date()).format('YYYY-MM-DD hh:mm:ss')
})

function fn () {
  console.log(time)
}

fn()
// vue2 + js
import moment from 'moment'

export default {
  methods: {
  // 这里注册
    moment,
	hello () {
	  console.log('hello')
	}
  },
  computed: {
    time () {
	  this.hello()
	  return this.moment(new Date()).format('YYYY-MM-DD hh:mm:ss')
	}
  }
}
  • react 函数方法处理
import moment from 'moment'
import React from 'react'

function app () {
  return (<>
    { moment(new Date()).format('YYYY-MM-DD hh:mm:ss') }
  </>)
}

export default app

dom事件绑定

vue和react都是dom直接绑,但是有区别。区别见下方代码注释

  • vue dom事件绑定
<!-- vue3 -->
<template>
  <div>
    {{ count }}
	<!-- vue dom事件绑定时候必须传 运行函数 -->
	<button @click="setCount()"> +1 </button>
	<button @click="setCount(3)"> +3 </button>
	<button @click="() => { setCount(5) }"> +5 </button>
	<button @click="count += 7"> +7 </button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'

const count = ref<number>(0)

function setCount (addNum: number = 1) {
  count.value += addNum
}
</script>

vue2我就偷个懒不写了

  • react dom事件绑定
import React, { useState } from 'react'

function app () {
  const [count, setCount] = useState<number>(0)

  const addNum = (num: number = 1) => { setCount(count => count + num) }

  return (<>
	{ count }
	{ /* react dom事件绑定时候必须传函数类型 */ }
	<button onClick={ addNum }> +1 </button>
	<button onClick={ () => { setCount(count => count + 3) } }> +3 </button>
	<button onClick={ () => { addNum(5) } }> +5 </button>
  </>)
}

export default app

获取dom节点

除去原生的DOM操作外,vue和react都有自己的获取dom节点方式

  • vue 获取dom节点
<!-- vue3 -->
<template>
  <div>
    <!-- 加标识 -->
    <button ref="btn" @click="showButton()" >show button dom<button>
  </div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'

// 名称与标识保持一致
const btn = ref<HTMLInputElement>()
function showButton () {
  console.log(btn.value)
}
</script>
<!-- vue2 -->
<template>
  <div>
    <!-- 加标识 -->
    <button ref="btn" @click="showButton()" >show button dom<button>
  </div>
</template>
<script>
export default {
  methods: {
	showButton () {
	  // 名称可以不用与标识一致
	  const button = this.$refs.btn
	}
  }
}
</script>
  • react 获取dom节点
import React, { useRef } from 'react'

function app () {
  const btn = useRef<HTMLInputElement>(null)

  function showButton () {
	console.log(btn)
  }

  return (<>
  <button ref={btn}>show button dom</button>
  </>)
}

export default app

生命周期使用

先看看 vue3 setupreact 生命周期(不完整)比对 微信截图_20230627160716.png

相对于现在 react hooks 来说

import React, { useEffect } from 'react'

function app () {
  useEffect(function () {
    console.log('组件装载')
    return function () {
      console.log('组件卸载')
    }
  }, [])

  return (
    <h1>this is testRoute component</h1>
  )
}

export default app

父子组件通信

父 => 子:vue和react都一样,通过 props传递

<!-- vue3 -->
<template>
  <childComponent title="data1" :value="23" />
</template>
<script lang="ts" setup>
import childComponent from 'xxxxxx'
</script>

咱懒了,就不写vue2了

import React from 'react'
import childComponent from 'xxxxxx'
export default function () {
  return (<childComponent title="data1" :value="23" />)
}

子 => 父:vue可以通过emits向父传递回调事件,react可以通过向子组件传递回调函数实现

<!-- vue3 -->
<template>
  <button @click="sendMsg()">向父传消息</button>
</template>
<script lang="ts" setup>
import { defineEmits } from 'vue'
const $emits = defineEmits(['send'])

function sendMsg () {
  $emits('send', 'this is ChildComponent')
}
</script>
import React, { useCallback } from 'react'

function Child ({ cb }) {
  return (<button onClick={cb}>向父传消息</button>)
}

function Parent () {
  const getChildEvent = useCallback(function () {
    console.log('Child component run click event')
  }, [])
  return (<Child cb={getChildEvent}>)
}

插槽

简单来说,就是向子组件传递 dom/其他组件 要求子组件能渲染出来

vue通过插槽方式实现,react通过获取props.children,加载到对应位置实现

  • vue 实现方法
<!-- vue3 parent -->
<template>
  <ChildComponent>
  <h1>默认位置</h1>
  <h2 slot="place2">第二位置</h2>
  </ChildComponent>
</template>
<!-- vue3 parent -->
<template>
  <div>
    <!-- 默认位置 -->
    <slot></slot>
	<hr/>
	<!-- 第二位置 -->
	<slot name="place2"></slot>
  </div>
</template>
  • react 实现方法
import React from 'react'

function Child ({ children }) {
  return (
    <>
      { children[0] /* 默认位置 */}
      <hr/>
      { children[1] /* 第二位置 */}
    </>
  )
}

function Parent () {
  return (
    <Child>
      <h1>默认位置</h1>
      <h2>第二位置</h2>
	</Child>
  )
}

结束

根据自己开发经验,咱就只有大致分层这几个

若是涉及其他的,请在评论区留言,不胜感激

若是有出入,欢迎大佬教我做人

28936773_0_final.png