你不知道的React系列(四十五)DOM 元素

136 阅读2分钟

在 React 中,所有的 DOM 特性和属性(包括事件处理)都应该是小驼峰命名的方式

属性差异

  • aria-* 以及 data-* 属性,自定义属性全部小写字母

  • onAbort 和 onLoad React 冒泡,浏览器不冒泡

  • checked

    • 当 <input> 组件的 type 类型为 checkbox 或 radio 时,组件支持 checked 属性

    • defaultChecked 则是非受控组件的属性,用于设置组件首次挂载时是否被选中

  • className

    • 所有常规 DOM 节点和 SVG 元素

    • Web Components 使用 class

  • dangerouslySetInnerHTML

    • React 为浏览器 DOM 提供 innerHTML 的替换方案
    • 你不能同时使用 children 和 dangerouslySetInnerHTML
    • __html对象
    const markup = { __html: '<p>some raw html</p>' };
    return <div dangerouslySetInnerHTML={markup} />;
    
  • htmlFor 代替 for

  • onChange

    每当表单字段变化时,该事件都会被触发

  • selected

    <option> 标记为已选中状态

  • style

    • 在渲染过程中添加动态计算的样式

    • 小驼峰命名属性的 JavaScript 对象

    • 样式不会自动补齐前缀

      const divStyle = {
        WebkitTransition: 'all', // note the capital 'W' here
        msTransition: 'all' // 'ms' is the only lowercase vendor prefix
      };
      
      function ComponentWithTransition() {
        return <div style={divStyle}>This should work cross-browser</div>;
      }
      
    • 自动添加 ”px” 后缀到内联样式为数字的属性后

  • suppressContentEditableWarning

    子节点的元素被标记为 contentEditable关闭警告

  • suppressHydrationWarning

    不会警告服务端和客户端属性与元素内容不一致

  • value

    • <input><select> 和 <textarea> 组件支持 value 属性

    • defaultValue 属性对应的是非受控组件的属性,用于设置组件第一次挂载时的 value

  • 自定义属性,属性名全都为小写

Input

  • Checkboxes 接收 checked defaultChecked 属性

  • label 标签嵌套或者 htmlFor

    import { useId } from 'react';
    
    export default function Form() {
      const ageInputId = useId();
      return (
        <>
          <label>
            Your first name:
            <input name="firstName" />
          </label>
          <hr />
          <label htmlFor={ageInputId}>Your age:</label>
          <input id={ageInputId} name="age" type="number" />
        </>
      );
    }
    
  • form 提交表单

    form 包含的 button 按钮默认都是提交按钮

    export default function MyForm() {
      function handleSubmit(e) {
        // Prevent the browser from reloading the page
        e.preventDefault();
    
        // Read the form data
        const form = e.target;
        const formData = new FormData(form);
    
        // You can pass formData as a fetch body directly:
        fetch('/some-api', { method: form.method, body: formData });
    
        // Or you can work with it as a plain object:
        const formJson = Object.fromEntries(formData.entries());
        console.log(formJson);
      }
    
      return (
        <form method="post" onSubmit={handleSubmit}>
          <label>
            Text input: <input name="myInput" defaultValue="Some initial value" />
          </label>
          <hr />
          <label>
            Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
          </label>
          <hr />
          <p>
            Radio buttons:
            <label><input type="radio" name="myRadio" value="option1" /> Option 1</label>
            <label><input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Option 2</label>
            <label><input type="radio" name="myRadio" value="option3" /> Option 3</label>
          </p>
          <hr />
          <button type="reset">Reset form</button>
          <button type="submit">Submit form</button>
        </form>
      );
    }
    
  • input 组件封装在一个组件里面改善性能

问答

  • 每次输入 input 光标就跳到开始

    • 必须同步更新
    • input 移除重新添加到 DOM
    • input 组件或者它的父组件设置了 key
    • 函数写在了组件内部
  • A component is changing an uncontrolled input to be controlled

    value 设置了 null 或 undefined

option

option 不支持 selected 属性

使用 <select defaultValue><select value>

progress

  • value 为 null,循环运行
  • max 默认为 1

select

form 表单

export default function EditPost() {
  function handleSubmit(e) {
    // Prevent the browser from reloading the page
    e.preventDefault();
    // Read the form data
    const form = e.target;
    const formData = new FormData(form);
    // You can pass formData as a fetch body directly:
    fetch('/some-api', { method: form.method, body: formData });
    // You can generate a URL out of it, as the browser does by default:
    console.log(new URLSearchParams(formData).toString());
    // You can work with it as a plain object.
    const formJson = Object.fromEntries(formData.entries());
    console.log(formJson); // (!) This doesn't include multiple select values
    // Or you can get an array of name-value pairs.
    console.log([...formData.entries()]);
  }

  return (
    <form method="post" onSubmit={handleSubmit}>
      <label>
        Pick your favorite fruit:
        <select name="selectedFruit" defaultValue="orange">
          <option value="apple">Apple</option>
          <option value="banana">Banana</option>
          <option value="orange">Orange</option>
        </select>
      </label>
      <label>
        Pick all your favorite vegetables:
        <select
          name="selectedVegetables"
          multiple={true}
          defaultValue={['corn', 'tomato']}
        >
          <option value="cucumber">Cucumber</option>
          <option value="corn">Corn</option>
          <option value="tomato">Tomato</option>
        </select>
      </label>
      <hr />
      <button type="reset">Reset</button>
      <button type="submit">Submit</button>
    </form>
  );
}

textarea

  • textarea 没有 children,使用 defaultValue
  • resize: none