zoukankan      html  css  js  c++  java
  • React

    笔记来自
    github实例
    immutable的学习
    面试题
    手写实现react

    需要学的知识有

    • 脚手架安装启动
    • JSX组件基础使用,修改数据,for,if,事件...
    • JSX组件传参通信
    • 生命周期
    • 路由
    • Redux
    • React-Hooks
    • 打包发布
    • 首屏优化,Next服务器渲染

    安装脚手架

    • 普通的命令
    # 一个电脑安装一次就好
    cnpm install -g create-react-app
    # 创建项目
    create-react-app 【name】
    
    cnpm install
    npm start
    
    • 脚手架有什么
    // 自带了Ject测试插件
    // eslint代码规范检查
    // PWA功能的 manifest.json 和 serviceWorker.js 文件
    
    // 入口文件 index.js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    // 这是一个组件
    import App from './App';
    // import * as serviceWorker from './serviceWorker';
    
    // 这个就是jsx写法
    // 后面等引入了路由和redux后得修改,具体往下看
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    // PWA没用注释了
    // serviceWorker.unregister();
    

    脚手架设置

    • 跨域请求
    // 安装
    npm i http-proxy-middleware --save
    
    // 在src下创建setupProxy.js,名字固定
    const { createProxyMiddleware } = require('http-proxy-middleware');
    module.exports = function(app) {
        app.use('/api', 
            createProxyMiddleware({ 
                target: 'http://xxx.pdt1997.top/', 
                changeOrigin: true 
            })
        );
    }
    
    // axios安装设置查看【axios和fetch】笔记
    
    • 打包文件的配置查看【React打包配置】笔记

    基础使用

    • 组件的结构
    // vue是一个template+script+style组成的
    // 而react是一个js文件加一个css文件,建议创建一个文件夹装起来使用,再一起装进pages文件夹里比较规范
    
    // app.js
    import React from 'react';
    import logo from './logo.svg';
    import './App.css';
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>
              Edit <code>src/App.js</code> and save to reload.
            </p>
            <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learn React
            </a>
          </header>
        </div>
      );
    }
    
    // 上面的写法不规范,应该改成下面的写法
    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    
    // 这里面的一级属性都不需要逗号结束
    class App extends Component{
        // 这个就是vue的data
        state = {
            msg: "测试",
        }
        render(){
            return (
                <div className="App">
                    <header className="App-header">
                        <div>{this.state.msg}</div>
                        <img src={logo} className="App-logo" alt="logo" />
                        <p>
                            Edit <code>src/App.js</code> and save to reload.
                        </p>
                        <a
                            className="App-link"
                            href="https://reactjs.org"
                            target="_blank"
                            rel="noopener noreferrer"
                        >
                            Learn React
                        </a>
                    </header>
                </div>
            );
        }
    }
    
    export default App;
    
    • 修改数据,在react应该叫修改状态state
    // 不要直接修改 state(状态)
    // this.state.comment = 'Hello';
    // 上述代码并不会重新渲染组件,需要使用this.setState()代替:
    // 正确操作
    this.setState({
      comment: 'Hello'
    });
    
    //  state(状态) 更新可能是异步的
    // React 为了优化性能,有可能会将多个 setState() 调用合并为一次更新。
    // 因为this.props和this.state 可能是异步更新的,你不能依赖他们的值计算下一个state(状态)
    // this.setState({
      // counter: this.state.counter + this.props.increment,
    // });
     
    
    // 我们并不能通过上述代码得到想要的值
    // 为了弥补这个问题,使用另一种 setState() 的形式,接受一个函数
    // 这个函数将接收前一个状态作为第一个参数,应用更新时的 props 作为第二个参数,代码如下:
    this.setState((prevState, props) => ({
      counter: prevState.counter + props.increment
    }));
    
    • 事件绑定
    class Toggle extends React.Component {
      state = {
        isToggleOn: true,
      }
      // 一定要箭头函数,否则没有this
      handleClick = (e) => {
        // 这就是修改state方法
        this.setState({
          isToggleOn: !this.state.isToggleOn
        });
      }
      // event永远在最后一位参数
      handleClick2 = (msg,e) => {
        console.log(msg)
      }
      render() {
        return (
          <button onClick={this.handleClick('test')}>
            {this.state.isToggleOn ? 'ON' : 'OFF'}
          </button>
          // 如果要传参就得加上bind(this,参数)
          <button onClick={this.handleClick2.bind(this,'test')}>
            {this.state.isToggleOn ? 'ON' : 'OFF'}
          </button>
        );
      }
    }
    
    • 条件渲染
    // 三元
    render() {
      return (
        <div>
          { this.state.isLoggedIn ? (
            <LogoutButton onClick={this.handleLogoutClick} />
          ) : (
            <LoginButton onClick={this.handleLoginClick} />
          ) }
        </div>
      );
    }
    
    // 是否 &&
    render() {
      return (
        <div>
          <h1>Hello!</h1>
          { unreadMessages.length > 0 &&
            <h2>
              您有 {unreadMessages.length} 条未读信息。
            </h2>
          }
        </div>
      );
    }
    
    • 列表渲染
    render() {
      return (
        <div>
          { 
            this.state.selectedProList.map((item, index) => {
              return <li key={index} className="selected-pro-item ellipsis">{item.product_name}x{item.selectNum}</li>
            })
          }
        </div>
      );
    }
    

    JSX组件传参通信

    • 所有的数据和方法都在this.props对象里
    • 父传子
    // 父
    render(){
       return(
             <Child {...person} />
             <Child txt={this.state.message}/>
       )
    }
    // 子
    render(){
       return(
             <div>{this.props.name}</div>
             <div>{this.props.age}</div>
             <div>{this.props.message}</div>
       )
    }
    
    • 子传父,子组件调用父组件的方法进行数据的传递
    // 父
    getDatas(msg){
        //把子组件传递过来的值赋给this.state中的属性
        this.setState({
          mess: msg
        });
    }
    render(){
        return (
             <Son getdata={this.getDatas.bind(this)}></Son>
             <div>展示数据:{this.state.mess}</div>
        );
    }
    
    // 子
    handleClick(){
        //通过props属性获取父组件的getdata方法,并将this.state值传递过去
        this.props.getdata(this.state.inputValue);
    }
    render(){
        return (
            <button onClick={this.handleClick.bind(this)}>点击获取数据</button>
        );
    }
    
    • 兄弟,组件A传值父组件,父组件传值组件B,就是把上面的
    // 父
    getDatas(msg){
        //把子组件传递过来的值赋给this.state中的属性
        this.setState({
          mess: msg
        });
    }
    render(){
        return (
             <SonA getdata={this.getDatas.bind(this)} />
             <SonB mess={mess} />
        );
    }
    
    • 组件传值可以使用prop-type这个插件进行格式判断和默认值使用
    • 跟vue一样,数据之间的传递非常的麻烦,应该是用第三方的数据储存插件redux

    生命周期

    • 核心 constructor 》componentWillMount 》render 》componentDidMount
    class Button extends Component {
      state = { 
         data: 0 
      }
      setNewNumber() {
        this.setState({data: this.state.data + 1})
      }
      render() {
          return (
             <div>
                <button onClick = {this.setNewNumber.bind(this)}>INCREMENT</button>
                <Content myNumber = {this.state.data}></Content>
             </div>
          );
        }
    }
     
     
    class Content extends Component {
      componentWillMount() {
          // 在渲染前调用,在客户端也在服务端
          console.log('Component WILL MOUNT!')
      }
      componentDidMount() {
          //  在第一次渲染后调用,只在客户端
          //  初始化请求写在这
          //  为什么不写在componentWillMount 
          //  因为componentWillMount方法的调用在constructor之后,在render之前,在这方法里的代码调用setState方法不会触发重渲染,所以它一般不会用来作加载数据之用,它也很少被使用到
          console.log('Component DID MOUNT!')
      }
      componentWillReceiveProps(newProps) { 
          console.log('Component WILL RECEIVE PROPS!')
      }
      shouldComponentUpdate(newProps, newState) {
          // 这个是数据更新前会执行的方法,如果返回false,页面不会更新
          // 这个的用处特别的大,如果你在render里打印一下666,会发现每次数据更新实际都调用了无数次的render,非常的损耗性能
          // 当然必须要的不能阻止,如果是前后一样的数据应该避免render的更新,所以在这里可以对两个参数进行一致性判断,一样则返回false
          // 可是这个数据的判断就是深拷贝,深拷贝的性能也是非常的离谱,也不好完成
          // 所以在这里应该使用插件,也就是最上的那个immutable插件
          // 引用这个插件后,整个项目的数据都应该改用插件里使用的【List和Map和Set和其他】,按照他要求的方法进行数据变化
          // 具体自行学习
          return true;
      }
      componentWillUpdate(nextProps, nextState) {
           console.log('Component WILL UPDATE!');
      }
      componentDidUpdate(prevProps, prevState) {
           // 数据更新调用
           console.log('Component DID UPDATE!')
      }
      componentWillUnmount() {
           // 销毁前
           console.log('Component WILL UNMOUNT!')
      }
     
      render() {
         return (
            <div>
              <h3>{this.props.myNumber}</h3>
            </div>
         );
      }
    }
    
  • 相关阅读:
    背水一战 Windows 10 (61)
    背水一战 Windows 10 (60)
    背水一战 Windows 10 (59)
    背水一战 Windows 10 (58)
    背水一战 Windows 10 (57)
    背水一战 Windows 10 (56)
    背水一战 Windows 10 (55)
    背水一战 Windows 10 (54)
    背水一战 Windows 10 (53)
    背水一战 Windows 10 (52)
  • 原文地址:https://www.cnblogs.com/pengdt/p/13070740.html
Copyright © 2011-2022 走看看