一、视图更新有哪些方案?
1、对于数据变量 正常的增删改查
,只会让数据更新,但是不会触发 React 视图
的更新;
如:
javascript
<script lang="jsx">
const baseTable = [
{name:'Andy', age: 18, id: 1},
{name:'Jack', age: 19, id: 2},
]
const handleAdd = () => {
baseTable.push({
id: baseTable.length + 1,
name: `${baseTable.length + 1}-newName`,
age: baseTable.length + 10
})
// 这样操作时,是不会触发React 视图更新的;
}
export default const MyTable = () => {
return (
<>
<button onClick={handleAdd}>新增</button>
</>
)
}
export default MyTable
</script>
2、为什么会出现这种情况?
2.1、局部变量无法在多次渲染中持久保存。当 React 再次渲染
这个组件时候,他会从头开始渲染
,并不会考虑之前对局部变量的任何更改;
2.2、更改局部变量不会
触发渲染。React 没有意识到它 需要使用新数据 重新渲染组件;
3、如何解决?要做到如下两点
3.1、保留 渲染之前的数据
3.2、触发 React 使用新数据渲染组件-达到重新渲染的效果
4、React 内部自带 Hook useState
提供解决方案
4.1、State
变量 用于保存渲染 之间的数据。
4.2、State setter
函数更新变量 并且触发 React 再次渲染
组件;
如:
javascript
<script lang="jsx">
import React, { useState } from 'react
// 比如写一个列表
const Table = () => {
// useState() 返回 的第一个参数是初始值,第二是更改初始值的方法;
const [tableData, setData ] = useState([])
const handleAdd = () => {
const curTable = tableData
curTable.push({id:1, name: 'Andy', age: 18})
// 通过 setData 修改初始值,并且更新视图
// 需要浅拷贝的方式获取数据并修改
// 对于react 来说 引用类型的都是地址,没有重新赋值(地址没有改变),故不会更新视图
setData([...curTable])
}
const Itmes = tableData && tableData.map(itm =>
return (
<li key={itm.id} onClick={() => handleEdit(itm)}>{itm.name}</li>
)
)
return (
<>
<ul>
<Itmes></Itmes>
</ul>
</ul>
)
}
</script>
二、React 中事件的应用注意事项
1、通常是以 handle 开头
的,编程书写习惯,但是为了提高代码的可读性,建议保持良好的编写规范;
javascript
<script lang="jsx">
const myForm = () => {
const [count, setCount] = useState(0)
const handleAdd = () => {
setCount(count + 1)
}
return (
<>
<div>修改内容:{name}</div>
{/* 第一种 */}
<button onClick={() => handleAdd()}>add1</button>
{/* 第二种 */}
<button onClick={() => setCount(count + 1)}>add2</button>
{/* 第三种,此时 handleAdd 后面 没有 () 小括号,不然就是方法直接执行了 */}
<button onClick={handleAdd}>add3</button>
</div>
)
}
export default myForm
</script>
2、事件处理函数
props 应该以 on
开头,后面跟一个大写字母即驼峰命名
;
必须传递事件处理函数,而非函数调用! onClick={handleClick}
,不是
onClick={handleClick()}。
子组件
javascript
<script lang="jsx">
// { onSubmit, name } = props 对象
const MyButton = ({ onSubmit, name }) => {
return (
<>
<button type="button" onClick={() =>onSubmit(name)}>{name}</button>
</>
)
}
export default MyButton;
</script>
javascript
// 父组件
<script lang="jsx">
import React, { useState } from 'react'
import MyButton from './myButton.jsx'
const MyEvent = () => {
const [ count, setCount ] = useState(0)
const handleSubmit = (data) => {
console.log('submit:', data)
setCount(`${count}_andy`)
}
return (
<>
{/*
onSubmit 与子组件 props 中的 onSubmit 保持一致
即 等号左侧为 子组件 属性 方法名称;等号右侧为 父组件中的 方法 属性名称
*/}
<MyButton onSubmit={handleSubmit} name={count}>MyButton</MyButton>
</>
)
}
export default MyEvent
</script>
三、React 事件中处理 阻止冒泡
和阻止默认事件
利用原生事件的
e.stopPropagation();
--阻止冒泡;
e.preventDefault();
--阻止默认事件
javascript
<script lang="jsx">
const myButton = () => {
const handleSubmit = () => {
console.log('提交了')
}
return (
<button type="button"
onClick={(e) => {
{/* 阻止事件冒泡 */}
e.stopPropagation();
handleSubmit()
}}
>
add
</button>
<button type="button"
onClick={(e) => {
{/* 阻止默认事件 */}
e.preventDefault();
handleSubmit()
}}
>
add
</button>
)
}
</script>