日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

优雅地提高 React 的表单页面的开发效率

發(fā)布時(shí)間:2025/7/25 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 优雅地提高 React 的表单页面的开发效率 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Den Form

為什么叫 Den Form ? 可能是因?yàn)?丹鳳眼 非常迷人吧...

一個(gè)非常輕巧的 Form 實(shí)現(xiàn), gzip 體積只有 3kb, 可以很方便跨越組件層級獲取表單對象, 或者管理聯(lián)動更新

安裝

$ yarn add react-den-form 復(fù)制代碼

基礎(chǔ)使用

Form 組件會在有 field 屬性的子組件上注入 onChange 事件, 并獲取其中的值

field 屬性是 Form 組件用于標(biāo)記哪一類子組件需要被監(jiān)管的字段, 并且也是用于校驗(yàn)更新的 key

field 可以重復(fù), 但是如果兩個(gè)子組件擁有相同的 field 值, 那么當(dāng)此類 field 需要更新時(shí), 兩個(gè)子組件都會進(jìn)行更新

import React from "react"; import Form from "react-den-form";export default () => {return (<div><Form onSubmit={({ data }) => console.log(data)}><input field="userName" /></Form></div>); }; 復(fù)制代碼

當(dāng)我們輸入數(shù)據(jù)后, 按回車鍵, onSubmit 方法打印如下:

{userName: "333"} 復(fù)制代碼

層級獲取數(shù)據(jù)不需要進(jìn)行額外處理

import React from "react"; import Form from "react-den-form";export default () => {return (<div><Form onChange={({ data }) => console.log(data)}><div><div><div><input field="userName" /></div><input field="password" /></div></div></Form></div>); }; 復(fù)制代碼

當(dāng)我們輸入數(shù)據(jù)時(shí), onChange 方法打印如下:

{userName: "333", password: "555"} 復(fù)制代碼

Form 表單嵌套不需要處理

有時(shí)候, 我們會有一些頁面結(jié)構(gòu)讓兩個(gè)不同的表單進(jìn)行嵌套, 如登錄時(shí), 驗(yàn)證碼的輸入框在用戶名和密碼中間, 而驗(yàn)證碼有單獨(dú)的請求. 當(dāng)然, 我們可以更換實(shí)現(xiàn)方式, 但是對于這類場景, DenForm 默認(rèn)處理了表單嵌套.

由于 Form 內(nèi)部有一個(gè) form 標(biāo)簽, 外層 onSubmit 會捕獲所有子組件的 onSubmit 事件, 但是 data 數(shù)據(jù)只會捕獲 當(dāng)前層級內(nèi)的 field 對象

export default () => {return (<div>{/* 此 Form 只會捕獲 userName及password, code被子Form攔截了 */}<Form onSubmit={({ data }) => console.log("1", data)}><input field="userName" />{/* 此 Form 只會捕獲 age */}<Form onSubmit={({ data }) => console.log("2", data)}><input field="code" /><button type="submit">此Submit會被最近的父級捕獲</button></Form><input field="password" /></Form></div>); }; 復(fù)制代碼

跨組件的值獲取

  • 為對象標(biāo)記一個(gè) toform 屬性, 會為對象注入一個(gè) ToForm 組件
  • 然后使用 ToForm 組件在對象內(nèi)部對表單進(jìn)行概括
  • import React from "react"; import Form from "react-den-form";// 此對象會被注入 ToForm 組件 function SubInput({ ToForm }) {return (<div><div><ToForm><input field="subPassword" /></ToForm></div></div>); }export default () => {return (<div><Form onChange={({ data }) => console.log(data)}><div><div><div><input field="userName" /></div><input field="password" /><SubInput toform /></div></div></Form></div>); }; 復(fù)制代碼

    當(dāng)我們輸入數(shù)據(jù)時(shí), onChange 方法打印如下:

    {userName: "333", password: "555", subPassword: "666"} 復(fù)制代碼

    自定義 Field 組件

    如果我們自己定義的特殊組件, 需要滿足兩個(gè)條件:

  • 組件外部的 props 需要設(shè)置 field 屬性
  • 組件內(nèi)部需要使用 this.props.onChange 返回?cái)?shù)據(jù)
  • import React from "react"; import Form from "react-den-form";class SubInput extends React.Component {handleOnChange = e => {// 需要使用 this.props.onChange 返回?cái)?shù)據(jù)this.props.onChange(e.target.value);};render() {return <input onChange={this.handleOnChange} />;} }export default () => {return (<div><Form onChange={({ data }) => console.log(data)}>{/* 需要設(shè)置 field 屬性 */}<SubInput field="userName" /></Form></div>); }; 復(fù)制代碼

    :art: 使用 onChangeGetter 獲取自定義組件的值

    以下標(biāo)簽, From 會自動識別 onChange 的返回值, 進(jìn)行解析獲取

    import React from "react"; import Form from "react-den-form";export default () => {return (<div><Form onChange={(...args) => console.log(args)}><input field="userName" /><textarea field="password" /><select field="loginType"><option value="signUp">Sign up</option><option value="signIn">Sign in</option></select></Form></div>); }; 復(fù)制代碼

    我們自己定義的特殊組件, 如果它們的 onChange 的返回值結(jié)構(gòu)不確定, 我們可以編寫 onChangeGetter 屬性:

    import React from "react"; import Form from "react-den-form";class SubInput extends React.Component {// 假定數(shù)據(jù)有一定的層級inputData = {value: ""};handleOnChange = e => {this.inputData.value = e.target.value;this.props.onChange(this.inputData);};render() {return <input onChange={this.handleOnChange} />;} }export default () => {return (<div><Form onChange={({ data }) => console.log(data)}><SubInput field="userName" onChangeGetter={e => e.value} /></Form></div>); }; 復(fù)制代碼

    onChangeGetter 的默認(rèn)值相當(dāng)于 onChangeGetter={e => e}

    表單提交

    以下三個(gè)情形為都會觸發(fā) Form 的 onSubmit 函數(shù):

    • 包含 field 屬性的對象中, 使用鍵盤的回車鍵
    • 包含 submit 屬性, 點(diǎn)擊(onClick)
    • 包含 type="submit" 屬性的對象中, 點(diǎn)擊(onClick)
    import React from "react"; import Form from "react-den-form";export default () => {return (<div><Form onSubmit={({ data }) => console.log(data)}><input field="userName" /><input submit field="password" /><button type="submit" /></Form></div>); }; 復(fù)制代碼

    異步請求提交

    Form 表單內(nèi)部并無封裝請求行為, 請?jiān)?onSubmit 事件中自行處理, 如:

    import React from "react"; import Form from "react-den-form";function fetchLogin({ data }) {fetch("/api/login", { method: "post", body: JSON.stringify(data) }).then(res => {return res.json();}).then(data => {console.log(data);}); }export default () => {return (<div><Form onSubmit={fetchLogin}><input field="userName" /><input field="password" /></Form></div>); }; 復(fù)制代碼

    上下文獲取數(shù)據(jù)

    我們?yōu)?Form 顯式注入一個(gè) data, 當(dāng)數(shù)據(jù)變化時(shí), data 的值也會變化, 這樣可以在上下文獲取 Form 的數(shù)據(jù)

    // React.Component 版本 import React from "react"; import Form from "react-den-form";export default class extends React.Component {data = {};render() {return (<div><Form data={this.data}><input field="userName" /><button onClick={() => console.log(this.data)}>show-data</button></Form></div>);} } 復(fù)制代碼// useHooks 版本 import React, { useState } from "react"; import Form from "react-den-form";export default () => {const [data] = useState({});return (<div><Form data={data}><input field="userName" /><button onClick={() => console.log(data)}>show-data</button></Form></div>); }; 復(fù)制代碼

    輸入數(shù)據(jù), 點(diǎn)擊 button, data 數(shù)據(jù)打印如下:

    { userName: "dog" } 復(fù)制代碼

    表單校驗(yàn)

    表單校驗(yàn)是無痛的, 并且是高效的

    我們給 input 組件添加 errorcheck 屬性, 該屬性可以是一個(gè)正則對象, 也可以是一個(gè) 函數(shù), 如果 errorcheck 校驗(yàn)的結(jié)果為 false, 就會將其他 error 相關(guān)的屬性賦予至組件中

    如下代碼, 如果 input 內(nèi)容不包含 123, 字體顏色為紅色:

    import "./App.css"; import React from "react"; import Form from "react-den-form";export default () => {return (<div><Form><inputfield="userName"errorcheck={/123/}errorstyle={{ color: "#f00" }}/></Form></div>); }; 復(fù)制代碼

    表單校驗(yàn)相關(guān)的 api:

    prop類型用途
    errorcheck正則或函數(shù)若返回值為 false, 將其他 error Api 應(yīng)用至組件中
    errorstylestyle 對象若校驗(yàn)為錯(cuò)誤, 將 errorstyle 合并至 style 中
    errorclassclassName 字符串若校驗(yàn)為錯(cuò)誤, 將 errorstyle 合并至 className 中
    errorpropsprops 對象若校驗(yàn)為錯(cuò)誤, 將 errorprops 合并至整個(gè) props 中

    為什么是 errorcheck 而不是 errorCheck ? 這是因?yàn)?React 對 DOM 元素屬性的定義為 lowercass:

    Warning: React does not recognize the `errorCheck` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `errorcheck` instead. If you accidentally passed it from a parent component, remove it from the DOM element. 復(fù)制代碼

    表單校驗(yàn)時(shí)進(jìn)行特殊處理

    如果我們有一個(gè)需求, 當(dāng)表單校驗(yàn)錯(cuò)誤時(shí), 顯示一個(gè)提示信息, 當(dāng)表單校驗(yàn)通過時(shí), 取消提示信息, 我們就需要對每次校驗(yàn)有差異時(shí), 進(jìn)行處理

    使用 onChange 方法每次都會被執(zhí)行, 可是我們只希望在表單校驗(yàn)結(jié)果有變化時(shí)進(jìn)行提示

    Form 提供了一個(gè) onErrorCheck 的屬性, 滿足以上需求

    import React from "react"; import Form from "react-den-form";export default () => {return (<div>{/* 只有當(dāng) input內(nèi)容校驗(yàn)結(jié)果發(fā)生變化時(shí), onErrorCheck 才會執(zhí)行 */}<Form onErrorCheck={({ isError, data }) => console.log(isError, data)}><inputfield="userName"errorcheck={/123/}errorstyle={{ color: "#f00" }}/></Form></div>); }; 復(fù)制代碼

    聯(lián)動

    當(dāng)我們修改一個(gè)對象時(shí), 根據(jù)某些條件, 希望修改另一個(gè)對象的行為我們稱之為聯(lián)動

    DenForm 的聯(lián)動是高性能的, 僅更新需要更新的對象

    我們可以在任何 Form 的回調(diào)函數(shù)中使用 update 進(jìn)行更新某個(gè)被 field 捆綁的組件的 value 或者 props

    下面這個(gè)例子: 1. 當(dāng)在 password 輸入時(shí), 會將 userName 的 input 框內(nèi)容改為 'new value'; 2. 當(dāng) userName 的 input 的內(nèi)容包含 'aa' 時(shí), 會將 password 的 value 和 style 進(jìn)行修改;

    import React from "react"; import Form from "react-den-form";export default () => {return (<div><FormonChange={({ data, field, update }) => {if (field === "password") {update({ userName: "new value" });}if (/aa/.test(data.userName)) {update({password: {value: "new value and style",style: { fontSize: 30 }}});}}}><input field="userName" /><input field="password" /></Form></div>); }; 復(fù)制代碼

    性能開銷

    Form 存在的意義在于簡化開發(fā), 用計(jì)算機(jī)的時(shí)間換取開發(fā)者的時(shí)間, 所以會有一些性能開銷.

    但是 Form 的開銷絕對不大, 因?yàn)?Form 內(nèi)部更新時(shí)只會針對指定的子組件進(jìn)行更新.

  • 每個(gè)包含 field 屬性的子組件都相當(dāng)于一個(gè)受控組件, 當(dāng)子組件 onChange 時(shí), 此子組件會進(jìn)行更新
  • Form 組件聲明或被外部更新時(shí)會去查詢當(dāng)前 JSX 對象中的所有子組件是否包含 field 或者 submit 屬性, 如果包含, 則注入 onChange 或 onClick; 如果不希望 Form 被外部更新, 請聲明 <Form shouldUpdate={false} >{...}</Form>
  • 如果因?yàn)槭褂?Form 遇到了性能問題, 請檢查以下情況:

    • 請減少 Form 內(nèi)部子組件的個(gè)數(shù), 最好不要超過 100 個(gè)
    • 在一個(gè)無限長的滾動列表外包裹 Form 時(shí), 請盡量使用 react-virtualized 或 react-window 類型的虛擬 List 組件, 以減少 Form 包裹的內(nèi)容個(gè)數(shù)
    • 如果 Form 子組件的個(gè)數(shù)過多時(shí), 請確保 Form 組件不會由外部頻繁更新, 或者添加 shouldUpdate={false} 至 Form 中: <Form shouldUpdate={false} >{...}</Form>

    我們有理由相信, 在一個(gè)設(shè)計(jì)合理的應(yīng)用中, 每個(gè) Form 包裹的組件個(gè)數(shù)應(yīng)該是有限的

    支持哪些 React 渲染層 ?

    此庫支持所有 React 的渲染層, 如 ReactDOM, ReactNative, ReactVR, 但是非 ReactDOM 中, 需要初始化事件類型

    如 ReactNative 中, 在項(xiàng)目之初設(shè)定:

    import { immitProps } from "react-den-form";// 設(shè)定 ReactNative 中的讀取值和更新值的監(jiān)聽屬性: immitProps.value = "value"; immitProps.change = "onChange"; immitProps.click = "onPress"; 復(fù)制代碼

    API

    Form API

    屬性描述類型默認(rèn)值必填
    data用于捆綁上下文的 data 對象, 也會當(dāng)成默認(rèn)值設(shè)置到相應(yīng)的 field 監(jiān)管的組件中Object: {:}{}--
    onChange當(dāng)有 field 監(jiān)管的子組件執(zhí)行 onChange 時(shí), 進(jìn)行回調(diào)(IEvents) => voidundefined--
    onSubmit當(dāng)有表單進(jìn)行提交時(shí), 進(jìn)行回調(diào)(IEvents) => voidundefined--
    onErrorCheck當(dāng)有 field 監(jiān)管的子組件的錯(cuò)誤校驗(yàn)結(jié)果發(fā)生變化時(shí), 進(jìn)行回調(diào)(IEvents) => voidundefined--

    IEvents API (回調(diào)函數(shù)的參數(shù))

    Form 組件回調(diào)函數(shù)的參數(shù)如下: ({isError, event, data, field, value, element, update }) => void

    具體的 API 描述如下:

    屬性描述類型默認(rèn)值必傳
    isError最后輸入的對象校驗(yàn)是否正確Booleanfalsetrue
    eventonChange 的原始返回對象Booleanundefinedfalse
    dataform.data 對象, 包含所有 field 監(jiān)管的值Object: {:}{}true
    field當(dāng)前修改的組件的 field 屬性Stringundefinedtrue
    value當(dāng)前修改的值Boolean''String or Number
    element當(dāng)前修改的 ReactElementBooleanReact.Elementtrue
    update更新某個(gè) field 監(jiān)管的對象(IEvents)=> {:}(IEvents)=> {:}true

    子組件關(guān)聯(lián)參數(shù)

    一個(gè)子組件可以被識別關(guān)聯(lián)的參數(shù)如下

    <inputfield="userName"submittype="submit"errorcheck={/123/}errorstyle={{ color: "#f00" }}errorclass="input-error-style"errorprops={{ disable: true }} /> 復(fù)制代碼

    具體的 API 描述如下:

    屬性描述類型默認(rèn)值必傳
    field用于標(biāo)記組件是否被 Form 組件監(jiān)聽, 并且也是 data 用于存放值的 keyStringundefined
    submit用于確定當(dāng)前對象是否可以響應(yīng) onClick 事件進(jìn)行提交Booleanundefined--
    toform注入ToForm 組件, 讓子組件對象也可以概括子表單Booleanundefined
    type當(dāng) type = "submit" 時(shí), 可以響應(yīng) onClick 事件進(jìn)行提交Object: {:}undefined--
    errorcheck用于校驗(yàn)當(dāng)前對象 value 是否錯(cuò)誤正則對象或函數(shù)undefined--
    errorstyle當(dāng)前對象 value 錯(cuò)誤時(shí), 合并 errorstyle 至 styleObjectundefined--
    errorclass當(dāng)前對象 value 錯(cuò)誤時(shí), 合并 errorclass 至 classNameStringundefined--
    errorprops當(dāng)前對象 value 錯(cuò)誤時(shí), 合并 errorprops 至 propsObjectundefined--

    以上就是全部, 希望 Den Form 能夠幫到你解決 React 表單相關(guān)的痛點(diǎn) :)

    轉(zhuǎn)載于:https://juejin.im/post/5c977e075188252d785f20b5

    總結(jié)

    以上是生活随笔為你收集整理的优雅地提高 React 的表单页面的开发效率的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。