当前位置: 首页 > news >正文

ueditor是做网站的吗自适应 wordpress

ueditor是做网站的吗,自适应 wordpress,校园网站建设的缺陷,安徽省建设部网站官网更新 state 中的对象 state 中可以保存任意类型的 JavaScript 值,包括对象。但是,你不应该直接修改存放在 React state 中的对象。相反,当你想要更新一个对象时,你需要创建一个新的对象(或者将其拷贝一份)…

更新 state 中的对象

state 中可以保存任意类型的 JavaScript 值,包括对象。但是,你不应该直接修改存放在 React state 中的对象。相反,当你想要更新一个对象时,你需要创建一个新的对象(或者将其拷贝一份),然后将 state 更新为此对象。

文章及例子是参考React官方文档教程,开发环境:React+ts+antd

学习内容:

  • 如何正确地更新 React state 中的对象
  • 如何在不产生 mutation 的情况下更新一个嵌套对象
  • 什么是不可变性(immutability),以及如何不破坏它
  • 如何使用 Immer 使复制对象不那么繁琐

什么是 mutation?

你可以在 state 中存放任意类型的 JavaScript 值。

const [x, setX] = useState(0);
setX(5);

state x 从 0 变为 5,但是数字 0 本身并没有发生改变。在 JavaScript 中,无法对内置的原始值,如数字、字符串和布尔值,进行任何更改。

现在考虑 state 中存放对象的情况:

const [position, setPosition] = useState({ x: 0, y: 0 });

从技术上来讲,可以改变对象自身的内容。当你这样做时,就制造了一个 mutation:

position.x = 5;

然而,虽然严格来说 React state 中存放的对象是可变的,但你应该像处理数字、布尔值、字符串一样将它们视为不可变的。因此你应该替换它们的值,而不是对它们进行修改。

将 state 视为只读的

换句话说,你应该 把所有存放在 state 中的 JavaScript 对象都视为只读的。

在下面的例子中,我们用一个存放在 state 中的对象来表示指针当前的位置。当你在预览区触摸或移动光标时,红点会跟随着你的指针移动:

import React from 'react';
import {useState} from "react";const App: React.FC = () => {const [position, setPosition] = useState({x: 0,y: 0});return (<divonPointerMove={e => {setPosition({x: e.clientX,y: e.clientY});}}style={{position: 'relative',width: '100vw',height: '100vh',}}><div style={{position: 'absolute',backgroundColor: 'red',borderRadius: '50%',transform: `translate(${position.x}px, ${position.y}px)`,left: -10,top: -10,width: 20,height: 20,}}/></div>);
};export default App;

使用展开语法复制对象

在之前的例子中,始终会根据当前指针的位置创建出一个新的 position 对象。但是通常,你会希望把 现有 数据作为你所创建的新对象的一部分。例如,你可能只想要更新表单中的一个字段,其他的字段仍然使用之前的值。

下面的代码中,输入框并不会正常运行,因为 onChange 直接修改了 state :

import React from 'react';
import {useState} from "react";const App: React.FC = () => {const [person, setPerson] = useState({firstName: 'Barbara',lastName: 'Hepworth',email: 'bhepworth@sculpture.com'});const handleFirstNameChange=(e:any)=> {person.firstName = e.target.value;}const handleLastNameChange=(e:any)=> {person.lastName = e.target.value;}const handleEmailChange=(e:any)=> {person.email = e.target.value;}return (<><label>First name:<inputvalue={person.firstName}onChange={handleFirstNameChange}/></label><label>Last name:<inputvalue={person.lastName}onChange={handleLastNameChange}/></label><label>Email:<inputvalue={person.email}onChange={handleEmailChange}/></label><p>{person.firstName}{' '}{person.lastName}{' '}({person.email})</p></>);
};export default App;

在这里插入图片描述
此时输入框是不会正常运行的.
例如,下面这行代码修改了上一次渲染中的 state:

person.firstName = e.target.value;

想要实现你的需求,最可靠的办法就是创建一个新的对象并将它传递给 setPerson。但是在这里,你还需要 把当前的数据复制到新对象中,因为你只改变了其中一个字段:

setPerson({firstName: e.target.value, // 从 input 中获取新的 first namelastName: person.lastName,email: person.email
});

你可以使用 … 对象展开 语法,这样你就不需要单独复制每个属性。

setPerson({...person, // 复制上一个 person 中的所有字段firstName: e.target.value // 但是覆盖 firstName 字段 
});

在这里插入图片描述
改变输入后

在这里插入图片描述
请注意 … 展开语法本质是是“浅拷贝”——它只会复制一层。这使得它的执行速度很快,但是也意味着当你想要更新一个嵌套属性时,你必须得多次使用展开语法。

更新一个嵌套对象

考虑下面这种结构的嵌套对象:

const [person, setPerson] = useState({name: 'Niki de Saint Phalle',artwork: {title: 'Blue Nana',city: 'Hamburg',image: 'https://i.imgur.com/Sd1AgUOm.jpg',}
});

如果你想要更新 person.artwork.city 的值,用 mutation 来实现的方法非常容易理解:

person.artwork.city = 'New Delhi';

但是在 React 中,你需要将 state 视为不可变的!为了修改 city 的值,你首先需要创建一个新的 artwork 对象(其中预先填充了上一个 artwork 对象中的数据),然后创建一个新的 person 对象,并使得其中的 artwork 属性指向新创建的 artwork 对象:

const nextArtwork = { ...person.artwork, city: 'New Delhi' };
const nextPerson = { ...person, artwork: nextArtwork };
setPerson(nextPerson);

或者,写成一个函数调用:

setPerson({...person, // 复制其它字段的数据 artwork: { // 替换 artwork 字段 ...person.artwork, // 复制之前 person.artwork 中的数据city: 'New Delhi' // 但是将 city 的值替换为 New Delhi!}
});

这虽然看起来有点冗长,但对于很多情况都能有效地解决问题

使用 Immer 编写简洁的更新逻辑

如果你的 state 有多层的嵌套,你或许应该考虑 将其扁平化。但是,如果你不想改变 state 的数据结构,你可能更喜欢用一种更便捷的方式来实现嵌套展开的效果。Immer 是一个非常流行的库,它可以让你使用简便但可以直接修改的语法编写代码,并会帮你处理好复制的过程。通过使用 Immer,你写出的代码看起来就像是你“打破了规则”而直接修改了对象:

updatePerson(draft => {draft.artwork.city = 'Lagos';
});

但是不同于一般的 mutation,它并不会覆盖之前的 state!

Immer 是如何运行的?

由 Immer 提供的 draft 是一种特殊类型的对象,被称为 Proxy,它会记录你用它所进行的操作。这就是你能够随心所欲地直接修改对象的原因所在!从原理上说,Immer 会弄清楚 draft 对象的哪些部分被改变了,并会依照你的修改创建出一个全新的对象。

尝试使用 Immer:

  1. 运行 npm install use-immer 添加 Immer 依赖
  2. 用 import { useImmer } from ‘use-immer’ 替换掉 import { useState } from ‘react’

下面我们把上面的例子用 Immer 实现一下:

import React from 'react';
import { useImmer } from 'use-immer';const App: React.FC = () => {const [person, updatePerson] = useImmer({name: 'Niki de Saint Phalle',artwork: {title: 'Blue Nana',city: 'Hamburg',}});const handleNameChange=(e:any)=> {updatePerson(draft => {draft.name = e.target.value;});}const handleTitleChange=(e:any)=> {updatePerson(draft => {draft.artwork.title = e.target.value;});}const handleCityChange=(e:any)=>{updatePerson(draft => {draft.artwork.city = e.target.value;});}return (<><label>Name:<inputvalue={person.name}onChange={handleNameChange}/></label><br/><label>Title:<inputvalue={person.artwork.title}onChange={handleTitleChange}/></label><br/><label>City:<inputvalue={person.artwork.city}onChange={handleCityChange}/></label><p><i>{person.artwork.title}</i>{' by '}{person.name}<br/>(located in {person.artwork.city})</p></>);
};export default App;

在这里插入图片描述
改变输入内容:
在这里插入图片描述

可以看到,事件处理函数变得更简洁了。你可以随意在一个组件中同时使用 useState 和 useImmer。如果你想要写出更简洁的更新处理函数,Immer 会是一个不错的选择,尤其是当你的 state 中有嵌套,并且复制对象会带来重复的代码时。

为什么在 React 中不推荐直接修改 state?

有以下几个原因:

  • 调试:如果你使用 console.log 并且不直接修改 state,你之前日志中的 state 的值就不会被新的 state 变化所影响。这样你就可以清楚地看到两次渲染之间 state 的值发生了什么变化
  • 优化:React 常见的 优化策略 依赖于如果之前的 props 或者 state 的值和下一次相同就跳过渲染。如果你从未直接修改 state ,那么你就可以很快看到 state 是否发生了变化。如果 prevObj === obj,那么你就可以肯定这个对象内部并没有发生改变。
  • 新功能:我们正在构建的 React 的新功能依赖于 state 被 像快照一样看待 的理念。如果你直接修改 state 的历史版本,可能会影响你使用这些新功能。
  • 需求变更:有些应用功能在不出现任何修改的情况下会更容易实现,比如实现撤销/恢复、展示修改历史,或是允许用户把表单重置成某个之前的值。这是因为你可以把 state 之前的拷贝保存到内存中,并适时对其进行再次使用。如果一开始就用了直接修改 state 的方式,那么后面要实现这样的功能就会变得非常困难。
  • 更简单的实现:React 并不依赖于 mutation ,所以你不需要对对象进行任何特殊操作。它不需要像很多“响应式”的解决方案一样去劫持对象的属性、总是用代理把对象包裹起来,或者在初始化时做其他工作。这也是 React 允许你把任何对象存放在 state 中——不管对象有多大——而不会造成有任何额外的性能或正确性问题的原因。

摘要

  • 将 React 中所有的 state 都视为不可直接修改的。
  • 当你在 state 中存放对象时,直接修改对象并不会触发重渲染,并会改变前一次渲染“快照”中 state 的值。
  • 不要直接修改一个对象,而要为它创建一个 新 版本,并通过把 state 设置成这个新版本来触发重新渲染。
  • 你可以使用这样的 {…obj, something: ‘newValue’} 对象展开语法来创建对象的拷贝。
  • 对象的展开语法是浅层的:它的复制深度只有一层。
  • 想要更新嵌套对象,你需要从你更新的位置开始自底向上为每一层都创建新的拷贝。
  • 想要减少重复的拷贝代码,可以使用 Immer。
http://www.dtcms.com/a/444180.html

相关文章:

  • 【ROS2学习笔记】rqt 模块化可视化工具
  • 广东网站设计费用泰州网站建设方案推广
  • 苏州网站优化找哪家网站开发课程百度云
  • 网站网页切换怎么做WordPress建站主机推荐
  • 找高权重的网站做外链dw旅游网站设计教程
  • 如何用个门户网站做销售在网站后台管理系统里产品说明怎么添加图片
  • 北京网站搭建哪家好自己怎么设计公司的logo
  • wordpress注册不seo的作用有哪些
  • 手机做网站用什么软件wordpress 搭建知识库
  • AI大事记8:深蓝与卡斯帕罗夫——符号主义 AI 的巅峰与局限(下)
  • 苏州做网站的单位网站公司市场营销方案
  • model.export参数说明
  • 北京网站搜索优化北京建网站费用
  • 建设网站呼叫中心有什么好处wordpress没有用户选项
  • 怎么自己做一个网页产品seo优化
  • aspcms手机网站插件公司网站建设济宁
  • 番禺学校网站建设建议做编程网站
  • 怎么制作网站模版如何制作微信公众号里的小程序
  • 微网站是什么时候创建的桂林网络平台开发公司
  • 合肥网站seo优化排名c 做网站后台
  • 友链交换网站常州网警
  • 用什么建网站 cms广西贵港网站建设
  • 标准通网站建设合肥网站建设专业设计
  • 青岛做公司网站的公司怎么开个人网站
  • 如何做游戏推广网站中山精品网站建设案例
  • 信誉好的商城网站建设山东省建设管理中心网站首页
  • 广州网站建设电话大全家庭网络搭建网站
  • 专做白酒的网站深圳网站建设公司业务招聘
  • 网站建设相关工作济源市建设工程管理处网站
  • 网站模版建设教程十大互联网培训机构