react实例与总结(一)

目录

一、简单认识

1.1、特点

1.2、JSX语法规则

1.3、函数组件和类式组件

1.4、类组件三大属性state、props、refs

1.4.1、state

1.4.2、props

1.4.3、refs

1.5、事件处理

1.6、收集表单数据---非受控组件和受控组件

1.7、高阶函数---函数柯里化

1.8、生命周期---新旧对比

1.8.1、旧16+

1.8.2、新17+

1.8.3、对比

1.9、DOM的Diffing算法

二、脚手架搭建

2.1、创建项目

因为真实DOM频繁操作节点会导致页面重绘和重排,影响性能,所以会用虚拟DOM【应用于前端框架】进行跨平台开发

一、简单认识

英文:Getting Started -- React

中文:快速入门 -- React 中文文档

1.1、特点

(1)采用组件化模式、声明式编码,提高开发效率及组件复用率

(2)在React Native中使用它进行移动端开发

(3)使用虚拟DOM+Diffing算法,减少与真实DOM的交互

1.2、JSX语法规则

(1)、定义虚拟DOM时,不要写引号

(2)、标签中混入js表达式时要用{}

(3)、样式的类名指定不要用class,要用className

(4)、内联样式:要用**style={{key:value}}**形式

(5)、只有一个根标签,所有标签必须闭合

(6)、标签首字母

若小写字母开头,则将该标签转为html中同名元素;若html中没有该标签对应的同名元素,则报错

若大写字母开头,则react去找对应的组件,若找不到,则报错

在Microsoft Edge安装React Developer Tools扩展进行开发辅助,以下语法基于**16+**版本。

1.3、函数组件和类式组件

前者适用于简单组件(只能使用props属性,除非使用Hooks里的useRef 和 useState ),后者适用于复杂组件

html 复制代码
    <div id="root"></div>
    <script type="text/babel">
      // 1.创建函数式组件
      function MyComponent() {
        return <h1>我是函数式组件</h1>;
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("root"));
    </script>
javascript 复制代码
      // 1.创建类式组件
      class MyComponent extends React.Component {
        render() {
          //  render()中的this 指向当前组件实例
          return <h1>我是类式组件</h1>;
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("root"));

1.4、类组件三大属性state、props、refs

注意:类组件里的render()会调用1+N次(只要state更新就变)

1.4.1、state

javascript 复制代码
      class MyMood extends React.Component {
        state = {
          isGood: false,
          number: 0,
        };
        render() {
          const { isGood, number } = this.state;
          return (
            <div>
              <h1 onClick={this.changeMyMood}>
                今天心情很{isGood ? "好" : "糟糕"}
              </h1>
              <h1 onClick={() => this.setState({ number: 10 })}>
                打个{number}分
              </h1>
            </div>
          );
        }
        changeMyMood = () => {
          this.setState({
            isGood: !this.state.isGood,
          });
        };
      }
      ReactDOM.render(<MyMood />, document.getElementById("root"));

总结:

(1)、状态必须通过setState进行更新,且更新是一种合并,不是替换;

(2)、组件中render()方法中的this为组件实例对象,当this为undefined,如何解决?

a. 通过函数对象的**bind()**强制绑定this;b.箭头函数

1.4.2、props

html 复制代码
<div id="root1"></div>
<div id="root2"></div>
<div id="root3"></div>
    <script type="text/babel">
      class Person extends React.Component {
      // 使用 PropTypes 进行类型检查
      static propTypes = {
        name: PropTypes.string.isRequired,//必传项
        sex: PropTypes.string,
        age: PropTypes.number,
        onSuccess: PropTypes.func
      };
      // 设置默认属性
      static defaultProps = {
        age: 18,
        sex: "男"
      };
      render() {
          const { name, age, sex } = this.props;
          return (
            <ul>
              <li>姓名:{name}</li>
              <li>性别:{sex}</li>
              <li>年龄:{age + 1}</li>
            </ul>
          );
        }
      }
ReactDOM.render(<Person name="tom" age={18} sex="男" onSuccess={onSuccess}/>, document.getElementById("root1"));
      // 批量传递 props 【{...x}】
      const backData = { name: '后端返回数据', age: 19, sex: "女" }; 
ReactDOM.render(<Person {...backData} />, document.getElementById("root2"));
ReactDOM.render(<Person name="jack" age={20}/>, document.getElementById("root3"));
      function onSuccess() {
        console.log('执行事件');
      }
    </script>

函数组件Props

javascript 复制代码
      function Person(props) {
        const { name, age, sex } = props;
        return (
          <ul>
            <li>姓名:{name}</li>
            <li>性别:{sex}</li>
            <li>年龄:{age + 1}</li>
          </ul>
        );
      }
      Person.propTypes = {
        name: PropTypes.string.isRequired, 
        sex: PropTypes.string,
        age: PropTypes.number,
      };
ReactDOM.render(<Person name='tom' age={18} sex="男" />, document.getElementById("root"));

总结:

(1)、组件标签的所有属性都保存在props中,但是组件内部不要修改props数据;

(2)、批量传递:{...item}、类型检查:PropTypes、默认属性:defaultProps

1.4.3、refs

javascript 复制代码
class MyComponent extends React.Component {
        showData = () => {
          const { input1 } = this.refs;
          alert(input1.value);
        };
        showData2 = () => {
          const { input2 } = this;
          alert(input2.value);
        };
        myRef=React.createRef();
        showData3 = () => {
          alert(this.myRef.current.value);
        };
render() {
          return (
            <div>
              {/* 1、字符串形式 */}
              <input ref="input1" type="text" placeholder="点击按钮提示数据" />
              &nbsp;
              <button onClick={this.showData}>点击提示左侧数据</button>&nbsp;
              {/* 2、回调函数形式 */}
              <input
                ref={(c) => (this.input2 = c)}
                onBlur={this.showData2}
                type="text"
                placeholder="失去焦点提示数据"
              />&nbsp;
              {/* 3、createRef API:存储被ref标识的节点,"专人专用" */}
              <input
                ref={this.myRef}
                onBlur={this.showData3}
                type="text"
                placeholder="createRef的使用"
              />
            </div>
          );
        }
}
ReactDOM.render(<MyComponent />, document.getElementById("root"));

总结:

(1)、直接访问和操作DOM元素或React组件实例;

(2)、使用React.createRef() 或者回调函数形式(类组件);使用**useRef**(函数组件)

1.5、事件处理

总结:

(1)、通过onXxx属性指定事件处理函数,事件通过事件委托【委托给组件最外层的元素】处理的;

(2)、通过event.target得到发生事件的DOM元素对象【高效】;

(3)、原生Js事件使用onclick,而React事件使用onClick【为了更好的兼容性】。

1.6、收集表单数据---非受控组件和受控组件

特性 受控组件 (Controlled) 非受控组件 (Uncontrolled)
值存储位置 存储在React组件的state 存储在DOM中(使用ref访问)
表单元素控制 React通过state控制表单的值 浏览器控制,React不干涉
更新方式 用户输入时通过onChange更新state 使用**ref获取值**,无需触发事件
适用场景 需要表单验证、交互或复杂逻辑时 简单表单,且无需与React状态紧密交互
代码复杂度 稍微复杂,需要维护状态和事件处理 简单,直接使用ref访问DOM

1.7、高阶函数---函数柯里化

总结:

高阶函数 :如果函数的参数或者返回值是函数,那么这个函数就是高阶函数。

常见有:Promise、setTimeout、arr.map()、call、apply、bind、...

函数柯里化 :通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的一种函数编码形式。·

或者:直接在视图上使用箭头函数,同时传入属性值和对应的event。

1.8、生命周期---新旧对比

1.8.1、旧16+

javascript 复制代码
  <script type="text/babel">
    class MyComponent extends React.Component {
      constructor(props) {
        console.log("构造器---constructor");
        super(props);
        this.state = { count: 0 };
      }
      componentWillMount() {
        console.log("组件将要挂载---componentWillMount");
      }
      componentDidMount() {
        console.log("组件挂载完毕---componentDidMount");
      }
      shouldComponentUpdate(nextProps, nextState) {
        console.log("组件是否需要更新---shouldComponentUpdate");
        return true;
      }
      componentWillUpdate() {
        console.log("组件将要更新---componentWillUpdate");
      }
      componentDidUpdate() {
        console.log("组件更新完毕---componentDidUpdate");
      }
      componentWillUnmount() {
        console.log("组件即将卸载---componentWillUnmount");
      }
      moveIt = () => {
        ReactDOM.unmountComponentAtNode(document.getElementById("root")); //卸载
      };
      addIt = () => {
        const { count } = this.state;
        this.setState({ count: count + 1 });
      };
      forceIt = () => {
        this.forceUpdate();
      };
      render() {
        console.log("挂载页面---render");
        const { count } = this.state;
        return (
          <div>
            <h2>当前求和为:{count}</h2>
            <button onClick={this.addIt}>点击+1</button>
            <button onClick={this.moveIt}>销毁</button>
            <button onClick={this.forceIt}>强制更新</button>
          </div>
        );
      }
    }
    // A和B是父子关系
    class A extends React.Component {
      state = { carName: '奔驰' };
      changeCar = () => {
        this.setState({ carName: '宝马' });
      };
      render() {
        return (
          <div>
            <div>A页面</div>
            <button onClick={this.changeCar}>换车</button>
            <B carName={this.state.carName} />
          </div>
        );
      }
    }
    class B extends React.Component {
      componentWillReceiveProps(nextProps) {
        console.log('B组件接收到新的属性(第一次不调)', nextProps);
      }
      render() {
        return <div>B组件接收的车是:{this.props.carName}</div>;
      }
    }
    // ReactDOM.render(<MyComponent />, document.getElementById("root"));
    ReactDOM.render(<A />, document.getElementById("root"));
  </script>

1.8.2、新17+

javascript 复制代码
    static getDerivedStateFromProps(props,state) {
        console.log("获取新的属性---getDerivedStateFromProps",props,state);
        return null;//返回null或者props
      }
    ReactDOM.render(<MyComponent count={199} />, document.getElementById("root"));
javascript 复制代码
<style>
    .list {
      width: 200px;
      height: 150px;
      background-color: skyblue;
      overflow: auto;
    }
    .news {
      height: 30px;
</style>
class MyComponent extends React.Component {
      state = { newArr: [] }
      componentDidMount() {
        setInterval(() => {
          const { newArr } = this.state
          const news = '新闻' + (newArr.length + 1)
          this.setState({ newArr: [news, ...newArr] })
        }, 1000);
      }
      getSnapshotBeforeUpdate(prevProps, prevState) {
        return this.refs.list.scrollHeight;// 获取更新前的DOM节点
      }
      componentDidUpdate(prevProps, prevState, snapshot) {
        this.refs.list.scrollTop += this.refs.list.scrollHeight - snapshot;
      }
      render() {
        return <div className="list" ref="list">
          {
            this.state.newArr.map((item, index) => {
              return <div className="news" key={index}>{item}</div>
            })
          }</div>;
      }
}

1.8.3、对比

17+在16+的基础上新增了getDerivedStateFromProps、getSnapshotBeforeUpdate;

即将废弃 componentWillMount、componentWillReceiveProps、componentWillUpdate三个钩子。

1.9、DOM的Diffing算法

经典面试题:为啥key不能使用index,而是取id(唯一标识)

总结:

1、使用 index 作为 key

在列表项的顺序发生变化、增加或删除时,可能会导致错误渲染或状态丢失

适用于列表项不变,且不涉及删除、增加或排序操作的简单情况。

2、使用id 作为 key

更稳定,能够确保元素在更新时保持一致,特别是在列表顺序发生变化时。

尤其是在动态数据列表(增、删、改、排序等操作)中使用。

二、脚手架搭建

2.1、创建项目

1、全局安装:npm i -g create-react-app【查看是否下载create-react-app --version

2、切换到想创建项目的目录下:create-react-app react_app【Node版本在**14+**及以上】

3、进入项目文件夹:cd react_app

4、启动项目:npm start【修改package.json,重新下载node_modules、 package-lock.json来修改版本

或者直接用:React--Umi和Dva_react dva-CSDN博客

相关推荐
Lanwarf-前端开发7 分钟前
gis风场加载
开发语言·前端·javascript
海上彼尚12 分钟前
ModuleJS 与 CommonJS 混用的两种解决方案
javascript·node.js
吃蛋糕的居居12 分钟前
疯狂前端面试题(四)
前端·javascript·chrome·ajax·正则表达式·firefox·html5
Lovely Ruby1 小时前
【ThreeJS Basics 1-3】Hello ThreeJS,实现第一个场景
javascript
前端加油站1 小时前
高级前端成长之路必看前端请求
前端·vue.js·react.js
lixww.cn2 小时前
ASP.NET Core SignalR向部分客户端发消息
javascript·websocket·vue·asp.net core·signalr
四十aaa3 小时前
前端监控SDK:从基础到实践 (3. 行为监控)
前端·javascript·监控
gqkmiss3 小时前
React Vite 项目增加 eslint 和 prettier
javascript·react.js·ecmascript·eslint·prettier
打野赵怀真4 小时前
css中的fill有什么应用场景?
前端·javascript
ETO_冬4 小时前
Fastadmin根据链接参数显示不同列表格
javascript·php·thinkphp·fastadmin