@author: 郭瑞峰 @createTime: 2023/6/26 @updateTime: 2023/7/13
如果说可以的话,建议大家学的第一个前端框架为 React ,这样就不用看我这篇文章了
如果你在看,说明你跟我一样,都是先学的vue框架,那么有必要看一看我的文章了
废话到此,开始吹牛 ( ̄y▽, ̄)╭
温故旧识
vue开发无外乎涉及到一下几个方面:
- 数据读写
- 数据监听
- 函数方法使用
- dom事件绑定
- 获取dom节点
- 生命周期使用
- 父子组件通信
- 插槽
当然还有其他的,欢迎评论区补充
至于其他方面的什么 路由router、全局状态管理store、UI组件库 啥的,都不是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中一些配置代码(如列表)必须经过data或computed注册,而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 setup 与 react 生命周期(不完整)比对
相对于现在 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>
)
}
结束
根据自己开发经验,咱就只有大致分层这几个
若是涉及其他的,请在评论区留言,不胜感激
若是有出入,欢迎大佬教我做人