React

React 和 Vue对比

  • React将一切视为函数。组件作为一个函数,返回JSX进行构建。
  • React高度自定义化,特别灵活。Vue相对将内容固定,不需要太多的自定义,开箱即用的感觉。可以将React比喻成手动档,Vue比喻成自动档。Vue与React相比,Vue2的选项式确实会让框架变得死板,但是Vue3组合式增强了函数式编程的思想,提高了Vue的灵活性,用Vue3和React相比,Vue3的简洁和灵活恰到好处。
  • React使用JSX编写模板,写惯Vue转React需要一段时间将思想转变过来。

 

JSX写模板

在组件函数中,需要通过return() 返回JSX内容。如果只有一行则不需要()

1.根组件必须使用一个块去包裹内容,因为只能返一个根元素。

这里的最外层标签可以使用<div></div> <></> <Fragment></Fragment>,他们最总都不会渲染成实际的标签

const A = () => {
    return (
        <>
          <p>111</p>  
        </>
    )
}

2.标签内属性命名需要用驼峰命名法

<img 
  src="https://i.imgur.com/yXOvdOSs.jpg" 
  alt="Hedy Lamarr" 
  className="photo"
/>

 

JSX中使用Javascript

使用{},在{}内写js表达式

  1. 传字符串用引号
  2. 传变量用{}
  3. 传css或对象用{{a:1,b:2}},{{color:'red'}}

 

组件传参和收参

传:定义参数名,使用{}包裹数据

<Avatar
    size={100}
    person={{ 
        name: 'Katsuko Saruhashi',
        imageId: 'YfeOqp2'
    }}
/>

收:与函数接收参数一样,接收一个props对象。可以通过结构的方式将参数展开。与解构一样,可以自定义默认值。

function Avatar(props) {
   // props.person
   // props.size
}
function Avatar({ person, size = 100 }) {

}

 

条件渲染

1.条件返回JSX:在return前做逻辑处理。通过不同的情况,分开return不同是JSX

2.选择性包含JSX:

  2.1 使用三目运算符:<li>{true ? (<p>true</p>) : (<p>false</p>)}</li>

  2.2 使用&&:<li>{true && (<p>true</p>)</li>

  2.3 使用赋值返回: 通过定义变量,进行逻辑判断给变量不同的JSX,然后再return这个变量

 

渲染列表

通过对数组进行循环,返回相应的标签。

需要对渲染的元素传入key属性,用于让react标识是每一个元素,最好使用独一无二的数据进行定义。

function List() {
    const list = [1,2,3]
    return (
        {list.map(l => <p key={l}>{l}</p>)}                  
    )
}
//1
//2
//3

 

响应事件

通过在标签上定义事件,传入回调函数进行交互<li onClick={() => alert('click)}>Click</li>

由于有事件冒泡和默认事件的影响,我们需要进行额外的处理

1.阻止冒泡

通过接收event参数,调用e.stopPropagation()进行阻止

<button onClick={e => {
        e.stopPropagation()
        onClick();
    }}>
</button>

2.阻止默认事件

当我们在form标签中,或者button是submit状态时,点击button会进行页面刷新

通过接收event参数,调用e.preventDefault()进行阻止

<form onSubmit={e => {
      e.preventDefault();
      alert('提交表单!');
    }}>
    <input />
    <button>发送</button>
</form>

 

数据和响应式 

通过useState这个hook,定义响应式数据const [name, setName] = useState('Karle')

useState()返回一个数组,包含当前state和一个更新state的函数

我们需要将state视为readOnly,不能通过直接赋值的方式进行数据更新

与Vue不同,react没有v-model进行双向绑定。每次更新响应式数据都需要手动调用setState()进行更新,react才会重新渲染

更新对象和数组

不能通过直接赋值的方式进行数据更新(const [state, setState] = useState('000'); state.a = '123'),这将会产生mutation(更新带来的副作用)

我们需要提供一个新的数据,通过setXXX()将原来的state进行更新

const _person = {
    name: 'karle',
    age: 100
    edu:[{},{},{}]
}
const [person, setPerson] = useState(_person)
const updatePersonName = (person) => {
    const nextPerson = {
        ...person,
        name:'Peter'
    }
}

对于数组,我们不能使用改变原数组的方法进行数组操作,如push,pop,splice等。应该接收一个新的被处理后的数组,再通过setXXX()进行更新

const [age, setAge] = useState([1,2,3,4,5,6])
const deletArray5 = (age) => {
    const nextArray = age.filter(a => a!== 5)
    setAge(nextArray)
}

 

使用Context进行状态共享

当我们有多个嵌套组件,其中有些state只有根组件和最后一个组件用到。如果使用props需要一层一层传递是否麻烦,因此有Context进行状态共享。

1.定义Context对象

export const TextContext = createContext({name:'karle',age:12})

2.读取Context对象

import {TextContext} from './TextContext.js'
import {useContext} from 'react'

function A(){
    const text = useContext(TextContext)
    //text = {name:'karle',age:12}
    return ()
}

3.如果要设置状态共享作用域

function App() {
    return (
        <TextContext.Provider value={name:'Peter',age:12}>
            <Father>
                <Son></Son>
            </Father>
        </TextContext.Provider>
    )
}

function Son() {
    return (
        <TextContext.Consumer>
            { person => {
                <p>{person.name}</p>
                <p>{person.age}</p>
            }}
        </TextContext.Consumer>
    )
}

读取Context有两种方式

  1. 通过<XXXContext.Consumer>组件,其中{}内必须使用函数,参数即为定义的共享状态
  2. 通过useContext()钩子,将XXXContext放入参数,返回的即为共享状态

 

用Reducer管理更新状态的逻辑

我们有一个状态,需要对其进行增删改的操作,分别定义了三个handler函数。

这样显得代码十分冗余,于是可以使用Reducer进行管理,减少代码体积和增强可读性可调试性

function handleAddTask(text) {
  setTasks([
    ...tasks,
    {
      id: nextId++,
      text: text,
      done: false,
    },
  ]);
}

function handleChangeTask(task) {
  setTasks(
    tasks.map((t) => {
      if (t.id === task.id) {
        return task;
      } else {
        return t;
      }
    })
  );
}

function handleDeleteTask(taskId) {
  setTasks(tasks.filter((t) => t.id !== taskId));
}

1.将更新状态的逻辑修改成dispatch的一个action

  1.1 移除所有具体逻辑,只剩下三个方法名

  1.2 往方法中写入dispatch()函数,传入一个action对象

    action对象没有规定的结构,其包含你需要操作的数据和当前状态。以及需要表明操作类型如{type:'add'},这里的type和内容都以自己实际开发为准

2.编写reducer函数

state即为当前需要操作的状态,action即为上述action

在该reducer函数中,进行不同的逻辑处理

const myReducer(state, action) {
    const { type } = action
    switch(type) {
        ...
    }
}

3.使用reducer函数

需要用到useReducer()这个钩子,参数为自己定义的reducer函数和state初始化数据,返回响应式状态和dispatch函数

将useState()进行替换

const [tasks, setTasks] = useState({...})
=====>
const [tasks, dispatch] = useReducer(myReducer, {...})

便可照常使用

posted on 2024-02-21 19:00  Karle  阅读(9)  评论(0编辑  收藏  举报