zoukankan      html  css  js  c++  java
  • JavaScript 和 React,React用了大量语法糖,让JS编写更方便。


    https://reactjs.org/docs/higher-order-components.htmlhttps://codepen.io/gaearon/pen/WooRWa?editors=0010

    JSX in Depth

    https://babeljs.io/  JS编译器,学习react和JS直接的转换。

     JSX仅支持句法糖syntactic sugar:

    React.createElement(component, props, ...children)函数,

    JSX code:

    <MyButton color="blue" shadowSize={2}>
     Click Me
    </MyButton> 

     编译compiles into:

    React.createElement(

      MyButton,
      {color: 'blue', shadowSize: 2},
      'Click Me'
    )   

    也可以使用self_closing form of the tag if there are no children. So:

    <div className="sidebar" />

    compiles into:

    React.createElement(
      'div',
      {className: 'sidebar'},
      null
    )

    函数形式的:

    function hello() {

      return <div>Hello world!</div>; 

    转换为:

    function hello() {
      return React.createElement(
        'div',
        null,
        'Hello world!'
      );
    }

    关于React元素的格式: 

    React 一定在Scope内。

    使用. Dot Notaiton ,可以在JSX中使用点符号。如果一个模块要调出一些React组件,这样就方便了。例子:

    import React from 'react';
    const MyComponents = {
      DatePicker: function DatePicker(props) {
        return <div>Imagine a {props.color} datepicker here.</div>;
      }
    }
    function BlueDatePicker() {
      return <MyComponents.DatePicker color="blue" />;
    }

    自定义的组件必须首字母大写(除非分配它一个首字母大写的变量)。function Hello(props){...} 

    在运行时选择类型Choosing the type at runtime 

    不能把表达式用做React element type。但是可以把它分配给一个大写字母的变量,然后就可以间接用JSX格式了

    import React from 'react';
    import { PhotoStory, VideoStory } from './stories';
    const components = {
      photo: PhotoStory,
      video: VideoStory
    };
    function Story(props) {
      // Wrong! JSX type can't be an expression.
      return <components[props.storyType] story={props.story} />;
    }
    function Story(props) {
      // Correct! JSX type can be a capitalized variable.
      const SpecificStory = components[props.storyType];
      return <SpecificStory story={props.story} />;
    }

     Props in JSX

    通过{}, 任何JS expression 都可以作为props. 例如<MyComponent foo={1 + 2 + 3 + 4} />

    if statements and for loops 不是JS表达式,不能直接用于JSX。但{}就能用了

    function NumberDescriber(props) {
      let description;
      if (props.number % 2 == 0) {
        description = <strong>even</strong>;
          } else {
            description = <i>odd</i>
          }
      return <div>{props.number} is an {description} number</div>;
    }

    条件判断 Inline的写法: 

    {true && expression}  //如果是true,则执行表达式。 

    {condition ? true : false }

    防止组件被渲染:

    return null; ⚠️,组件的lifecycle 方法钩子方法,仍然生效componentWillUpdate 和 componentDidUpdate。


    Children in JSX

    string Literals

    <div>This is valid HTML &amp; JSX at the same time.</div>

    &amp; 就是& 

    编译:

    React.createElement(
      "div",
      null,
      "This is valid HTML & JSX at the same time."
    );

    JSX移除一行开头和结尾的空格

    JSX Children

    支持内嵌JSX元素作为孩子。在嵌套组件中很有用。

    React组件也返回数组元素。return [, ,]; 

    JS expression也可以作为孩子。

    function Item(props) {
      return <li>hello, {props.message}</li>;  //props.children
    }
    function TodoList() {
      const todos = ['finish', 'submit ', 'review'];
      return (
        <ul>

    //这个是函数作为props.children。 

          {todos.map(message =>
            <Item key={message} message={message} />
          )} 
        </ul>
      );
    }

    Function as Children 

     见标黄的代码.React.createElement(component, props,...child)

    function Repeat(props) {
      let items = [];
      for (let i= 0; i < props.numTimes; i++) {
        items.push(props.children(i));
      }
      return <div>{items}</div>;
    }
    function ListOfTenThings() {
      return (
        <Repeat numTimes={10}>
          {(index) => <div key={index}>{index}:This is item {index}</div>}
        </Repeat>
      );
    }

     

    Booleans, Null, and Undefined are Ignored. 

    false ,null, undefined, true都是验证的孩子,不过它们不渲染。

    所以可以作为条件判断 condition && expression。

    如果showHeader是true则渲染<Header />

    <div>
      {showHeader && <Header />}
      <Content />
    </div>

    ⚠️ 0会被渲染

    如果要让true渲染使用类型转换,String()。 


    Typechecking With PropTypes(未看)

    用于检查输入的一个方法PropTypes ,这是React内置的方法,JS扩展中也有Flow,TypeScript等扩展插件。

    大型的代码检查,官方推荐使用Flow or TypeScript 而不是用默认的。 

    https://reactjs.org/docs/typechecking-with-proptypes.html 

    PropTypes输出了一组验证器用于确保你接收的数据是通过验证的。如果一个未通过验证的值提供给一个prop,一条warning会显示在JS console中。propTypes只用于开发模式。

    import PropTypes from 'prop-types';
    class Greeting extends React.Component {
      render() {
        return (
          <h1>Hello, {this.props.name}</h1>
        );
      }
    }
    Greeting.propTypes = {
      name: PropTypes.string    //确保是string类的值,否则报告⚠️信息。
    };

    Refs ans the DOM(未看)

    https://reactjs.org/docs/refs-and-the-dom.html 

    在典型的数据流模式,组件之间的交互使用props。但有少数情况属于例外情况。

    Refs提供了一个方法,能够使用DOM nodes 和React elements created in the render method。React提供了这个escape hatch逃生舱门。

    何时用:

    • 管理focus,text selection ,media playback
    • 合并第三方DOM库
    • 打开必要的动画Triggering imperative animations 
    React.createRef:

    创建一个ref可以附加到React elements 

    this.myRef = React.createRef() 并通过ref属性付给React元素


    Uncontrolled Components 

    推荐使用controlled components 来实现forms, 这时,表格数据被React组件处理。

    但我们也可以用别的方式,这时,表格data被DOM自身处理。 

    既然非控制组件保持了DOM的原生性,有时它比较容易合并React和非React代码。如果你想要更快并不在乎代码太脏(可读性差),也能够稍微少输入点代码。

    你应该尽量用可控制的组件。

     https://codepen.io/gaearon/pen/WooRWa?editors=0010

     红字是用原生DOM加ref。

    class NameForm extends React.Component {
      constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleTextChange = this.handleTextChange.bind(this);
        this.state = {text: ""};
      }
      
      handleTextChange(e) {
        this.setState({text: e.target.value});
      }
      
      handleSubmit(e) {
        // alert("A name was submitted: " + this.input.value);
        alert("A name was submitted: " +  this.state.text);
        e.preventDefault();
      }
      
      render() {
        return (
          // <form onSubmit={this.handleSubmit}>
          //   <label>
          //     Name:
          //     <input type="text" ref={(input) => this.input = input}  />
          //   </label>
          //   <input type="submit" value="Submit" />
          // </form>
          <form>
            <label>
              Name:
              <input type="text" onChange={this.handleTextChange}/>
            </label>
            <input type="submit" value="Submit" onClick={this.handleSubmit} />
          </form>
        );
      }
    }
    ReactDOM.render(
      <NameForm />,
      document.getElementById('example')
    );

    Optimizing Performance(略读)

    优化执行的方法和工具。

    使用React Developer Tools for Chrome.(也有其他浏览器版本) 

    这个工具可以制作Timeline可视化每个组件mount update, unmount. 


    Context(一个不使用传统方法传递数据的方法。)

    https://reactjs.org/docs/context.html 

    一整章节,暂时不看。


     Fragments

    让你返回多个元素在一个render()方法中,不需要创建一个额外的DOM 元素。

    The React.Fragment component lets you return multiple elements in a render()method without creating an additional DOM element:
    render() {
      return (
        <React.Fragment>
          <ChildA />
          <ChildB />
          <ChildC />
        </React.Fragment>
      );
    }

    这时如果是静态的可以不加key,最好加上。另外用[]也可以,但必须加key

     HTML description list:

    <dl>

      <dt>

        <dd></dd>

      </dt> 

    </dl> 


    Portals

    大门,入口。 

    https://reactjs.org/docs/portals.html 

    渲染孩子进入一个Dom节点 

    ReactDOM.createPortal(child,container) 

    第一个参数是任意的渲染的React child。如an element, string, or fragment. 

    第二个参数container是一个DOM元素。 

    一般来说,从一个组件的渲染方法中返回一个元素,它作为孩子附加在离它最近的父节点后。

    而使用createPortal这样就可以插入一个孩子到DOM中不同的位置。 (但仍然受到父组件event事件的影响)

     案例:https://codepen.io/gaearon/pen/yzMaBd?editors

        return (
          <div className="app">
            This div has overflow: hidden.
            <button onClick={this.handleShow}>Show modal</button>
            {modal}  //看似是在这个block中,其实Modal组件使用了createProtal()把自己插入到了其他DOM节点。
          </div>
        );

    Event Bubbling Through Portals

    a portal可以插入到在DOM tree的任何位置,不过它在其他方面仍旧是一个普通的React child。

    假如:在一个父组件中渲染一个子组件(Modal),那么Modal就可以被这个父组件捕捉到。这个父组件不会考虑Modal是否用了protals。

    即便Modal用了protal把代码插入到不属于父组件的其他节点,父组件仍然可以捕捉到Modal,父组件定义了一个点击事件,对Modal中的元素进行点击也会触发父组件的点击事件。

    案例:https://codepen.io/chentianwei411/pen/ZoLeBE?editors=0010 


    Error Boundaries 

    错误边界。 目的:解决仅仅是部分UI的错误就会造成整个app崩溃的问题。

    Error boundaries也是一个React组件。JS 错误发生在子组件的任何位置,它都可以捕捉到,并且log those errors, 并且display a fallback UI。

    Error boundaries 捕捉错误是在渲染的时候,因此lifecycle methods 和 constructors of the whole tree都低于Error boundaries.

    ⚠️以下超出了Error-b的使用范围:

    Event handlers, 异步代码, 服务器端渲染, 自身抛出错误。


    Higher-Order Components (基本用法,一些约定没有看。)

    一种代码的抽象化, 根据dry原则,把有相同逻辑的组件重构。

    即重构一个函数,这个函数接受一个组件并return 一个新组件。 

    要点:发现有很多相同逻辑(内部代码基本一样)的组件, 为了减少代码的量和便于阅读维护。

     https://reactjs.org/docs/higher-order-components.html

     // 调用Highter-Order组件withSubscription.把返回的新组件存入一个JSX.

    const CommentListWithSubscription = withSubscription(

      CommentList,

      (DataSource) => DataSource.getComments() 

    ); 

    const BlogPostWithSubscription = withSubscription(
      BlogPost,
      (DataSource, props) => DataSource.getBlogPost(props.id)
    );

    function withSubscription(WrappedComponent,  selectData) {

      //WrappedComponent是组件名字, selectData是数据及其使用的methods。 

      return class extends React.Component {...} ;  //class后面没有组件名字

    ⚠️ ,不要在higher-order组件中对原有组件修改,如果需要组件进行功能的变化,把这个变化写在return中。

    ⚠️, 约定convension: 传递不相关的props,通过wrapped 组件。 在render方法中使用不相关的props.


    Render Props

    术语render prop是一个简单的技术:在React组件之间,通过使用一个值是函数的prop来分享代码。

    The term "render prop" refers to a simple technique for sharing code between React components using a prop whose value is a function. 

    <DataProvider render={data => (
      <h1>Hello {data.target}</h1>
    )}/>

    一个组件带着一个render prop,这个组件渲染的时候可以使用这个render prop的值

    a render prop is a function prop that a component uses to know what to render.

     https://reactjs.org/docs/render-props.html


     


    React.Component 

    组件的lifecycle methods

    Methods prefixed with will are called right before sth happens. did are called after sth happens. 

    Mounting

    这些方法在一个组件实例被创建和插入DOM时调用。 

    constructor(props){...}   //在加载组件前调用。

    before it is mounted,如果组件是一个子类,还需要在其他声明前面调用super(props)。 constructor()用于初始化state。也用于bind event-handlers to the class instance.

    分配给this.state的对象可以包含props。但⚠️这不是时时更新的,最好不这么用,例子: 

      this.state = {
        color: props.initialColor
      };


    UNSAFE_componentWillMount()   //在加载组件前引用。它在render()前调用。

    render() 

    When called, it should examine this.props and this.state and return one of the following types:

    • React elements. 包括自定义的组件或原生的DOM component <div />
    • String and numbers. 作为text nodes 渲染在DOM中。
    • Portals. Created with ReactDOM.createPortal 
    • null 什么也不加载
    • Booleans。一般用于 return test && <Child />模式,当test是true时,加载后面
    ⚠️ shouldComponentUpdate()方法返回false时,不加载render()

    componentDidMount()   //在组件加载后立即引用

    用途:

    加载远程endpoint的数据,这里可以实例化network request。

    也可以建立任何订阅并配合componentWillUnmount()取消订阅。 

    调用setState(),会激活额外的rendering. 

    Updating

     一个update会被props或state的改变引起。下面的方法当一个组件被再加载时调用。(只看了其中几个,一共7个方法)

    componentWillReceiveProps() 

    在一个已经加载的组件再次接收新的props之前引用这个方法。 这个方法限制很多不推荐用。

    shouldComponentUpdate(nextProps, nextState)

    返回true,false。让React知道一个组件的输出是否被当前state or propsde 变化所影响。如果是true,则组件再render()。方法默认是true。所以一般不主动使用这个方法。 

    如果是false,render(), componentWillUpdate(), componentDidUpdate()不会调用。

    componentWillUpdate(nextProps, nextSate)

    当一个新props or state 被接收到后,在渲染之前引用。

    render() 

    每次更新props or state后,调用render(). 

    componentDidUpdate(prevProps, prevState, snapshot) 

    在更新发生后,立即引用。

    Unmounting

    • componentWillUnmount(): 在一个组件被卸载和删除前立即引用。用于执行必要的清洁。如未验证的timers, 取消网络请求, 清洁任何在componentDidMount()中的订阅
    Error Handing
    •  componentDidCatch():这个方法被调用当一个❌发生在渲染中,在lifecyle方法中,或者在一个孩子组件的constructor中。

    Other APIS

    setState()

    enqueuqs changes to the component state and tells React that this component and its children need to be re-rendered with the updated state.

    改变组件的状态state并告诉React“组件和它的孩子需要根据更新的state再渲染”

    这是一个主要的方法,用来更新user interface in response,事件处理和服务器响应。

    把setState()当作一个request,而不是更新组件的即时命令。 

    setState()不总是立即执行更新组件,因为它类似request,有延迟。因此,使用componentDidUpdate或者setState(updater, callback)可以保证fire(立即执行).


    setState(updater, callback)

    updater是一个函数:(prevState, props) => stateChange   //prevState是之前state的一个引用。 例子:用props.step增加一个值到state中。

    this.setState((prevState, props) => {
      return {counter: prevState.counter + props.step};
    }); 

    callback参数是可选的函数。在setState完成更新,组件被再渲染后执行这个函数,推荐使用componentDidUpdate代替。 

    第一个参数可以是一个对象object.代替一个函数。 这个执行会把状态变化合并到新状态中。 

    this.setState({quantity: 2}) 

    forceUpdate() 

    component.forceUpdate(callback),如果render()方法依靠其他数据源,你可以告诉组件调用forceUpdate()来再渲染。个人理解:这个方法就是用来执行渲染的。

    Class Properties

    defaultProps

    给组件的property设定默认值。 

    class CustomButton extends React.Component {
      // ...
    }
    CustomButton.defaultProps = {
      color: 'blue'
    };

    渲染的时候自动增加上color="blue"

    render() {
      return <CustomButton /> ; // props.color will be set to blue
    }

     displayName 

     https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging

    debug用。

    Instance Properties

    • props
    • state 


    ReactDOM 

    import ReactDOM from 'react-dom'

    react-dom package提供了DOM-specific methods。大多数组件不需要使用这个module.

    ReactDOM.render(element, container[, callback]) 

    渲染一个React element到DOM中。具体位置是container, 返回a reference 给组件。

    如果之前已经渲染进container中,更新时只修改必要的部分。

    callback可选,在组件渲染或更新后执行.

    createPoratal() 

    ReactDOM.createPortal(child, container) 


    hydrate()
    unmountComponentAtNode()
    findDOMNode()

    ReactDOMServe

    import ReactDOMServer from 'react-dom/server'; 

    用于把组件渲染到静态标记中,一般用于一个Node server

    这两个方法可以用于server,也可以用在浏览器。 

    renderToString()

    renderToStaticMarkup() 

    ReactDOMServer.renderToString(element) 

    渲染一个React元素到 原始HTml. React返回一个HTML string。


    DOM Elements

    https://reactjs.org/docs/dom-elements.html 

    style 

    style属性可以接受JS 对象。属性要用驼峰写法。如backgroundImage. px可以省略

    const divStyle = {
      color: 'blue',
      background: 'lightblue',
    };
    function Hello() {
      return <div style={divStyle}>Hello World!</div>;
    }

    value 

    <input>, <textarea>组件支持value属性。

    className 

    用来指定css class的名字。

    checked 

    <input>组件中的type类型为checkbox or radio的支持这个属性。 

    All Supported HTML Attributes 


    SyntheticEvent 

    人工事件

    event handlers被传到人工事件的实例,一个跨浏览器的包裹器(包含浏览器的原生事件)。

    每个SyntheticEvent对象有一系列的属性attributes:如:

    currentTarget, target, type, timeStamp, isTrusted, preventDefault()等等。 

     https://reactjs.org/docs/events.html

  • 相关阅读:
    docker是PaaS,与openstack是IaaS的关系
    nuget安装.net standard
    GitHub sync the original repository by pull request
    Is there a way to include commas in CSV columns without breaking the formatting?
    How to determine why visual studio might be skipping projects when building a solution
    IHttpHandler vs IHttpModule
    .NET 3.0 SDK Projects not Loading
    Microsoft Edge version
    Microsoft Edge High CPU and Memory
    Google Analytics
  • 原文地址:https://www.cnblogs.com/chentianwei/p/8960912.html
Copyright © 2011-2022 走看看