React初体验

110 阅读4分钟

1. 引入React

  1. CDN引入(一般不用,了解即可)
<div id="app"></div>

<script src="https://cdn.bootcss.com/react/16.10.2/umd/react.development.js"></script>

<script src="https://cdn.bootcss.com/react-dom/16.10.2/umd/react-dom.development.js"></script>
<script src="src/index.js"></script>

本地则项目可以用parcel运行

cjs和umd的区别:

cjs全称是CommonJS,时Node.js支持的模块规范
umd是统一的模块定义,兼容各种模块规范(含浏览器)
理论上是优先使用umd,同时支持Node.js和浏览器
最新的模块规范使用import和export关键字

  1. 通过webpack引入(一般不用)
yarn add react react-dom
import React from 'react'    // 变量大写
import ReactDom from 'react-dom'

注意大小写

  1. 新手用create-react-app,老手自己配webpack/rollup
// 方法一:
yarn global add create-react-app
create-react-app react-demo
// 根据提示符继续操作

// 方法二:打开官网看文档最新使用方法npx

React实现n+1(很麻烦)

失败的案例:

const React = window.React;
const ReactDOM = window.ReactDOM;
const root = document.querySelector("#root");

let n = 0;
const App = React.createElement("div", { className: "red" }, [
    n,
    React.createElement(
        "button",
        {
            onClick: () => {
            n += 1;
        }
    },
    "+1"
    )
]);

ReactDOM.render(App, root);

为什么点击按钮数字未发生变化?

因为App=React.create...只执行了一次

如何让他重新执行以获取n的最新值?想想6个6案例

经典面试题之6个6

  • 打印6个6
let i;
for(i=0; i<6; i++){
    setTimrout(()=>{console.log(i)}, 1000)
}

解释:当 i=0 时,setTimeout说我一会就执行;i=1 时,还说我一会再执行。。。一直到 i=5 时,他还说我一会就执行,i++=6,这时候setTimeout要执行了,每隔一秒打印i,循环了6次 6个6.png

  • 打印0-5
  1. 语法糖:js为了方便小白使用遍历0-5而创造的方法
for(let i=0; i<6; i++){
    setTimeout(()=>{console.log(i)}, 1000)
}

当你这样写的时候就相当于如下写法:这样保证了每次循环内部j的值与setTime函数保持同步(不要用var因为他会让作用域跑到最外边)

for(i=0; i<6; i++){
    let j=0;
    setTimeout(()=>{console.log(j)}, 1000)
}

0-5.png 2. 立即执行函数:将后括号的实参复制给前括号的形参

forvar i; i<6; i++){
    !function(j){        // 加!是为了不让函数报错;j为形参可取任意变量
        setTimeout(()=>{console.log(i)}, 1000)
    }(i)
}

由上得出更新视图的方法:将App变为函数

const React = window.React;
const ReactDOM = window.ReactDOM;
let n = 0;

const App = () =>
React.createElement("div", null, [
    n,
    React.createElement(
        "button",
        {
            onClick: () => {
                n += 1;
                console.log(n); //这一句是精髓
                ReactDOM.render(App(), document.querySelector("#app")); 
            }
        },
        "+1"
    )
]);
ReactDOM.render(App(), document.querySelector("#app"));

函数本质:延迟

setTimeout(fn, 0) 含义:在0s后,尽快执行fn

普通代码let b=1+a会立即求出b的值

函数let f=()=>1+alet b=f会等调用时才求值(延迟求值),且求值时才会读取a的最新值

2. React元素和函数组件

App1 = React.createElement('div', null, n)    // 创建div标签,无className/id,内容为n  
App1 是一个React元素
App2 = ()=> React.createElement('div', null, n) 
App2 是一个React函数组件

即App2是延迟执行的代码,会在被调用时执行(同步异步关注的是得到结果的时机)

React元素:

虚拟DOM对象:createElement的返回值代表一个div,但不是真正的div这个element称为虚拟DOM

()=>React元素:

DOM Diff算法:该元素返回createElement的函数,也代表一个div。这个函数多次执行,每次执行得到最新的虚拟div。React对比两个虚拟div,找出不同来局部更新视图。找不同的算法叫DOM Diff

3. JSX用法

vue-loarder

.vue文件里使用<template><script><style>,通过vue-loader变成一个构造选项

JSX

webpack内置的babel-loader插件让我们可以使用jsx:将React.createElement('button',{onClick: add}, '+1')变成<button onClick="add">+1</button>

方法一:CDN(生产环境不要用,效率低,且不支持src)

该方法下载一个babel.min.js,利用它在浏览器端把jsx语法转译成js

<script src="https://cdn.bootcss.com/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
    <script type="text/babel">
      let n = 0;
      const App = () => (
        <div>
          {n}
          <button
            onClick={() => {
              n += 1;
              render();
            }}
          >
            +1
          </button>
        </div>
      );
      const render = () =>
        ReactDOM.render(<App />, document.querySelector("#app"));
      render();
    </script>

方法二:webpack+babel-loader(新手跳过)

方法三:使用create-react-app

yarn start后你会发现webpack让js默认走babel-loader,App.js默认使用了jsx语法

微信截图_20230623191000.png 微信截图_20230623191019.png

JSX注意事项

  1. 变量,函数,对象,标签里的JS代码用{}包起来;{}会解析成js,()会解析成HTML
  2. return要加(),否则他返回undefined
  3. 注意className:<div className="red">n</div>

eg:条件循环与判断

三目运算符判断

import React from "react";
const App = ()=> {
    return (
        <div>App组件
            <Component />
        </div>    // React.creatElement()
    )
}
const Component = ()=> {
    let n = 2;
    return n%2 === 0 ? <div>{n}是偶数</div> : <sapn>{n}是奇数</sapn>
}
export default App;

// 第11行可以放在变量里再返回
const Component = ()=> {
    let n = 2;
    const inner = n%2 === 0 ? <div>{n}是偶数</div> : <sapn>{n}是奇数</sapn>;
    const content = (
        <div>
            {inner}
        </div>     
    )
    return content;
}

条件判断式

const Component = ()=> {
    let n = 2;
    let inner;
    if(n%2===0){
        return inner = <div>{n}是偶数</div>;
    }else{
        return inner = <span>{n}是奇数</span>
    }
    const content = (
        <div>
            {inner}
        </div>
    )
    return content;
}

eg:循环语句

js内置函数遍历数组

const Component = (props)=> {
    return (<div>
       { props.numbers.map((n,index)=>{
             return <div>下标{index}值为{n}</div>
         })       
       }
    </div>)
}

for循环

import React from "react";
const App = ()=> {
    return (
        <div>App组件
            <Component numbers={[1,2,3]}/>
        </div>    // React.creatElement()
    )
}
const Component = (props)=> {
    const array=[];
    for(let i=0; i<props.numbers.length; i++){
        array.push(
            <div>{i}:{props.numbers[i]}</div>
        )
    }      
    return  <div>{array}</div> 
}
export default App;

其实这样写就行: uTools_1687585787476.png

总结:

微信截图_20230623192017.png