日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2025/7/25 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 优雅地提高 React 的表单页面的开发效率 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Den Form

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

一個非常輕巧的 Form 實現, gzip 體積只有 3kb, 可以很方便跨越組件層級獲取表單對象, 或者管理聯動更新

安裝

$ yarn add react-den-form 復制代碼

基礎使用

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

field 屬性是 Form 組件用于標記哪一類子組件需要被監管的字段, 并且也是用于校驗更新的 key

field 可以重復, 但是如果兩個子組件擁有相同的 field 值, 那么當此類 field 需要更新時, 兩個子組件都會進行更新

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>); }; 復制代碼

當我們輸入數據后, 按回車鍵, onSubmit 方法打印如下:

{userName: "333"} 復制代碼

層級獲取數據不需要進行額外處理

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>); }; 復制代碼

當我們輸入數據時, onChange 方法打印如下:

{userName: "333", password: "555"} 復制代碼

Form 表單嵌套不需要處理

有時候, 我們會有一些頁面結構讓兩個不同的表單進行嵌套, 如登錄時, 驗證碼的輸入框在用戶名和密碼中間, 而驗證碼有單獨的請求. 當然, 我們可以更換實現方式, 但是對于這類場景, DenForm 默認處理了表單嵌套.

由于 Form 內部有一個 form 標簽, 外層 onSubmit 會捕獲所有子組件的 onSubmit 事件, 但是 data 數據只會捕獲 當前層級內的 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>); }; 復制代碼

跨組件的值獲取

  • 為對象標記一個 toform 屬性, 會為對象注入一個 ToForm 組件
  • 然后使用 ToForm 組件在對象內部對表單進行概括
  • 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>); }; 復制代碼

    當我們輸入數據時, onChange 方法打印如下:

    {userName: "333", password: "555", subPassword: "666"} 復制代碼

    自定義 Field 組件

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

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

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

    以下標簽, From 會自動識別 onChange 的返回值, 進行解析獲取

    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>); }; 復制代碼

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

    import React from "react"; import Form from "react-den-form";class SubInput extends React.Component {// 假定數據有一定的層級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>); }; 復制代碼

    onChangeGetter 的默認值相當于 onChangeGetter={e => e}

    表單提交

    以下三個情形為都會觸發 Form 的 onSubmit 函數:

    • 包含 field 屬性的對象中, 使用鍵盤的回車鍵
    • 包含 submit 屬性, 點擊(onClick)
    • 包含 type="submit" 屬性的對象中, 點擊(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>); }; 復制代碼

    異步請求提交

    Form 表單內部并無封裝請求行為, 請在 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>); }; 復制代碼

    上下文獲取數據

    我們為 Form 顯式注入一個 data, 當數據變化時, data 的值也會變化, 這樣可以在上下文獲取 Form 的數據

    // 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>);} } 復制代碼// 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>); }; 復制代碼

    輸入數據, 點擊 button, data 數據打印如下:

    { userName: "dog" } 復制代碼

    表單校驗

    表單校驗是無痛的, 并且是高效的

    我們給 input 組件添加 errorcheck 屬性, 該屬性可以是一個正則對象, 也可以是一個 函數, 如果 errorcheck 校驗的結果為 false, 就會將其他 error 相關的屬性賦予至組件中

    如下代碼, 如果 input 內容不包含 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>); }; 復制代碼

    表單校驗相關的 api:

    prop類型用途
    errorcheck正則或函數若返回值為 false, 將其他 error Api 應用至組件中
    errorstylestyle 對象若校驗為錯誤, 將 errorstyle 合并至 style 中
    errorclassclassName 字符串若校驗為錯誤, 將 errorstyle 合并至 className 中
    errorpropsprops 對象若校驗為錯誤, 將 errorprops 合并至整個 props 中

    為什么是 errorcheck 而不是 errorCheck ? 這是因為 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. 復制代碼

    表單校驗時進行特殊處理

    如果我們有一個需求, 當表單校驗錯誤時, 顯示一個提示信息, 當表單校驗通過時, 取消提示信息, 我們就需要對每次校驗有差異時, 進行處理

    使用 onChange 方法每次都會被執行, 可是我們只希望在表單校驗結果有變化時進行提示

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

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

    聯動

    當我們修改一個對象時, 根據某些條件, 希望修改另一個對象的行為我們稱之為聯動

    DenForm 的聯動是高性能的, 僅更新需要更新的對象

    我們可以在任何 Form 的回調函數中使用 update 進行更新某個被 field 捆綁的組件的 value 或者 props

    下面這個例子: 1. 當在 password 輸入時, 會將 userName 的 input 框內容改為 'new value'; 2. 當 userName 的 input 的內容包含 'aa' 時, 會將 password 的 value 和 style 進行修改;

    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>); }; 復制代碼

    性能開銷

    Form 存在的意義在于簡化開發, 用計算機的時間換取開發者的時間, 所以會有一些性能開銷.

    但是 Form 的開銷絕對不大, 因為 Form 內部更新時只會針對指定的子組件進行更新.

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

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

    我們有理由相信, 在一個設計合理的應用中, 每個 Form 包裹的組件個數應該是有限的

    支持哪些 React 渲染層 ?

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

    如 ReactNative 中, 在項目之初設定:

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

    API

    Form API

    屬性描述類型默認值必填
    data用于捆綁上下文的 data 對象, 也會當成默認值設置到相應的 field 監管的組件中Object: {:}{}--
    onChange當有 field 監管的子組件執行 onChange 時, 進行回調(IEvents) => voidundefined--
    onSubmit當有表單進行提交時, 進行回調(IEvents) => voidundefined--
    onErrorCheck當有 field 監管的子組件的錯誤校驗結果發生變化時, 進行回調(IEvents) => voidundefined--

    IEvents API (回調函數的參數)

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

    具體的 API 描述如下:

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

    子組件關聯參數

    一個子組件可以被識別關聯的參數如下

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

    具體的 API 描述如下:

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

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

    轉載于:https://juejin.im/post/5c977e075188252d785f20b5

    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。