Skip to content

React

React1 - ECMAScript 6

Goal

  • Introduction
  • Standalone Starter Set Up
  • Let + Const
  • Destructuring
  • Default + Rest + Spread
  • Arrow Function
  • Class
  • Template String

1 Introduction

  • ECMAScript 6, also known as ECMAScript 2015
  • the latest version of the ECMAScript standard
  • ECMAScript is the scripting language standardized by Ecma International in the ECMA-262 specification and ISO/IEC 16262.
  • Full list of ES6 feature examples http://es6-features.org/
  • What is ECMA

ECMA-> 编程语言界的联合国

业界一定大于6的版本

Javascript 只能浏览器才能运行, 问题: 不好统一

2 Standalone Starter Set Up

  • Babel https://babeljs.io/Screenshot 2023-05-07 at 23.49.19
  • Create a index.html

transpiler: 把一种机器看不懂的东西变成另一种机器看不懂的东西

compiler: 把机器看不懂的东西变成机器看的懂的.

Babel: 你可以写javascript 最新的, 它帮你生成浏览器能支持的

Screenshot 2023-05-07 at 23.50.44

这个是个处理过后的代码, 比如第一行的function(e,t) 变量这个, 它把所有变量都变成单一的字母, 再结合它这个文件min, 所以它就是把不需要的空间都腾出来,急剧的压缩它. 这个文件的size越小越好, 因为用户的浏览器得去下载它.

https://codesandbox.io/s/4jk5r8mkvw

3 Let + Const

  • let + const have block scope
let b = 1;
let b = 2; // wrong
console.log(b);

//===========
function test() {
  var a = 1;
  var a = 2;

  let b = 10;
  b = 20; // 2, 20
  let b = 20; // Wrong

  console.log(a, b);
}
test();

// ===== block scope ===
for (var j = 0; j < 2; j++){
  console.log(j);
}

console.log(j);

for (let i = 0; i < 2; i++) {
  console.log(i);
}

console.log(i); // wrong

// must assign a value
const d; // wrong

// cannot be reassigned
const t = 123;
t = 456; // wrong

// block scope
{
  const a = 123;
  console.log(a);
}
console.log(a); // wrong

Screenshot 2023-05-08 at 02.23.52

var 是function scope

var 定义的只有local 和global, 而且它会重定义.

如果判断? 看这个var是否在函数里, 是的话就是local, 不是的话就是global.

var a = 2;
var a = 1; // a 会被重定义redeclare 就是关键字是否可以重复写
for (var i = 0; i < 5; i++){ // 这个i不在fucntion里, 所以它是global
}

console.log(i); // 它还活 

用let 来定义变量的话, 更像是java里面的行为.

let c = 5;     // 存的是动态
c = 6;       // 关键字let就不用重复写 reassign
{
  let a = 2;      // 这个是合法语法, 但是很少人这么写
}

console.log(a);    // 它的生命周期止于花括号里 

function func(){
  for (var i = 0; i < 5; i++){     // 这样写才叫在函数里

  }
}

const: 常量. 不能重赋值

let 可以重赋值

4 Destructuring

  • destructuring assignment is a special syntax

  • more convenient

  • allows us to “unpack” arrays or objects into a bunch of variables
  • allows us to “unpack” complex functions that have a lot of parameters, default values
// Array
let [a, b, c] = [1, 2, 3];
console.log(a, b, c);

let arr = [4, 5, 6];
let [d, e, f] = arr;
console.log(arr);
// let arr = [4, 5, 6];
// let d = arr[0];
// let e = arr[1];
// let f = arr[2];

// Object
let { name, age } = { name: "Joe", age: 10 };
console.log(name, age);

// let Object  = { name: "Joe", age: 10 };
// let name = object.name;
// let age = object.age;

let{name2: alias, age2 = 1} = {name2:"Joe"};
console.log(alias);
console.log(alias, age2);

// Function
function fn([a, b]) {
  console.log(a + b);
}

fn([1, 2]);

function fn2({name3}){
  console.log(name3);
}
fn2({name3: "Joe"});

fn2(1);
// let name3.name 

Screenshot 2023-05-08 at 09.57.22

上述方法使用非常频繁.

5 Default + Rest + Spread

  • Default

    • absent values are considered undefined
  • if we want a “default” value to replace the missing one, we can provide it using =

  • Rest

    • to gather all that follows using three dots "..."
  • Spread

    • to spread all items in an array or an object using three dots "..."
// default
function add1(x = 1, y = 2) {
  console.log(x + y);
}

// 只有当x是undefined时候才能生效
// null 不会生效, null是个合法的值
// let a = null; null 需要赋值

add1(); // ? 1+2 =3
add1(5, 6); //?  5+6 = 11

// rest
// function fn(args) 表示期待1个参数
function fn(...args) {
  // 三个点表示期待>=0个 unlimited
  // 它所有传进来的参数变成了数组
  let sum = 0;
  for (let i = 0; i < args.length; i++) {
    sum += args[i];
  }
  console.log(sum);
}

fn(1, 2, 3, 4);

// spread
let arr = [1, 2, 3];
let arr1 = [...arr, 4, 5]; // 把arr一个个拿出来,插入arr1
let arr2 = [3, 4, 5, ...arr, 4, 5]; // 有顺序

console.log(arr1);
console.log(arr2);

let obj1 = { a: 1, b: 2 };
let obj2 = { ...obj1, c: 3 };
console.log(obj2);
let obj3 = { c: 3, ...obj1 };

console.log(obj3);

let obj4 = { a2: 1, b2: 2 };
console.log(obj4);
let obj5 = { a2: 3, ...obj4 };
console.log(obj5);
// {
//   a: 3; // ->1
//   b: 2;
// }
// 现在顺序有关系了
let obj6 = { a3: 1, b3: 2 };
console.log(obj6);
let obj7 = { ...obj6, a3: 3 };
console.log(obj7);
// 运行结果不一样了
// ...obj6 实际上是把里面一个个拆开一个个的拷贝
// 如果a又是一个object  会把{name:'x'} 作为一个浅拷贝
let obj8 = { a4: { name: "x" }, b4: 2 };
console.log(obj8);
let obj9 = { a4: 3, ...obj8 }; // a4 浅拷贝
console.log(obj9);

// deepclone -> dfs,bfs

Screenshot 2023-05-08 at 10.30.53

6 Arrow Function

  • The syntax

    • (arg1, arg2, ...argN) => expression
    • This creates a function that accepts arguments arg1..argN, then evaluates the expression on the right side with their use and returns its result.
  • the shorter version of

    function(arg1, arg2, ...argN) {
    
            return expression;
    
    };
    

The example:

  • special cases:
// Arrow Function
let f1 = (a, b) => {   // function 变成了箭头
  a++;
  return a + b;
};

console.log(f1(1, 2));

// Normal Function
let f2 = function (a, b) {
  a++;
  return a + b;
};

console.log(f2(20, 10));


// special cases
// case1:
// without curly braces
// when the function
// evaluates it and return result

let f3 = (a, b) => a + b;

// case2:
// only one argument
// then parentheses around
// parameters can be omitted

let f4 = a => {
  a++;
  console.log(a);
};

// case1 + case2
let f5 = a => a; // return 就一行的时候

Screenshot 2023-05-08 at 14.12.49

  • The usage
let arr = [3, 5, 1, 2, 8];

let arr2 = arr.map((a) => a * 2); // (a) => a * 2 传进来的参数乘2
// map把回调函数作用在arr中的每一个上面 生成一个新的数组 返回给arr2
// .map 是个colletion
// collection.map(method);
// map will apply "method" on each element in collection
console.log(arr);
console.log(arr2);

let arr3 = [3, 5, 1, 2, 8];
let arr4 = arr3.map(function (a) {
  return a * 2;
});

console.log(arr3);
console.log(arr4);

Screenshot 2023-05-08 at 14.18.48

  • this keyword

Remember: For arrow functions, the value of this is determined based on where the arrow function is declared, not where or how it is invoked.

会有点儿tricky.

function fn() {
  console.log("fn", this); // this 指向 item1

  const run = () => {
    console.log(this); // 贴的最近的函数 run
    console.log(this.a);
  };

  run(); // 执行
}

let item1 = {
  a: 1,
  fn: fn // fn赋值到object上 fn是个函数不是primitive 所以可以展开
};

let item2 = {
  a: 100,
  fn: fn
};

item1.fn();
item2.fn();

// 先找爹, 看这个函数怎么被调用

Screenshot 2023-05-08 at 15.12.28

function fn(){
  console.log('fn', this);

  function run(){
    console.log(this);
  }
  run();
}

let item1 = {
  a : 1,
  fn : fn
}

let item2 = {
  a : 100,
  fn : fn
}

item1.fn(); //
item2.fn();

Screenshot 2023-05-08 at 15.15.04

7 Class

  • The basic syntax

javascript从设计之初, 它就不是一个class basic语言. 它虽然可以让你这么写但是它是个语法糖 syntax sugar

class 的优点 scope, 模块化更好点.

// The basic syntax
class Person {
  constructor(name, age, hobby) {
    this.name; // 和java的this一样 但很少用到class
    this.age; // js 中.
    this.hobby;
  }

  sayHello() {
    console.log(`My name is ${this.name}, 
    I am ${this.age} years old, I like 
    ${this.hobby}`);
  }

  walk() {
    console.log(`${this.name} is walking`);
  }
}

let joe = new Person("Joe", 20, "swimming"); // object
joe.sayHello();
joe.walk();

// Class inheritance
class Student extends Person {
  // 继承 java 要@override   js就是简版.
  constructor(name, age, hobby, school) {
    super(name, age, hobby); // super调用parent的constructor
    this.school;
  }

  goToSchool() {
    console.log(`this is ${this.name}, I go to ${this.school}`);
  }
}

var curry = new Student("Curry", 9, "basketball", "elementary school");
curry.sayHello();
curry.goToSchool();

Screenshot 2023-05-08 at 14.06.24

8 Template String

  • It’s used for constructing strings
  • Strings are enclosed within backticks
  • Backticks allow us to embed any expression into the string, by wrapping it in ${…}

组装语法

function ex1() {
  const firstName = "John";
  const lastName = "Doe";
  const fullName = `${firstName} ${lastName}`;
  // Template String, 把变量和符号揉合在一起
  // 方便组装string
  // 空格就是空格
  console.log(fullName); // John Doe
}

ex1();

Screenshot 2023-05-08 at 10.41.48

React 2 (JSX & Props)

Goal

  • Introduction
  • Installation
  • Virtual DOM
  • JSX
  • Component

1 Introduction

What Is React?

  • a JavaScript library for building user interfaces
  • maintained by Facebook, Instagram and a community of individual developers and corporations
  • declarative
  • component-based
  • learn once, write anywhere

2 Installation

  • React - the React top level API
  • React DOM - adds DOM-specific methods

  • Babel - a JavaScript compiler that lets us use ES6+ in old browsers

  • online playground: https://codepen.io/pen?&editors=0010&layout=left
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello React!</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

</head>
<body>
  <div id = "root" > </div>
  <script type = "text/babel">
    // React code will go here
  </script>
</body>
</html>

https://legacy.reactjs.org/docs/add-react-to-a-website.html

like_button.js

'use strict';// 更严格的写js

const e = React.createElement;     // variable 用react的方法create了一个element

class LikeButton extends React.Component {    // inherit
    constructor(props) {
        super(props);     // 要去call parent constructor
        this.state = { liked: false };   // 初始state 里面是个map 而不是object this.state 不可以变, 里面的可以变
    }

    render() {     //   必须定义的一个function  告诉浏览器button要怎么显示 每一个compoent里面都有
        if (this.state.liked) {
            return 'You liked this.';
        }

        return e(           // React。createElement
            'button', // 相当于 <button> .....
            { onClick: () => this.setState({ liked: true }) },  // props 我会给他哪儿些属性 update State的值
            'Like' // button里面要显示什么
        );

        // <button  id = "button", onClick=...> Like </button>
    }
}

// ... the starter code you pasted ...

const domContainer = document.querySelector('#like_button_container');  // 需要query element  #id  class .
const root = ReactDOM.createRoot(domContainer);// 我们要从容器里面create 一个tree 结构 从上往下有个根节点
root.render(e(LikeButton)); // render

// const buttomDiv = document.querySelector('#like_button_container');
// buttomDiv.onclick = function (){
//     if (liked){
//         buttomDiv.innerHTML = "you liked this"
//     }else {
//         buttomDiv.innerHTML = "<button>"
//     }
// }
// react 可以让你focus on 重要的逻辑render 而不是底层的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello React!</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>


  <!-- Load React. -->
  <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

</head>
<body>
  <div id = "root" > </div>
  <div id = "like_button_container"></div> <!--react 的一个容器 入口-->
  <script type = "text/babel">
    // React code will go here
  </script>

  <!-- Load our React component. -->
  <script src="like_button.js"></script>
</body>
</html>

Screenshot 2023-05-08 at 17.57.03

Screenshot 2023-05-08 at 17.57.11

3 Virtual DOM + The Diff Algorithm

Image 5-8-23 at 18.00

Screenshot 2023-05-08 at 18.01.55

3.1 What is virtual dom

  • The virtual DOM (VDOM) is a programming concept
  • The representation of a UI kept in memory and synced with the “real” DOM by ReactDOM

getelementbyid, innerhtml ... 我们统一叫这些 DOM operation. 它挺慢的, 不停的计算机, 需要找. 所以update需要把整个dom tree 又update一遍. 这个过程也是很慢的过程, 而且还要计算layout. 这个计算非常昂贵. 而且用户的浏览器可能没有那么高级的话就很慢. 所以需要virtual DOM.

3.2 What is the diff algorithm

  • The diff algorithm is implemented by React to compare two different trees

Screenshot 2023-05-08 at 15.40.03

4 React Elements

4.1 createElement()

// create virtual dom element
const ele1 = React.createElement('h1', {className: 'box'}, 'hello react!');

// render DOM
ReactDOM.render(
   ele1,
   document.getElementById('root')
);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello React!</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>


  <!-- Load React. -->
  <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

</head>
<body>
  <div id = "root" > </div>
  <div id = "like_button_container"></div> <!--react 的一个容器 入口-->
  <script type = "text/babel">
    // React code will go here
  </script>

  <!-- Load our React component. -->
  <script src="like_button.js"></script>
  <script>
    // create virtual dom element
    const ele1 = React.createElement('h1', {className:'box'}, 'hello react!');

    // render DOM
    ReactDOM.render(
            ele1,
            document.getElementById('root')  // root container
    );
  </script>
</body>
</html>

Screenshot 2023-05-08 at 20.11.08

4.2 JSX

  • Used to create react element

  • JSX Represents Objects

  • Babel compiles JSX down to React.createElement() calls.

  • Embedding Expressions in JSX

    • Using {}
  • valid JavaScript expression

  • the result of calling a JavaScript function

  • Specifying Attributes with JSX

// JS expression
const a = 10;
const str = 'this is a str';
const arr = [ <p key='1'>first</p>, <p key='2'>second</p>, <p key='3'>third</p> ];

//map
const arr1 = ['apple', 'pear', 'berry'];
const res = arr1.map((item, index) => {
           return <p key={index}>* {item} *</p>
       });

// JS function
function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez',
};

const element = <h1>Hello, {formatName(user)}!</h1>;

ReactDOM.render(element, document.getElementById('root'));

5 React Component

5.1 Two ways to define react component

  • Use JavaScript function
  • Use ES6 Class
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>


  <!-- Load React. -->
  <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

</head>
<body>
<div id = 'root'></div>
<div id = 'root2'></div>
<script type = "text/babel">       // you have to add type="text/babel"> or will wrong
  // use JavaScript function
  function Hello(props){
    console.log(props);
    return <p> hello react {props.person.name} </p>
  }

  const person = {
    name : 'Joe',
    age : 10
  }

  ReactDOM.render(
          <Hello person={person}/>,
          document.getElementById('root')
  );

  // use ES6 clas
  class Hello2 extends React.Component{
    constructor() {
      super();
    }

    render(){
      return <h1>hello react, {this.props.name}</h1>
    }
  }

  ReactDOM.render(
    <Hello2 name = {'Lucy'} />,
          document.getElementById('root2')
  );
</script>
</body>
</html>

Screenshot 2023-05-08 at 21.51.55

5.2 props

  • Props are Read-Only 它是不会变化的, state 的话是可以改变
  • All React components must act like pure functions with respect to their props.

In class note: https://jsbin.com/suzavuxaqu/edit?html,output

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>
<body>
<h1>React JSX + Component</h1>

<div id="app"></div>

<script type="text/babel">

</script>

<script type="text/babel">
    // 1. how to install React Library
    //  - react -> core
    //  - reactdom -> virtual dom <-> dom
    //  - babel -> compile jsx
    // 2. how to create an element in React
    //  - createElement x
    //      - use jsx => html + js
    // 3. react components
    //  - class based
    //  - function based

    // const ele = React.createElement('h3', { className: 'box'}, 'hello react!');
    // const oP = React.createElement('p', null, 'hello react!');
    // const ele = React.createElement('h3', { className: 'box'}, [oP]);
    // const ele = <h3 className='box'>
    //     <p>Hello React!!!</p>
    // </h3>;
    // const a = 10;
    // const b = "hello";
    // const bool = false; // X
    // const arr = [1, 2, 3];
    // const arr1 = [<li key="1">pear</li>, <li key="2">apple</li>, <li key="3">cherry</li>];
    // const obj = { name: "Joe", age: 10 }; // X
    // const add = (a, b) => a + b;
    // // const ele = <div> { 1 < 2 ? 'dog' : 'cat' } </div>;
    // const arr2 = ['apple', 'pear', 'berry'];
    //
    // const ele = <div>{
    //     arr2.map( item => {
    //         return <p key={item}> { item } </p>;
    //     })
    // } </div>;

    // function Hello(props) {
    //     console.log(props);
    //     return <p>hello {props.personData.name}!</p>
    // }

    class App extends React.Component{
        constructor(props) {
            super(props);
            console.log(props)
        }

        render() {
            console.log(this.props);
            return <div>
                <p>This is APP component</p>
                <p>Hello App! Hello {this.props.personData.name}</p>
            </div>
        }
    }

    const person = { name: "Joe", age: 10 };


    ReactDOM.render(
        // react element,
        <App personData={ person } num={10} />,
        // wherr to mount
        document.getElementById("app")
    )

React 3 (State & Event)

Goal

  • What is state
  • How to use setState
  • Handling events
  • Data communication
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>


  <!-- Load React. -->
  <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

</head>
<body>
  <div id = root> </div>
  <script type = "text/babel">
    const App = () =>{       // 如何看是否为component
      return <div>Hello</div>
    }

    const root = ReactDOM.createRoot(
            document.getElementById('root')
    );

    root.render(<App />);         // ReactDom.createElement(App, ...) 导致App 变成component
                // 这个只帮浏览器运行App一次, 但是交互的时候元素的个数会发生改变
  </script>            

</body>
</html>

Screenshot 2023-05-09 at 01.06.52

render: data -> vision 画蓝图

1 State

What is state? How to use state?

class App extends React.Component{
   constructor() {
       super();
       // 1. add state
       this.state = {
           a : 20,
       };

       this.change = this.change.bind(this);
   }

   render() {
       return (
           // 2. use state
           <div>
             <button onClick={ this.handleClick }>
               click me</button>
             <button onClick={ this.change }>click me</button>
             {this.state.a}
           </div>
       )
   }

   handleClick = () => {
     const newState = {
       a : this.state.a + 10
     }
     this.setState(newState);
   }

   change() {
       this.setState({a : 999})
   }
}

ReactDOM.render(
   <App/>,
   document.getElementById('root')
);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>


  <!-- Load React. -->
  <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

</head>
<body>
  <div id = root> </div>
  <script type = "text/babel">
      class App extends React.Component{
          constructor() {
              super();
              // 1. add state
              this.state = {     // object  开关
                  a : 20,
              };

              this.change = this.change.bind(this);
          }

          render(){
              return (
                  // 2. use state
                  <div>
                      <button onClick = {this.handleClick}>
                          click me + 10
                      </button>
                      <button onClick = {this.change}>click me -> 999</button>
                      {this.state.a}
                  </div>
              )
          }
          // this.handleClick这是个函数, 如果没有{} 就会当作string 显示, 被编译了

          handleClick = () => {   // 要使用箭头函数
              const newState = {
                  a : this.state.a + 10
              }
              // no no no, state.propperty = newvalue no no no no
              // const newState = {b: 30};
              // {
              //    ...oldstate,
              //    ...newstate
              // }
              // 类似 merge
              // {
              //    b:30,
              //    a:20
              // }
              this.setState(newState);  //拨动开关
          }

          change(){
              this.setState({a : 999})
          }
      }

      ReactDOM.render(
          <App/>,
          document.getElementById('root')
      );

      //运行顺序[i]来表示
      //最初第一遍是按照顺序从上执行
      //会先定义一个class叫App 然后render(), ReactDOM.render, 会被甩到页面上
      //形成按钮显示
      //然后用户点击按钮的时候 由于render()中会导致handleClick函数执行. 每次点击按钮他都执行
      //handleClick 原地组装成新的state 与原先的进行融合。 然后再次根据react 又运行render()产生dom结构
      //然后react会根据新老结构进行将页面更新
  </script>

</body>
</html>

Screenshot 2023-05-09 at 03.16.14

2 What does setState do ?

  • setState() schedules an update to a component’s state object.
  • When state changes, the component responds by re-rendering.

3 Handling Events

3.1 The syntax

Handling events with React elements is very similar to handling events on DOM elements. There are some syntactic differences:

  • React events are named using camelCase, rather than lowercase.
  • With JSX you pass a function as the event handler, rather than a string.
// HTML
<button onclick="clickFn()">
  Click me
</button>
// React
<button onClick={clickFn}>
  Click me
</button>

How to write event handling function in React:

// method1
<button onClick={this.handleClick.bind(this)}>click me</button>

//method2 比较常用
<button onClick={ () => {this.handClick() }}>click me</button>

Note:

  • You have to be careful about the meaning of this in JSX callbacks.
  • If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
  • This is not React-specific behavior;
  • It is a part of how functions work in JavaScript.
  • if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.
  • If calling bind annoys you, you can use arrow-function in the callback.

4 Data Communication Between Components

4.1 Data Flows Down

A component may choose to pass its state down as props to its child components:

This is commonly called a “top-down” or “unidirectional” data flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components “below” them in the tree.

If you imagine a component tree as a waterfall of props, each component’s state is like an additional water source that joins it at an arbitrary point but also flows down.

Screenshot 2023-05-08 at 21.57.58

Screenshot 2023-05-08 at 21.57.43

Lift State Up

Once the state is changed by setState, component and it’s children’s virtual DOM will be re-rendered.

Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their lowest common ancestor.

4.2 Callback Climbs Up

When we want to pass the data generated from child component to parent component for a state change. We can pass binded function down as props. This means that child components can trigger state changes in their parent components.

Screenshot 2023-05-08 at 22.01.41

Screenshot 2023-05-08 at 22.02.00

Screenshot 2023-05-08 at 22.02.19

Screenshot 2023-05-08 at 22.02.52

In-class note: https://jsbin.com/dunekodoma/edit?html,output

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
    <style>
        .box {
            width: 100px;
            height: 100px;
            background-color: #ccc;
        }
    </style>
<body>
<h1>State + Event + Data Communication</h1>
<!--<h2>hello react</h2>-->
<!--<button class="btn">click me</button>-->
<!--<div class="box"></div>-->
<hr />
<div id="app"></div>

<script type="text/javascript">
    // let oBox = document.getElementsByClassName('box')[0],
    //     oBtn = document.getElementsByClassName('btn')[0];
    //
    // let val = 100;
    // oBtn.onclick = function() {
    //     // change val
    //     val += 20;
    //     // view <-> data(val)
    //     oBox.style.height = val + 'px';
    //     oBox.style.width = val + 'px';
    // }
    // get button
    // const oBtn = document.getElementsByClassName('btn')[0];
    // let oH2 = document.getElementsByTagName('h2')[0];
    // oBtn.onclick = function () {
    //     oH2.style.backgroundColor = "red";
    // }
    //oBtn.addEventListener('click', function(){})
</script>

<script type="text/babel">
    // 1. what is state?
    //  - props vs component ?
    // 2. how to use?
    //  - define
    //      - this.state = {}
    //  - write
    //      - setState()
    //          - {}
    //          - () => {}
    // 3. react event
    //  - jsx <button onClick={ this.doSthFn }></button>

    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                a: 1,
                b: 1,
                // data
                w: 100,
                h: 100,
                outerData: props.num
            }
            // this.change = this.change.bind(this);
        }

        // state = {
        //     a: 1,
        //     b: 10
        // }

        change = () => {
            console.log(1);
            console.log(this);
            this.setState({
                outerData: "haha"
            })
            // this.setState({ a: this.state.a + 10 });
            // this.setState({ b: `current a is: ${this.state.a}`})
            this.setState(preState => {
                console.log('1 -> ',preState);
                return {
                    a: preState.a + 10,
                }
            })

            this.setState(preState => {
                console.log('2 -> ',preState);
                return {
                    b: `current a is: ${preState.a}`
                }
            })
        }

        render() {
            console.log(this.state);
            const { w, h, b, outerData } = this.state;
            return (
                <div>
                    <p>the data is : { outerData }</p>
                    <p>the internal data: { this.state.a }</p>
                    <p>the internal b: { b }</p>
                    <div
                        style={{
                            width: w,
                            height: h,
                            backgroundColor: "#ccc"
                        }}></div>
                    <button onClick={
                        () => {
                            // this.state.a += 10;
                            // this.setState({
                            //     a: "haha"
                            // })
                            this.setState(preState => {
                                console.log(`preState: ${preState}`);
                                // return new state
                                return {
                                    w: preState.w + 10,
                                    h: preState.h + 10
                                }
                            })
                        }
                    }>click me + 10 </button>

                    <br />
                    <button onClick={ this.change }>click me</button>
                    {
                        // <button onClick={
                        //     () => {
                        //         console.log('clicked')
                        //         this.props.num = 100;
                        //     }
                        // }>click me -> 100</button>
                    }
                </div>

            )
        }
    }


    ReactDOM.render(
        <App num={10}/>,
        document.getElementById('app')
    )
</script>
</body>
</html>

In class note:

https://jsbin.com/kujarepeke/edit?html,output

https://jsbin.com/xemiyopada/edit?html,output

早起的state被class定义

React 4

Goal

  • Overview
  • Component Life Cycle
  • Mounting
  • Update
  • Unmounting

Screenshot 2023-05-11 at 00.21.33

1 Overview

  • React provides a series of hooks we can tap into at each phase of the life cycle.
  • These method hooks inform us of where the Component is in the life cycle.

2 Component Life Cycle(React 16.x)

http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

  • Each of the life cycle methods are called in a specific order and at a specific time.
  • The methods are also tied to different parts of the life cycle.

2.1 Mounting

  1. constructor() set intial state
  2. render()
  3. componentDidMount()

2.2. Update

  1. componentDidUpdate()

2.3. Unmount

  1. componentWillUnmount()
  2. Instance destroyed for Garbage Collection

The order of these methods are strict and called as defined above. Most of the time is spent in the Update phase and those methods are called many times. The Mount and Unmount methods will only be called once.

React Official Doc For Life Cycle Methods

https://reactjs.org/docs/react-component.html

Use react v16

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
   <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
</head>
<body>
   <div id="root"></div>

   <script type="text/babel">
   </script>
</body>
</html>

3 Mounting In Action

3.1 Default Props & Initial State

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
   <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
</head>
<body>
   <div id="root"></div>
   <script type="text/babel">
       class App extends React.Component {
           constructor(props) {
               super(props);
               console.log("parent's props - ", props)
           }
           render() {
               return <div>
                   <p>this is Parent Component</p>
                   <hr />
                   <Child num={100} />
               </div>
           }
       }

       class Child extends React.Component {
           constructor(props) {
               super(props);
               this.state = {
                   data : 888
               }
               console.log("child's props - ", props);
           }
           render() {
               return <div>
                   <p>this is Child Component</p>
                   <p>number from Parent { this.props.num }</p>
                   <p>data is from child itself { this.state.data }</p>
               </div>
           }
       }

       ReactDOM.render(
           <App />,
           document.getElementById('root')
       );
   </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

</head>
<body>
<h1>React Life Cycle</h1>
<div id="root"></div>
<!--<script>-->
<!--    // component life cycle 组件的生命周期 vs component life cycle function 组件生命周期函数-->
<!--    // life cycle <&#45;&#45; life cycle function   生命周期由生命周期函数组成的-->
<!--    // life cycle function -> class components 生命周期函数只存在于类组件中-->

<!--    // component 有三个阶段 -> mounting + updating + unmounting-->
<!--    // 它们组成了组件的life cycle-->
<!--    // 在component 中它是通过生命周期函数来体现这个三个阶段的 life cycle function-->
<!--    // life cycle => life cycle functions-->
<!--    // - mounting -> mounting life cycle function-->
<!--    // - updating -> updating life cycle function-->
<!--    // - unmounting -> unmounting life cycle function-->
<!--    //-->
<!--    // fn + class has life cycle-->
<!--    // fn does not have life cycle but class has life cycle-->
<!--    // react 提供了api 去访问组件的周期状态-->
<!--    // Example: Parent组件, 下面有个child组件,要对Child组件实现-->
<!--    // Mounting 和 unmounting, updating-->
<!--    //   p - c-->

<!--</script>-->
<script type="text/babel">
    class App extends React.Component{
        constructor(props) {
            super(props);
            console.log("parent's props -", props)
        }

        render(){
            return(
                <div>
                    <h2>This is Parent Component</h2>
                    <hr />
                    <Child num={100} />
                </div>
            )
        }
    }

    class Child extends React.Component{
        constructor(props) {
            super(props);
            this.state = {
                data : 888
            }
            console.log("child's props -", props);
        }
        render(){
            return(
                <div>
                    <h2>This is Child Component</h2>
                    <p> number from Parent { this.props.num } </p>
                    <p> data is from child itself { this.state.data }</p>
                </div>
            )

        }
    }

    ReactDOM.render(
        <App />,
        document.getElementById('root')
    );
</script>
</body>
</html>

Screenshot 2023-05-11 at 02.32.31

Child 和 Parent都同时在这个页面上, 想控制这个child, 要实现它的上树和下树. 想设置一个按钮, 点击它就上树, 再点击它就下树. 说明Child是个有条件的显示. 即, 我的状态的变化会导致child的变化.所以需要定义状态.

3.2 Mounting Methods

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

</head>
<body>
<h1>React Life Cycle</h1>
<div id="root"></div>
<script type="text/babel">
  class App extends React.Component{
    constructor(props) {
      super(props);
      this.state = {
        isShow : false,
        a : 100
      }
      console.log("parent's props -", props)
    }

    render(){
      return(
              <div>
                <h2>This is Parent Component</h2>
                <div>
                  <button onClick ={ () => {
                    this.setState({isShow : !this.state.isShow})
                  }}
                  >Click me to show/hid child </button>
                </div>

                <div>
                  <button onClick={() =>{
                    this.setState({
                      a : this.state.a + 10
                    })
                  }}>Click to add 10</button>
                </div>
                <hr />
                {
                  this.state.isShow ? <Child num={this.state.a}/> : null 
                }
              </div>
      )
    }
  }

  class Child extends React.Component{
    constructor(props) {
      super(props);
      this.state = {
        data : 888
      }
      console.log("1. constructor");
      // 这个是Mounting里的constructor部分, 这个部分可以用来定义state, bind this指针
      // e.g this.fn = this.fn.bind(this)
      // read props
      // 在这儿拿不到 dom

    }
    render(){
      console.log("3. render ");
      return(
              <div>
                <h2>This is Child Component</h2>
                <p> number from Parent { this.props.num } </p>
                <p> data is from child itself { this.state.data }</p>

                <div>
                  <button onClick ={() => {
                    this.setState({
                      data: this.state.data + 10
                    })
                  }}>click add 10 on child</button>
                </div>
              </div>
      )

    }

    componentDidMount(){
      console.log("4. componentDidMount")
      // 对dom的读写 可以访问到
      // fetch data from servers
    }
  }



  ReactDOM.render(
          <App />,
          document.getElementById('root')

  );
</script>
</body>
</html>

Screenshot 2023-05-11 at 03.02.04

上树Screenshot 2023-05-11 at 03.03.55

代码的顺序和我执行的顺序是没有关系的, constructor 先 后render

Screenshot 2023-05-11 at 03.12.48

4 Updating In Action

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

</head>
<body>
<h1>React Life Cycle</h1>
<div id="root"></div>
<script type="text/babel">
  class App extends React.Component{
    constructor() {
      super();
      this.state = {
        isShow : false,
        a : 100
      }
    }

    render(){
      return(
              <div>
                <h2>This is Parent Component</h2>
                <div>
                  <button onClick ={ () => {
                    this.setState({isShow : !this.state.isShow})
                  }}
                  >Click me to show/hid child </button>
                </div>

                <div>
                  <button onClick={() =>{
                    this.setState({
                      a : this.state.a + 10
                    })
                  }}>Click to add 10</button>
                </div>
                <hr />
                {
                  this.state.isShow ? <Child num={this.state.a}/> : null
                }
              </div>
      )
    }
  }

  class Child extends React.Component{
    constructor() {
      super();
      this.state = {
        data : 888
      }
      console.log("1. constructor");
      // 这个是Mounting里的constructor部分, 这个部分可以用来定义state, bind this指针
      // e.g this.fn = this.fn.bind(this)
      // read props
      // 在这儿拿不到 dom

    }

    componentDidUpdate(prevProps, prevState, snapshot){
      console.log("---updating---5.componentDidUpdate");
      console.log("---updating---5.prevProps", prevProps);
      console.log("---updating---5.prevState", prevState);
      console.log("---updating---5.snapshot",snapshot);
    }
    render(){
      console.log("---mounting/updating 3. render ");
      return(
              <div>
                <h2>This is Child Component</h2>
                <p> number from Parent { this.props.num } </p>
                <p> data is from child itself { this.state.data }</p>

                <div>
                  <button onClick ={() => {
                    this.setState({         //setState 会导致render的重新调用
                      data: this.state.data + 10
                    })
                  }}>click add 10 on child</button>
                </div>
              </div>
      )

    }

    componentDidMount(){
      console.log("4. componentDidMount")
      // 对dom的读写 可以访问到
      // fetch data from servers
    }
  }



  ReactDOM.render(
          <App />,
          document.getElementById('root')

  );
</script>
</body>
</html>

Screenshot 2023-05-11 at 15.19.52

5 Unmounting

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

</head>
<body>
<h1>React Life Cycle</h1>
<div id="root"></div>
<script type="text/babel">
  class App extends React.Component{
    constructor() {
      super();
      this.state = {
        isShow : false,
        a : 100
      }
    }

    render(){
      return(
              <div>
                <h2>This is Parent Component</h2>
                <div>
                  <button onClick ={ () => {
                    this.setState({isShow : !this.state.isShow})
                  }}
                  >Click me to show/hid child </button>
                </div>

                <div>
                  <button onClick={() =>{
                    this.setState({
                      a : this.state.a + 10
                    })
                  }}>Click to add 10</button>
                </div>
                <hr />
                {
                  this.state.isShow ? <Child num={this.state.a}/> : null
                }
              </div>
      )
    }
  }

  class Child extends React.Component{
    constructor() {
      super();
      this.state = {
        data : 888
      }
      console.log("1. constructor");
      // 这个是Mounting里的constructor部分, 这个部分可以用来定义state, bind this指针
      // e.g this.fn = this.fn.bind(this)
      // read props
      // 在这儿拿不到 dom

    }

    componentDidUpdate(prevProps, prevState, snapshot){
      console.log("---updating---5.componentDidUpdate");
      console.log("---updating---5.prevProps", prevProps);
      console.log("---updating---5.prevState", prevState);
      console.log("---updating---5.snapshot",snapshot);
    }
    render(){
      console.log("---mounting/updating 3. render ");
      return(
              <div>
                <h2>This is Child Component</h2>
                <p> number from Parent { this.props.num } </p>
                <p> data is from child itself { this.state.data }</p>

                <div>
                  <button onClick ={() => {
                    this.setState({         //setState 会导致render的重新调用
                      data: this.state.data + 10
                    })
                  }}>click add 10 on child</button>
                </div>
              </div>
      )

    }

    componentDidMount(){
      console.log("4. componentDidMount")
      // 对dom的读写 可以访问到
      // fetch data from servers
    }

    componentWillUnmount(){
      console.log("--- unmount ---")
    }
  }



  ReactDOM.render(
          <App />,
          document.getElementById('root')

  );
</script>
</body>
</html>

Screenshot 2023-05-11 at 15.22.49

React 5 - Hooks

const FComponent = () => {

}

class CComponent extends React.Component {
  state = {       // function 里就不容易定义这个

  }

  componentDidMount(){

  }

  componentDidUpdate(){

  }
}

实际开发过程中用的是function, 因为某些原因基本上就放弃了class的方式.

1 React Hooks

1.1 useState Hook

使用 useState hook

import React, { useState } from 'react';

function StateHook(props) {
    const [count, setCount] = useState(0);
    const [hidden, setHidden] = useState(false);
    const [steps, setSteps] = useState(0);

    return (
        <div>
            <h1>Clicked { count } times!!</h1>  
            <button onClick={() => setCount(count + 100)}>+</button>

            <hr/>
            <div>
                <h2>Today you've taken { steps } steps!</h2>
                <button onClick={increment}>I took another step</button>
            </div>

            <hr/>
            <button onClick={() => { setHidden(preState => !preState)}}>
                Click to see me
            </button>
            {
                hidden ? <h2>haha</h2> : null
            }
        </div>
    );

    function increment() {
        setSteps(preState => preState + 1)
    }
}
export default StateHook;

https://codesandbox.io/s/react-new?file=/src/App.js

Screenshot 2023-05-11 at 17.11.23

1.2 useEffect Hook

import React, {useState, useEffect} from 'react';

function EffectHook(props) {
    const [count, setCount] = useState(0);
    const [hidden, setHidden] = useState(false);
    const [steps, setSteps] = useState(0);


    useEffect(() => {
         setTimeout( () => { setCount(preState => preState + 10) }, 1000);
    }, [])

    return (
        <div>
            <h1>Clicked { count } times!!</h1>
            <button onClick={() => setCount(count + 100)}>+</button>

            <hr/>
            <div>
                <h2>Today you've taken { steps } steps!</h2>
                <button onClick={increment}>I took another step</button>
            </div>

            <hr/>
            <button onClick={() => { setHidden(preState => !preState)}}>
                Click to see me
            </button>
        </div>
    );

    function increment() {
        setSteps(preState => preState + 1)
    }
}
export default EffectHook;

Screenshot 2023-05-11 at 17.13.17