美文网首页
React 入门知识(二)

React 入门知识(二)

作者: 风之化身呀 | 来源:发表于2018-06-12 19:21 被阅读22次

事件处理

  • 传参注意点
class Popper extends React.Component{
    constructor(){
        super();
        this.state = {name:'Hello world!'};
    }
    
    preventPop(name, e){    //事件对象e要放在最后
        e.preventDefault();
        alert(name);
    }
    
    render(){
        return (
            <div>
                <p>hello</p>
                {/* Pass params via bind() method. */}
                <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
            </div>
        );
    }
}
  • 怎样避免函数被调用太快或者太多次
// 节流
import throttle from 'lodash.throttle';

class LoadMoreButton extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    this.handleClickThrottled = throttle(this.handleClick, 1000);
  }

  componentWillUnmount() {
    this.handleClickThrottled.cancel();
  }

  render() {
    return <button onClick={this.handleClickThrottled}>Load More</button>;
  }

  handleClick() {
    this.props.loadMore();
  }
}

https://doc.react-china.org/docs/handling-events.html
https://doc.react-china.org/docs/faq-functions.html
https://doc.react-china.org/docs/events.html

ref

  • 创建ref
// 1、React v16.3 引入的 React.createRef() 
// 1.1、用在内置组件上
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  focusTextInput() {
    // 注意:通过 "current" 取得 DOM 节点
    this.myRef .current.XX;
  }
  render() {
    return <div ref={this.myRef} />;
  }
}
// 1.2、用在自定义组件上

// 2、低于v16.3的可以使用回调refs
class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = null;
    this.setTextInputRef = element => {
      this.textInput = element;
    };
    this.focusTextInput = () => {
      // 直接使用原生 API 使 text 输入框获得焦点
      if (this.textInput) this.textInput.focus();
    };
  }
  componentDidMount() {
    // 渲染后文本框自动获得焦点
    this.focusTextInput();
  }
  render() {
    // 使用 `ref` 的回调将 text 输入框的 DOM 节点存储到 React
    // 实例上(比如 this.textInput)
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef}
        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

高阶组件

高阶组件(HOC)是react中对组件逻辑进行重用的高级技术。高阶组件就是一个函数,一个没有副作用的纯函数,且该函数接受一个组件作为参数,并返回一个新的组件。

function logProps(WrappedComponent) {
  return class extends React.Component {
    componentWillReceiveProps(nextProps) {
      console.log('Current props: ', this.props);
      console.log('Next props: ', nextProps);
    }
    render() {
      // 用容器组件组合包裹组件且不修改包裹组件,这才是正确的打开方式。
      return <WrappedComponent {...this.props} />;
    }
  }
}
  • 别将不相关的props属性传递给包裹组件
    高阶组件应该传递与它要实现的功能点无关的props属性
render() {
  // 1、过滤掉与高阶函数功能相关的props属性
  const { extraProp, ...passThroughProps } = this.props;

  // 2、向包裹组件注入props属性,一般都是高阶组件的state状态或实例方法
  const injectedProp = someStateOrInstanceMethod;

  // 3、向包裹组件传递props属性(extraProp已被过滤)
  return (
    <WrappedComponent
      injectedProp={injectedProp}
      {...passThroughProps}
    />
  );
}
  • 必须将静态方法做拷贝
// 定义静态方法
WrappedComponent.staticMethod = function() {/*...*/}
// 使用高阶组件
const EnhancedComponent = enhance(WrappedComponent);
// 增强型组件没有静态方法
typeof EnhancedComponent.staticMethod === 'undefined' // true

可以使用hoist-non-react-statics来帮你自动处理,它会自动拷贝所有非React的静态方法:

import hoistNonReactStatic from 'hoist-non-react-statics';
function enhance(WrappedComponent) {
  class Enhance extends React.Component {/*...*/}
  hoistNonReactStatic(Enhance, WrappedComponent);
  return Enhance;
}
  • Refs属性不能传递
    一般来说,高阶组件可以传递所有的props属性给包裹的组件,但是不能传递refs引用。因为并不是像key一样,refs是一个伪属性,React对它进行了特殊处理。如果你向一个由高阶组件创建的组件的元素添加ref应用,那么ref指向的是最外层容器组件实例的,而不是包裹组件
    https://doc.react-china.org/docs/higher-order-components.html

受控与非受控组件

  • 在HTML当中,像<input>,<textarea>, 和 <select>这类表单元素会维持自身状态,并根据用户输入进行更新(浏览器默认行为,脱离了React的state控制)。但在React中,可变的状态通常保存在组件的state中,并且只能用 setState() 方法进行更新。React为了保证数据来源的单一性,提出了“受控组件”的技术
  • 所谓“受控组件”技术不过是对input等标签的使用方式不同而已,如input的value和onChange均由React自己控制
class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  handleChange(event) {
    this.setState({value: event.target.value});
  }
  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

// 同样的还有 textarea 和 select
<textarea value={this.state.value} onChange={this.handleChange} />
// select 受控用法
<select value={this.state.value} onChange={this.handleChange}>
      <option value="grapefruit">Grapefruit</option>
      <option value="lime">Lime</option>
      <option value="coconut">Coconut</option>
      <option value="mango">Mango</option>
</select>
// select 非受控用法
<select>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
  <option selected value="coconut">Coconut</option>
  <option value="mango">Mango</option>
</select>
  • 当你有处理多个受控的input元素时,你可以通过给每个元素添加一个name属性,来让处理函数根据 event.target.name的值来选择做什么
  • 非受控组件,多半会用到ref属性,(非受控组件将真实数据保存在 DOM 中)
class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={(input) => this.input = input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}
  • 在 React 的生命周期中,表单元素上的 value 属性将会覆盖 DOM 中的值。使用非受控组件时,通常你希望 React 可以为其指定初始值,但不再控制后续更新。要解决这个问题,你可以指定一个 defaultValue 属性而不是 value。同样,<input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked,<select> 和 <textarea> 支持 defaultValue.

https://doc.react-china.org/docs/forms.html
https://doc.react-china.org/docs/uncontrolled-components.html

与DOM异同

  • 在React中,所有的DOM特性和属性(包括事件处理函数)都是小驼峰命名法命名。aria-(无障碍访问相关)和data-属性是例外的,一律使用小写字母命名。
  • 在React中,使用className属性指定一个CSS类;而不是class
  • dangerouslySetInnerHTML替代DOM中的innerHTML
  • htmlFor替代DOM中的for (label标签)
  • style属性接受一个键为小驼峰命名法命名的javascript对象作为值,而不是像css字符串.要注意,样式属性不会自动补齐前缀的。为了支持旧的浏览器,你需要手动支持相关的样式特性
  • 受控组件

相关文章

网友评论

      本文标题:React 入门知识(二)

      本文链接:https://www.haomeiwen.com/subject/gtyleftx.html