乐趣区

关于前端:ReactVue我全都要React-Hook-实现-Vue-的11个基本功能

前言

大家好,我是林三心,因为工作我的项目的须要,在上个月,我开始在我的项目中应用 React 去开发,到了明天,差不多一个月了,想跟大家分享一下我在 React 中是怎么去实现以前 Vue 中的一些性能的。

因为本菜鸟应用 React 不久,有不妥之处还请大家之处

注明:本文中所指 Vue 的版本是Vue2,React 的版本是 React17

1、JSX 和 template

在 Vue2 中是应用 template 的,这点应用 Vue 的同学们都晓得,而在 React 中应用的是 JSX JSX 是一个看起来很像 XML 的 JavaScript 语法扩大。

它有以下长处:

  • JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
  • 它是类型平安的,在编译过程中就能发现错误。
  • 应用 JSX 编写模板更加简略疾速。

JSX 的例子:应用 ReactDOM.render 函数,将 DOM 渲染到对应到 id 为 app 的节点下

// 应用 ReactDOM.render 函数,将 DOM 渲染到对应到 id 为 app 的节点下
ReactDOM.render(
  <div>
      <h1> 我是林三心 </h1>
      <h2> 我是菜鸟 </h2>
      <p>React 是一个很不错的 JavaScript 库!</p>
  </div>
  ,
  document.getElementById('app')
);

2、React 中给元素设置 style

React 应用内联款式。咱们能够应用 驼峰法 语法来设置内联款式. React 会在指定元素数字后主动增加 px。以下实例演示了为 h1 元素增加 myStyle 内联款式:

function Demo() {

  var myStyle = {
    fontSize: 100, // 驼峰法
    color: '#FF0000'
  }

  return <h1 style={myStyle}> 林三心是菜鸟 </h1>
}

3、React 中给元素设置 class

因为 JSX 就是 JavaScript,一些标识符像 class 不倡议作为 XML 属性名。作为代替,应用 className来做对应的属性。

function Demo() {

  const classes = 'haha heihei xixi'

  return (
    <div>
      <h1 className='haha'> 林三心是菜鸟 </h1> // 单个
      <h1 className='haha heihei'> 林三心是菜鸟 </h1> // 多个
      <h1 className={classes}> 林三心是菜鸟 </h1> // 应用值来当做 class
    </div>
  )
}

4、React 中的点击事件

Vue 中的点击事件应用的是 @click 来触发的,而在 JSX 中应用的是 onClick

function Demo() {const handleClick = () => {console.log('林三心是菜鸟')
  }

  return (<button onClick={handleClick}> 点我 </button>
  )
}

5、React 中批改值触发 DOM 更新

我应用的是 React hook 其中的 useState ,这一个 hook 在批改常量的时候比较简单,然而在批改援用 对象 或者 数组 的时候就须要先进行 浅拷贝 再进行笼罩批改

import {useState} from 'react'

function Demo() {const [msg, setMsg] = useState('我是菜鸟')
  const [obj, setObj] = useState({
    name: '林三心',
    food: '泡面'
  })
  const [arr, setArr] = useState([{ message: '林三心啊', id: 1},
    {message: '林三心啊啊', id: 2},
    {message: '林三心啊啊啊', id: 3}
  ])
  const handleClick = (type: number) => {switch (type) {
      case 1:
        setMsg('林三心是菜鸟') // 间接赋值
        break;
      case 2:
        setObj({...obj, food: '牛肉丸',}) // 浅拷贝
        break;
      case 3:
        setArr([...arr, { message: '林三心啊啊啊啊', id: 4}]) // 浅拷贝实现 push 成果
        break;
    }
  }

  return (
    <div>
      <button onClick={() => handleClick(1)}> 批改 msg</button>
      <button onClick={() => handleClick(2)}> 批改 obj 的 food</button>
      <button onClick={() => handleClick(3)}>arr 增加一项 </button>
      <h1>{msg}</h1>
      <p>{` 我是 ${obj.name}我喜爱吃 ${obj.food}`}</p>
      <ul>
        {arr.map(({ message, id}) => {return <li key={id}>{message}</li>
          })
        }
      </ul >
    </div>
  )
}

6、生命周期

应用 React 的 hook—— useEffect

import {useState, useEffect} from 'react'
function App() {const [num, setNum] = useState(1)
  const [count, setCount] = useState(1)
  useEffect(() => {console.log('哈哈哈哈')
  })
  return (
    <div>
      <button onClick={() => setNum(num + 1)}> 点我批改 num</button>
      <button onClick={() => setCount(count + 1)}> 点我 count</button>
    </div>
  )
}

第二个参数不传

 useEffect(() => {console.log('哈哈哈哈')
 })

useEffect 第二个参数不传时, 页面初始 数据更新 的时候,第一个参数函数都会执行,所以此时初始页面时会输入一次 哈哈哈哈 ,而后无论你点批改 num 或者批改 count 的按钮时,也都会输入 哈哈哈哈

第二个参数传空数组

 useEffect(() => {console.log('哈哈哈哈')
 }, [])

useEffect 第二个参数传 [] 时,那么第一个参数函数只有在 页面初始 的时候才会执行,也就是只执行一次,无论你点批改 num 或者批改 count 的按钮,都不会执行这个函数

第二个参数传非空数组

 // ①
 useEffect(() => {console.log('哈哈哈哈')
 }, [num])
 
 // ②
 useEffect(() => {console.log('哈哈哈哈')
 }, [count])
 
 // ③
 useEffect(() => {console.log('哈哈哈哈')
 }, [num, count])

useEffect 第二个参数传非空数组时, 页面初始 依赖的数据产生更新 的时候,第一个参数函数都会执行。比方上方例子:

  • ①、只有按批改 num 按钮时,才会再次输入 哈哈哈哈
  • ②、只有按批改 count 按钮时,才会再次输入 哈哈哈哈
  • ③、无论按哪个按钮都会再次输入 哈哈哈哈

return 革除操作

useEffect(() => {const timeId = setTimeout(() => console.log('我是定时器'), 1000)
    return () => clearTimeout(timeId)
 })

React 会在组件卸载的时候执行革除操作。effect 在每次渲染的时候都会执行。React 会在执行以后 effect 之前对上一个 effect 进行革除。

是在还不了解的同学,能够疯狂点击按钮,看看 我是定时器 这句话会输入多遍还是只输入一遍,就豁然开朗了

7、React 中实现 v-if & v-else

Vue 中的 v-if & v-else

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。

<h1 v-if="show"> 林三心是菜鸟 </h1>

也能够用 v-else 增加一个“else 块”:

<h1 v-if="show"> 林三心是菜鸟 </h1>
<h1 v-else>Oh no 😢</h1>

React 中实现

如果单单只想实现 v-if 的话,能够借助 && 逻辑运算符

import {useState} from 'react'
function Demo() {const [show, setShow] = useState(false)
  const changeShow = () => {setShow(!show)
  }

  return (
    <div>
      {show && <h1> 林三心是菜鸟 </h1>}
      <button onClick={changeShow}> 点我 </button>
    </div>
  )
}

如果想实现 v-if v-else 的话,能够借助 三元运算符

import {useState} from 'react'
function Demo() {const [show, setShow] = useState(false)
  const changeShow = () => {setShow(!show)
  }

  return (
    <div>
      {show ? <h1> 林三心是菜鸟 </h1> : <h1> 菜鸟是林三心 </h1>}
      <button onClick={changeShow}> 点我 </button>
    </div>
  )
}

8、React 中实现 v-show

Vue 中的 v-show

另一个用于依据条件展现元素的选项是 v-show 指令。用法大抵一样:

<h1 v-show="show"> 林三心是菜鸟 </h1>

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简略地切换元素的 CSS property display

React 中实现

其实就是扭转元素的 display 这个款式来实现成果

function Demo() {

  // ... 一样的代码
  
  return (
    <div>
      <h1 style={{display: show ? 'block': 'none'}}> 林三心是菜鸟 </h1>
      <button onClick={changeShow}> 点我 </button>
    </div>
  )
}

9、React 中实现 v-for

咱们能够用 v-for 指令基于一个数组来渲染一个列表。v-for 指令须要应用 item in items 模式的非凡语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的 别名

Vue 中的 v-for

<ul>
  <li v-for="item in items" :key="item.message">
    {{item.message}}
  </li>
</ul>

React 中实现

JSX 容许在模板中插入数组,数组会主动开展所有成员:

function Demo() {

  const arr = [<li key={1}> 林三心啊 </li>,
    <li key={2}> 林三心啊啊 </li>,
    <li key={3}> 林三心啊啊啊 </li>,
  ]

  return (
    <ul>
      {arr}
    </ul >
  )
}

然而我大多数状况会应用数组的 map 办法来帮助渲染

function Demo() {

  const arr = [{ message: '林三心啊', id: 1},
    {message: '林三心啊啊', id: 2},
    {message: '林三心啊啊啊', id: 3}
  ]

  return (
    <ul>
      {arr.map(({ message, id}) => {return <li key={id}>{message}</li>
        })
      }
    </ul >
  )
}

10、React 中实现 computed

Vue 中的 computed

只有 name 或者 food 扭转, mag 会更新成相应的值

<h1>{{msg}}</h1>

computed: {msg() {return ` 我是 ${this.name},我爱吃 ${this.food}` } }

React 中实现

在 React 中须要通过 useMemo 这个 hook 来来实现 computed 的成果

import {useState, useMemo} from 'react'
function Demo() {const [name, setName] = useState('林三心')
  const [food, setFood] = useState('泡面')

  // 实现 computed 的性能
  const msg = useMemo(() => ` 我是 ${name},我爱吃 ${food}`, [name, food]) // 监听 name 和 food 这两个变量

  const handleClick = (type: number) => {if (type === 1) {setName('大菜鸟')
    } else if (type === 2) {setFood('牛肉丸')
    }
  }

  return (
    <div>
      <button onClick={() => handleClick(1)}> 批改 name</button>
      <button onClick={() => handleClick(2)}> 批改 food</button>
      <h1>{msg}</h1>
    </div>
  )
}

11、React 中实现 watch

// useWatch.ts
import {useEffect, useRef} from 'react'

type Callback<T> = (prev?: T) => void
interface Config {immdiate: Boolean}

const useWatch = <T>(data: T, callback: Callback<T>, config: Config = { immdiate: false}) => {const prev = useRef<T>()
  const {immdiate} = config
  const inited = useRef(false)
  const stop = useRef(false)
  useEffect(() => {const execute = () => callback(prev.current)
    if (!stop.current) {if (!inited.current) {
        inited.current = true
        immdiate && execute()} else {execute()
      }
      prev.current = data
    }
  }, [data])

  return () => stop.current = true}

export default useWatch

应用

import {useState} from 'react'
import useWatch from '/@/hooks/web/useWatch'
function App() {const [num, setNum] = useState(1)
  useWatch(num, (pre) => console.log(pre, num), {immdiate: true})
  return (
    <div>
      <div style={{color: '#fff'}}>{num}</div>
      <button onClick={() => setNum(num + 1)}> 点我 </button>
    </div>
  )
}

结语

往年快完结了,心愿大家身体健康,万事如意

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜爱前端,想学习前端,那咱们能够交朋友,一起摸鱼哈哈,或者你有适合的前端岗位机会,能够让我试试的,那能够加我的 wx –> meron857287645

退出移动版