zoukankan      html  css  js  c++  java
  • React 介绍

    ttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

    The smallest React example looks like this:

    ReactDOM.render( 
     <h1>Hello, world!</h1>, 
     document.getElementById('root') 
    );
     

    介绍JSX 

    a syntax extension to JavaScript. 

    const element = <h1>hello, world</h1>;

    这不是string也不是HTML,这是JSX。是JS语法的扩展。 

    用途:在UI和JS代码混合工作时,作为可视化的助手 ;另外,JSX 让React 显示很多有用的错误和警告信息。

    1.Embedding Expressions in JSX .在JSX中插入JS表达式,用{}括起来。

    2.JSX 本身也是Expression.。 可以把JSX用在if,for, 分配给变量,作为参数,和从函数返回。 

    3.可以用字符串作为属性值,可以用{}插入JS expression给属性赋值。

    const element = <div tabIndex="0"></div>; 

    const element = <img src={user.avatarUrl}></img> 

    JSX更像是JavaScript,所以属性要用驼峰写法class-> className 

    4.如果tag是空的,可以用简写法:

    const element = <img src={user.avatarUrl} />

    5.JSX tags may contain children:就是可以嵌套

    const element = (
      <div>
        <h1>Hello!</h1>
        <h2>Good to see you here.</h2>
      </div>
    );

    6.React.createElement()方法,相等。这个对象称为 React element.

    const element = React.createElement(
      'h1',
      {className: 'greeting'},
      'Hello, world!的'
    );
    const element = (
      <h1 className="greeting">
        Hello, world!
      </h1>
    );

    Rendering Elements

    React element 是 components的组成部分。

    假设有<div id="root"></div>,使用ReactDOM.render操作DOM节点: 

    const element = <h1>Hello,world!</h1>;
    ReactDOM.render(element, document.getElementById('root'));

    相当于JS中的document.getElementById("root").innerHTML = element; 

    React element是惰性的,不能改它的属性和孩子。 

    React element只在必要的时候更新:

    function tick() {
      const element = (
        <div>
          <h1>Hello, world!</h1>
          <h2>It is {new Date().toLocaleTimeString()}.</h2>
        </div>
      );
      ReactDOM.render(element, document.getElementById('root'));
    }
    setInterval(tick, 1000);

    因为用setInterval函数每秒调用一次tick函数,同时element内部的代码new Date(),所以React element元素更新了。


    Components and Props

    组件比较像JS function,接受输入( props舞台道具 )并返回React elements

    最简单定义一个component:使用JS函数。(相对简洁)

    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }

    这个函数是一个React component,因为它接收了一个props object argument 作为数据并返回一个React element

    也可以使用ES6 class来定义一个组件:

    class Welcome extends React.Component {
      render() {
        return <h1>Hello, {this.props.name}</h1>;
      }
    }

    Rendering a Component 

    const element = <div />;

    这个React element代表Dom tag.⚠️首字母用小写,代码DOM tags.

    另外,也可以element也可以代表自定义组件,⚠️首字母用大写,代表组件。

    const element = <Welcome name="Sara" /> ;

    当这么用时,调用Welcome组件,并传递JSX属性给这个组件,这个属性是一个object,称为object"props",最后返回组件的结果。

    例子:

    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }
    const element = <Welcome name="Sara" />;
    ReactDOM.render(
      element,
      document.getElementById('root')
    );

    过程: 

    1. We call ReactDOM.render() with the <Welcome name="Sara" /> element.
    2. React calls the Welcome component with {name: 'Sara'} as the props.
    3. Our Welcome component returns a <h1>Hello, Sara</h1> element as the result.
    4. React DOM efficiently updates the DOM to match <h1>Hello, Sara</h1>.

    组件可以在它们的输出中加入别的组件 

    例子:

    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }
    function App() {
      return (
        <div>
          <Welcome name="Sara"/>
          <Welcome name="Cahal"/>
          <Welcome name="Edite"/>
        </div>
      );
    }
    ReactDOM.render(
      <App />,
      document.getElementById('root')
    );

     

    Extracting Components 

    如果一个组件过于复杂,或者一个组件可以在程序中多次使用,那么可以把它提取出来。类似于Ruby中的dry原则。

    Props are Read-Only



    State and Lifecycle 

    State类似于props,但是是私有的,只能被组件控制。

    当组件使用class来定义时增加了一些新的features,其中Local state就是其中之一 

    Converting a Function to a Class

    1. Create an class, with the same name, that extends React.Component.
    2. Add a single empty method to it called render().
    3. Move the body of the function into the render() method.
    4. Replace props with this.props in the render() body.
    5. Delete the remaining empty function declaration.

    例子:https://codepen.io/gaearon/pen/zKRGpo?editors=0010


    function Clock(props) {
      return(
        <div>
          <h1>Hello, world!</h1>
          <h2>It is {props.data.toLocaleTimeString()}.</h2>
        </div>
      );

    function tick() {

      ReactDOM.render(

        <Clock data={new Date()}  />,
        document.getElementById('root')
      );
    }
    setInterval(tick, 1000);
    Adding Local State to a Class 

    3步:

    1. Replace this.props.date with this.state.date in the render() method;
    2. Add a class constructor that assigns the initial this.state: 
      constructor(props) {
          super(props);
          this.state = {date: new Date()};
      }
      constructor 方法是一个特殊的方法用来创造和初始化一个对象伴随着一个类。因此这个类中只能有这么一个constructor方法。

      constructor使用super关键字来调用自己父类的constructor.

         3. Remove the date prop from the <Clock />element. 并去掉剩余函数

    结果:

    class Clock extends React.Component {
      constructor(props) {
        super(props);
        this.state1 = {data: new Date()};  //就是定义一个变量对象
      }
      
      render() {
        return(
          <div>
            <h1>Hello, world!</h1>
            <h2>It is {this.state1.data.toLocaleTimeString()}.</h2>
          </div>
        );
      }
    }
    ReactDOM.render(
      <Clock />,
      document.getElementById('root')
    );

    Adding Lifecycle Methods to a Class

    在组件类中定义特殊的方法componentDidMount(),componentWillUnmount(),当一个组件加载mounting,和卸载unmounting时。

    这两个方法叫lifecycle hooks。类似于Ruby中的after_action。钩子方法。 

      componentDidMount() {
        this.timerID = setInterval(
          () => this.tick(),
          1000
        );
      }
      
      componentWillUnmount() {
        clearInterval(this.timerID);
      }
      
      tick() {
        this.setState({
          data: new Date()
        });
      }

    setInterval(): 每隔指定的时间后,调用一次“函数或表达式”。直到clearInterval()被调用或者浏览器窗口关闭。1000ms =1 second; (详细解说)

    () => {};箭头函数:arrow function

    ES6引用,目的是让代码,更简短并且不创建自己的this。因为传统函数一旦新定义就会有自己的this,如果是一个函数嵌套一个新定义的函数,this就会弄混作用域。而箭头函数不创建自己的this,会使用上下文环境的this值。

    (param..) => {statements} 

    (param..) => expression

    //等同(param..) => {return epression; } 

    //Parenteses are optional when there is only one parameter name:

     singleParam => {statements}

    //支持参数列表解构 

    let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; 

    f();  // 6

    //没有参数则需要用(), ()=> {}

    //Parenthesize the body of function to return an object literal expression:

    params => ({foo: bar}) 

    fun.bind(thisArg,..)方法 :

    fun运行时,把bind里的this的值传给它。fun本身的this的值被替换。

    分析: 

    1.  <Clock />作为参数被传入ReactDOM.render()后,React调用Clock组件的constructor方法。Clock需要显示当前时间,所以它初始化了this.state,一个包含当前时间的JS对象。之后将更新这个对象,this.state。
    2. 然后,React调用Clock组件的render()方法。更新DOM以匹配组件的渲染输出。
    3. 当组件Clock的输出插入到网页对应的DOM后,React 调用 lifecycle钩子方法componentDidMount()。在这个方法内部,组件Clock要浏览器建立a timer来每秒调用一次组件的tick()方法。
    4. 每秒浏览器调用tick方法。在tick内部,Clock组件调用setState()方法,更新this.state对象中的当前时间。
    5. 由setState()方法,React可以知道this.state已经发生变化,需要再次调用render方法。因此浏览器页面上的时间发生变化。
    6. 如果Clock组件要从DOM移走,React调用componentWillUnmount()钩子方法。

    ⚠️ :在第一次调用Clock的人的人方法后,首次加载componentDidmount()方法,从英文名字Did可以看出,组件did后mount。setState和 render一前一后执行。



     Handing Evenets处理事件

    React events 使用驼峰命名

    With JSx you pass a function as the event handler,rather than a string. 


    两种方法绑定上下文this: 

    class Toggle extends React.Component {
      constructor(props) {
        super(props);
        this.state = {isToggleOn: true};
        // this.handleClick = this.handleClick.bind(this);
      }
      
      handleClick= () => {
        this.setState({isToggleOn: !this.state.isToggleOn})
      }
      
      render() {
        return(
          <button onClick={this.handleClick}>
            {this.state.isToggleOn? 'ON1q' : 'Of1f'}!
          </button>
        );
      }
    }
    ReactDOM.render(<Toggle />, document.getElementById('root'));

    传递参数给Event Handlers

    二选一:

    e参数代表了React event,作为第二个参数。 

    <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
    <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>


    条件渲染Conditional Rendering 

     if 和JS相似;

    function UserGreeting(props) {
      return <h1>Welcome back!,{props.name}</h1>;
    }
    function GuestGreeting(props) {
      return <h1>Please sign up.</h1>;
    }
    function Greeting(props) {
      const isLoggedIn = props.isLoggedIn;
      if ( isLoggedIn) {
        return <UserGreeting name="chentianwei"/>;
      } else {
        return <GuestGreeting />;
      }
    }
    ReactDOM.render(
      <Greeting isLoggedIn="true" />,
      document.getElementById('root')
    );

    反复练习:

    全的案例:https://codepen.io/gaearon/pen/QKzAgB?editors=0010 

    代码少但是功能都有: https://codepen.io/gaearon/pen/Xjoqwm?editors=0010

    this.handleLoginClick = this.handleLoginClick.bind(this); 为啥要这么绑定?
    函数声明会自带this,这个this不是上下文的this,要用到上下文环境的this,就需要bind(this);另外可以用箭头函数,因为箭头函数自动绑定上下文this。

    handleLoginClick = () => {}


    List and Keys 

    Basic List Component: 

      const numbers = props.numbers
      //使用map方法遍历数组。
      const listItems = numbers.map((number) =>
        <li>{number}</li>
      );
      return(<ul>{listItems}</ul>);                     
    }                                          
    const numbers =[1,2,9];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );

    这组代码在严格模式下Console会弹出⚠️,

    "Warning: Each child in an array or iterator should have a unique 'key' prop. 

    因为<li> 没有加上key关键字,类似于id。唯一识别码,用于改变和增减。

    改为: <li key={number.toString()}>,⚠️key应该是唯一的,这里是唯一的。

    规则:在map()里的element加上key. 

    规则:最好的key是唯一的识别码 ,在同等级的Siblings中。


    Forms

    HTMl from elements有自然的内部state,它有默认的behavior提交表格时定位到新的页面。React也支持这个行为,但是如果用JS function来处理表格的提交和存取数据会非常convenitent。 这种实现技术称为 controlled components.

    Controlled Components

    在HTML如<input> <textarea> <select>基于用户的输入来保存或更新它们的state。在React, 易变的state保存在组件的state property中,更新则使用setState().

    案例:https://codepen.io/gaearon/pen/VmmPgp?editors=0010

    疑问:

    1.event.target.value是什么意思?

    event是一个虚拟的事件。React定义这些synthetic events用来对应 W3C(event)标准。

    个人理解:DOMEventTarget target 

    这是SyntheticEvent object的attributes >见扩展,每个对象有14个属性(其中4个方法)。 

    扩展:SyntheticEvent: https://reactjs.org/docs/events.html

     我们的事件处理会被传到SyntheticEvent的实例,一个关于浏览器原生事件的跨浏览器包裹器wrapper。和原生浏览器事件的交互是一样的,包括stopPropagation()和preventDefault().

    2.event.prevetnDefault(); 

    答案:这也是SyntheticEvent实例对象的属性,一个方法,React不能使用 return false来防止默认的行为,如防止默认打开一个link到新的网页。因此必须使用preventDefault();

    <a href="#" onclick="console.log('The link was clicked.'); return false">
        Click me
    </a>

    一个控制的组件,每个state都关联一个处理函数,因此可以修改或验证用户输入。例如,让输入的名字强制转化为大写字母。

    handleChange(event) {
      this.setState({value: event.target.value.toUpperCase()});
    }

    Textarea tag 

    In HTML, a <textarea> element defines its text by its children.一般是firstChild。因为在HTML DOM中,text,attribute都是节点。

    而在React中,text则被当做a value attribute处理。在constructor可以初始化这个value。


     

    Select Tag
    IN HTML
    <select>
      <option value="grapefruit">Grapefruit</option>
      <option value="lime">Lime</option>
      <option selected value="coconut">Coconut</option>
      <option value="mango">Mango</option>
    </select>

    而在React中,则constructor初始化这个默认选项。this.state = {value: 'coconut'}; 

    ⚠️ :select接受array传入value属性 <select multiple={true} value={['B', 'C']}>

     一句话,<input type="text">. <textarea> <select>都接受a value attribute.


     练习代码:https://codepen.io/gaearon/pen/JbbEzX?editors=0010

    1. 一类元素对应一个触发的方法。最好不要写一起,不易读。如select,和textarea的onChage={}应该分别写不同的方法。偏要写一起的话,使用name进行区分。
    2. preventDefault();必须得有,否则回到默认页面。
    3. 不要瞎尝试,看现成的案例,或找相关文档。下午耽误了不到一个小时,就是因为在select和textarea元素的属性上不清楚,竟然想自定义属性?!!
    class Reservation extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          isGoing: true,
          numberOfGuests: 2,
          selectValue: "chen",
          textarea: "Hello,"
        };
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
      
      handleInputChange(event) {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;
        this.setState({
          [name]: value    //必须加【】,这是ES6新写法
        });
      }
      
      handleChange(event) {
        const target = event.target;
        this.setState({
          [name]: target.value
        });
      }
      
      handleSubmit(event) {
        alert(this.state.textarea + "" + this.state.numberOfGuests + "" + this.state.selectValue);
        event.preventDefault();
      }
      
      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              Is going:
              <input name="isGoing" type="checkbox"
                checked={this.state.isGoing}
                onChange={this.handleInputChange} />
            </label>
            <br />
            <label>
              Number of guests:
              <input name="numberOfGuests" type='number'
                value={this.state.numberOfGuests}
                onChange={this.handleInputChange}/>
            </label>
            <br />
            <label>
              textarea:
              <textarea name="textarea" value={this.state.textarea} onChange={this.handleChange}/>
              <select name="theName" value={this.state.selectValue} onChange={this.handleChange}>
                <option value="No1">chen</option>
                <option value="No2">tian</option>
                <option value="No3">wei</option>
              </select>
              <input type="submit" value="Submitx" />
            </label> 
          </form>
        )
      }
    }
    ReactDOM.render(
      <Reservation />,
      document.getElementById('root')
    );

    Lifting State up :

    把状态放到作为祖先的组件中,子组件则可以共享这个state了。 这么做的目的:多个组件共用一个相同的变化的数据。即:lifting the shared state up to their closest common ancestor。

    首先, 把TemperatureInput中的state移动到Calculator中。让它成为两个TemperatureInput实例的source of truth 。如此input会同步变化。

    第一,把this.state.temperature 替换为this.props.temperature。props来自Calculator。

             因为props是只读的,同时来自父类,所以TemperatureInput不能直接控制它。

     解决办法是让组件可控,即让TemperatureInput从父组件接收除了温度props外还有温  度的控制方法onTemperatureChange props。

      handleChange(e) {
        // Before: this.setState({temperature: e.target.value});
        this.props.onTemperatureChange(e.target.value);
        // ...

    第二,在render()中,const temperature = this.props.temperature;

    然后,设计Calculator组件。

    state为temperature和 scale单位符号。这就是lifted up的state。它作为source of true 服务于所有子组件。

    本例中,只要存储一个格式的数据即可,另一个格式随时通过换算来显示结果。 

    增加处理Celsius和Fahrenheit的方法,用于设置setState. 

    在render(){}中进行celsius和fahrenheit的数据计算。

    在return()中,调用TempertureInput组件两次,分别传入state,和控制方法。

    总结: recap

    1. React calls the function specified as onChange on the DOM <input>。本例就是在温度输入组件TemperatureInput中的handleChange() 方法.
    2. handleChange方法使用this.props.onTemperatureChange(),props来自父组件Calculator。
    3. 父组件指定了传入的props中的方法是F还是C。传入哪个方法依据我们输入input的位置。
    4. 在这些方法中,父组件因为调用this.setState()更新state,所以会再渲染。
    5. React调用父组件的render方法内部,两种格式的温度会再计算。
    6. 然后渲染方法会return 2个不同scale,temperature及其控制方法的TemperatureInput组件。
    7. React Dom更新DOM来匹配输入的值。我们刚才输入值的input框得到它当前的值,另以一个input框更新转换的温度值。
    top->down data flow
    可以把组件树看成黄河,每个组件的state作为一个支流水源加入。每个子组件都可以使用父组件及祖先们传入的state数据。

    每个组件都是独立的,都可以继承一个父组件的完整state。 

     parseFloat(string)方法,把string-> 浮点数。

     parseInt(string) 转化为整数。 

     Number.isNaN(),当算数运算返回一个为定义的或无法表示的值时,NaN就产生了。

     

    React Developer Tools用于检查数据有chrome, Safari等主流版本。 

    codepen中使用他人的代码,先fork再选择Change View > Debug。就可以使用了。 

     Monitoring State in React DevTools

     const output = convert(input); convert是传进来的函数。

     const rounded = Math.round(output *1000)/1000?

     Math.round(x),返回给定数字的值四舍五入到最接近的整数。乘以1000是为了保留小数。


    Composition vs Inheritance

    React有强大的组成模块,因此建议程序员多用Composition而不是继承。类似Ruby  min-in model 。

    在Facebook中使用了上千的components,没有用到组件继承。 

    Props and composition可以灵活的客制化一个组件的外观和行为。 因为组件可以接收各种各样的props,包括原始的value, React element, function.

    Containment:

    一些组件事先不知道它们的children。因此可以使用特殊的props: {props.children }去传递children elements  然后直接进入它们的输出。

    function FancyBorder(props) {
      return (
        <div className={'FancyBorder FancyBorder-' + props.color}>
          {props.children}
        </div>
      );
    }

    任何在<FancyBorder>JSX tag内的元素, 作为props.children被传递给FancyBorder组件。

    也可以客制化传入,如下例子: 

    function App() {
      return (
        <SplitPane
          left={
            <div className="Contacts" />
          }
          right={
            <Chat />
          } />
      );
    }

    然后在SpliPane组件中插入{props.left}和{props.right}

    全代码:

    https://codepen.io/chentianwei411/pen/QrbXeq?editors=0010 

     

    Specialization

    有时把某个组件当成特殊的某个组件。Ruby, 动物类包含有哺乳类,鸟类。 

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

     类似于继承。组件FancyBorder继承了Dialog中的属性title,message

    composition 也可以在class定义的组件中工作得很好。

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


    在ES6中,${}用来代替引号拼接。类似Ruby中的插入#{}。 

    alert("welcome," + this.state.login ); 

    alert(`welcome, + ${this.state.login}`)  ⚠️ 是`, 单引号和双引号不行。



    实例:用React设计一个小的功能: 


    在React中有两类model data:props and state:

    我的理解:props是组件之间数据,格式,函数等任何数据的传递,state是一个组件的定义的属性。 可以用props传递state。

     

    Step1:Break the UI into Component 层

    首先是分析需求,用画图来帮助思考的行为。给每个组件起名字要适合它们的特点。

    根据单一责任原理,一个组件理论上只做一件事情。随着组件的成长,应该把它拆分为更小的子组件。 

    Component diagram

    FilterableProductTable

    • SearchBar
    • ProductTable

      • ProductCategoryRow
      • ProductRow

    Step2: Build A static version in react

    先把架子搭起来。整体的层次hi.er.archy。

    最简洁的方法:先建立一个包括data model和render UI但没有交互行为的版本。

    因为建立一个静态版本只需大量的type不需要思考,而交互设计则需要大量思考而type较少。

    ⚠️ state是为交互行为服务的,建立静态版本无需使用state.

    为了建立一个静态版本的app,需要渲染数据模块,renders your data model。

    应当建立那种可以反复使用其他的组件和使用props传递data的组件。

    props是把数据从父传给子的一个办法。

    选择建设组件的方式:

    小的app:设计原则是从top->down,  大的复杂的app则相反bottom-up。

    最后,用reusable的组件渲染你的数据model。作为静态版本,组件中只有render()方法。

    FilterableProductTable组件处于the top of the hierarchy, 它用props传递data model。 

    forEach方法

    mySet.forEach(function callback(value1, value2, Set){

      //your iterator

    }[, thisArg])


    callback: Function to execute for each element 

    value1,value2: The value contained in the current position in the Set. 

    当set对象no key时,value2也是值。这样Array也可以使用forEach方法。 

    set: The set object that's being traversed.

    thisArg: Value to use as this when executing callback 

    对集合中的每个原素执行提供的callback函数一次,它不返回任何值。

    用到了关键字key. 

    Step3: Identify the minimal(but complete)Representation of UI State 识别最小的UI state 

    为了正确建立app,首先,思考哪些是最小变化的state。这里也提出dry 原则。

    找出绝对的代表最小state。

    本例:

    • 原始的产品列表
    • 用户输入的搜索文本
    • checkbook的值
    • 产品检索后的列表 

    思考:找出state。问3个问题:

    1. Is it passed in from a parent via props? If so, it isn't state. (存在于层次较高的组件)
    2. Does it remain unchanged over time? If so, it isn't state. (值肯定是会改变)
    3. Can you compute it based on any other state or props in you component? If so, it isn't state.(不会参与其他state/props的计算)
    分析一下,原始产品列表是作为props的,所以不是state。用户输入框和checkbox会变化但不参与计算,所以是state。最后检索后的列表不是state,因为它是被计算得到的数据(通过原始数据和搜索文本和checkbox计算后得到的数据)

    最后,我的的state是:

    The search text that user has entered, the value of the checkbox 

    Step4: Identify where your state should live 

    识别这些state存在于哪个组件。

    记住:React是关于单向数据流动的组件层级关系。对应新手来说,不容易理解组件应该拥有什么state。所以跟随以下思考步骤:

    • 识别每个组件基于state渲染了什么。 
    • 找到一个共同的拥有者组件,在层级上比其他组件更高的组件需要state。
    • 在层级上更高的组件应当拥有state.
    • 如果不能找到一个组件让它适合拥有一个state, 则创建一个新的组件来持有这个state并且这个新组件在层级上应该高于这个普通组件。
    根据这些原则:来分析本案例。
    • ProductTable 拥有检索产品列表(基于state和SearchBar) 
    • The common owner 组件 是 FilterableProductTable
    • 检索文体和checked 值在FilterableProductTable中是可以的
    所以,我们决定了state放在FilterableProductTable 。

    首先:增加一个实例特性instance property this.state={filterText: '', inStockOnly: false}

    其次:传递filterText和inStockOnly给ProductTable 和 SearchBar作为一个prop.

    最后:使用这些props来检索在ProductTable中的Rows

    indexOf(searchElement[, fromIndex]) :

    returns the first index at which a given element can be found in the string/array, or -1 if it is not present.

    indexOf()方法返回调用String/Array对象中第一次出现的指定值的索引,如果没有找到则返回-1.⚠️indexOf是用严格模式,区分大小写字母。如:

    "Blue Whale".indexOf("blue")    //returns -1 

    Array.indexOf():例子

    var beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
    console.log(beasts.indexOf('bison')); 输出1

    console.log(beasts.indexOf('bison', 2));  输出4 ,fromIndex开始搜索的位置,如果这个索引大于等于数组的长度,返回-1

    console.log(beasts.indexOf('giraffe'));  输出-1

    String.indexOf():例子: 

    var str = "To be, or not to be, that is the question.";

    var count = 0;

    var pos = str.indexOf('e');  // 相当于Ruby中的 index方法,Ruby没有找到返回nil。

    while (pos !==-1 ) {

      count++;

      pos = str.indexOf('e', pos + 1); 

    console.log(count); //display 4 


    Step5: Add Inverse Data Flow 

    第4步,当函数的props和state顺着组件的层级hierarchy向下流动时,app正确地渲染。

    现在,到了支持数据逆向流动的步骤。表格组件需要更新FilterableProductTable中的state。

    当用户改变form时,我们根据用户的输入input更新state。组件只能更新自己的state。所以FilterableProductTable会把更新的回调行为传给SearchBar。我们使用onChange事件。这个由FilterableProductTable传递的回调行为叫做setState. 之后app就会更新state了,之后则是因为state的改变,导致state data沿着组件的层级顺流而下,app渲染各个组件。

    看起来复杂,但代码只有几行。并且这种清晰的数据流动遍及整个app。

    ❌:上层组件传递的对state操作的方法的name,不能和传入的组件中声明的方法同名,这样会造成控制组件中的某个输入功能无效。本例子:

    传入的名字:handleInStock,组件中自身也在constructor中命名一个handleInStock自然会无效。

    ⚠️ :return关键字在Ruby和JavaScript中的理解。

    Ruby中return可以用于结束当前循环并返回值 (当然还有别的地方也用return),而在JS中return用于结束函数执行并返回一个指定值,箭头函数也是函数。

    记住:代码是用来读的而不是写的。就是可读行,可理解行强。清楚的模块很容易读和理解。

    当建立大的app的组件时,每个功能都用独立的组件,因为会反复使用组件,所以整体上代码会shrink收缩。

    Component diagram
  • 相关阅读:
    【转】Hibernate入门实例
    【J2EE】Java连接SQL Server 2000问题:“com.microsoft.sqlserver.jdbc.SQLServerException:用户'sa'登录失败。该用户与可信SQL Server连接无关联”
    【转】Java JDBC连接SQL Server2005错误:通过端口 1433 连接到主机 localhost 的 TCP/IP 连接失败
    linux命令行下的ftp 多文件下载和目录下载(转)
    Ubuntu下部署java JDK和eclipse IDE
    构建第一个Spring Boot2.0应用之集成dubbo上---环境搭建(九)
    构建第一个Spring Boot2.0应用之集成mybatis(六)
    构建第一个Spring Boot2.0应用之Controller(三)
    linux修改系统时间为北京时间(CentOS)
    构建第一个Spring Boot2.0应用之application.properties和application.yml(八)
  • 原文地址:https://www.cnblogs.com/chentianwei/p/8870340.html
Copyright © 2011-2022 走看看